aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-12-18 02:11:36 +0000
committerGravatar kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-12-18 02:11:36 +0000
commitfccb146e3fe437b0df1e9c50d4b8e1080ddb4bd9 (patch)
tree9f2d9fe0267d96a54e541377ffeada3d0bff0d1d
parentd5cf7b55a6a1f959d1646785f63ca2b62da78079 (diff)
Massive roll-up of changes. See CHANGES.txt.
-rw-r--r--CHANGES.txt46
-rw-r--r--Makefile.am6
-rwxr-xr-xautogen.sh10
-rwxr-xr-xgenerate_descriptor_proto.sh4
-rw-r--r--java/pom.xml1
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessage.java35
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessageLite.java28
-rw-r--r--java/src/main/java/com/google/protobuf/ByteString.java18
-rw-r--r--java/src/main/java/com/google/protobuf/CodedInputStream.java27
-rw-r--r--java/src/main/java/com/google/protobuf/Descriptors.java118
-rw-r--r--java/src/main/java/com/google/protobuf/ExtensionRegistry.java5
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessage.java4
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessageLite.java31
-rw-r--r--java/src/main/java/com/google/protobuf/Message.java4
-rw-r--r--java/src/main/java/com/google/protobuf/MessageLite.java8
-rw-r--r--java/src/main/java/com/google/protobuf/TextFormat.java2
-rw-r--r--java/src/main/java/com/google/protobuf/UnknownFieldSet.java20
-rw-r--r--java/src/main/java/com/google/protobuf/WireFormat.java18
-rw-r--r--java/src/test/java/com/google/protobuf/AbstractMessageTest.java38
-rw-r--r--java/src/test/java/com/google/protobuf/CodedInputStreamTest.java14
-rw-r--r--java/src/test/java/com/google/protobuf/DescriptorsTest.java51
-rw-r--r--java/src/test/java/com/google/protobuf/GeneratedMessageTest.java35
-rw-r--r--java/src/test/java/com/google/protobuf/ServiceTest.java47
-rw-r--r--java/src/test/java/com/google/protobuf/TestUtil.java92
-rw-r--r--java/src/test/java/com/google/protobuf/TextFormatTest.java22
-rw-r--r--java/src/test/java/com/google/protobuf/WireFormatTest.java3
-rwxr-xr-xpython/google/protobuf/descriptor.py211
-rwxr-xr-xpython/google/protobuf/internal/containers.py69
-rwxr-xr-xpython/google/protobuf/internal/decoder.py770
-rwxr-xr-xpython/google/protobuf/internal/decoder_test.py256
-rwxr-xr-xpython/google/protobuf/internal/descriptor_test.py227
-rwxr-xr-xpython/google/protobuf/internal/encoder.py888
-rwxr-xr-xpython/google/protobuf/internal/encoder_test.py286
-rwxr-xr-xpython/google/protobuf/internal/generator_test.py107
-rwxr-xr-xpython/google/protobuf/internal/input_stream.py338
-rwxr-xr-xpython/google/protobuf/internal/input_stream_test.py314
-rwxr-xr-xpython/google/protobuf/internal/message_listener.py41
-rwxr-xr-xpython/google/protobuf/internal/message_test.py42
-rwxr-xr-xpython/google/protobuf/internal/output_stream.py125
-rwxr-xr-xpython/google/protobuf/internal/output_stream_test.py178
-rwxr-xr-xpython/google/protobuf/internal/reflection_test.py354
-rwxr-xr-xpython/google/protobuf/internal/test_util.py467
-rwxr-xr-xpython/google/protobuf/internal/text_format_test.py25
-rwxr-xr-xpython/google/protobuf/internal/type_checkers.py127
-rwxr-xr-xpython/google/protobuf/internal/wire_format.py27
-rwxr-xr-xpython/google/protobuf/message.py11
-rwxr-xr-xpython/google/protobuf/reflection.py1487
-rwxr-xr-xpython/google/protobuf/text_format.py5
-rwxr-xr-xpython/setup.py11
-rw-r--r--src/Makefile.am29
-rw-r--r--src/google/protobuf/compiler/code_generator.cc9
-rw-r--r--src/google/protobuf/compiler/code_generator.h9
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc468
-rw-r--r--src/google/protobuf/compiler/command_line_interface.h65
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc576
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc11
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc14
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc71
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_extension.cc21
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.cc29
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.h6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc59
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc53
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h24
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc99
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc36
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.cc78
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc35
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc73
-rw-r--r--src/google/protobuf/compiler/java/java_enum.cc5
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.cc46
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.h3
-rw-r--r--src/google/protobuf/compiler/java/java_extension.cc3
-rw-r--r--src/google/protobuf/compiler/java/java_field.cc10
-rw-r--r--src/google/protobuf/compiler/java/java_field.h2
-rw-r--r--src/google/protobuf/compiler/java/java_file.cc40
-rw-r--r--src/google/protobuf/compiler/java/java_file.h5
-rw-r--r--src/google/protobuf/compiler/java/java_generator.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.cc43
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.h18
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc83
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.cc18
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.h2
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc46
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.h3
-rw-r--r--src/google/protobuf/compiler/main.cc1
-rw-r--r--src/google/protobuf/compiler/parser.cc11
-rw-r--r--src/google/protobuf/compiler/parser_unittest.cc6
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc227
-rw-r--r--src/google/protobuf/compiler/python/python_generator.h16
-rw-r--r--src/google/protobuf/descriptor.cc20
-rw-r--r--src/google/protobuf/descriptor.h23
-rw-r--r--src/google/protobuf/descriptor.pb.cc1327
-rw-r--r--src/google/protobuf/descriptor.pb.h637
-rw-r--r--src/google/protobuf/descriptor.proto22
-rw-r--r--src/google/protobuf/descriptor_database.cc30
-rw-r--r--src/google/protobuf/descriptor_database.h4
-rw-r--r--src/google/protobuf/descriptor_database_unittest.cc34
-rw-r--r--src/google/protobuf/descriptor_unittest.cc3
-rw-r--r--src/google/protobuf/dynamic_message.cc80
-rw-r--r--src/google/protobuf/dynamic_message.h27
-rw-r--r--src/google/protobuf/extension_set.cc304
-rw-r--r--src/google/protobuf/extension_set.h202
-rw-r--r--src/google/protobuf/extension_set_heavy.cc257
-rw-r--r--src/google/protobuf/extension_set_unittest.cc159
-rw-r--r--src/google/protobuf/generated_message_reflection.cc194
-rw-r--r--src/google/protobuf/generated_message_reflection.h17
-rw-r--r--src/google/protobuf/generated_message_util.cc9
-rw-r--r--src/google/protobuf/generated_message_util.h18
-rw-r--r--src/google/protobuf/io/coded_stream.cc379
-rw-r--r--src/google/protobuf/io/coded_stream.h347
-rw-r--r--src/google/protobuf/io/coded_stream_unittest.cc88
-rw-r--r--src/google/protobuf/io/gzip_stream.cc2
-rw-r--r--src/google/protobuf/io/printer.cc25
-rw-r--r--src/google/protobuf/io/printer.h19
-rw-r--r--src/google/protobuf/io/printer_unittest.cc69
-rw-r--r--src/google/protobuf/io/tokenizer.cc2
-rw-r--r--src/google/protobuf/io/tokenizer.h5
-rw-r--r--src/google/protobuf/io/tokenizer_unittest.cc6
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl.h9
-rw-r--r--src/google/protobuf/io/zero_copy_stream_unittest.cc3
-rw-r--r--src/google/protobuf/message.cc4
-rw-r--r--src/google/protobuf/message.h28
-rw-r--r--src/google/protobuf/message_lite.cc59
-rw-r--r--src/google/protobuf/repeated_field.cc12
-rw-r--r--src/google/protobuf/repeated_field.h273
-rw-r--r--src/google/protobuf/repeated_field_unittest.cc214
-rw-r--r--src/google/protobuf/stubs/common.h31
-rw-r--r--src/google/protobuf/stubs/strutil.cc34
-rw-r--r--src/google/protobuf/stubs/strutil.h8
-rw-r--r--src/google/protobuf/test_util.cc88
-rw-r--r--src/google/protobuf/test_util.h3
-rw-r--r--src/google/protobuf/testing/file.cc13
-rw-r--r--src/google/protobuf/text_format.cc156
-rw-r--r--src/google/protobuf/text_format.h35
-rw-r--r--src/google/protobuf/text_format_unittest.cc83
-rw-r--r--src/google/protobuf/unittest.proto93
-rw-r--r--src/google/protobuf/unittest_enormous_descriptor.proto1
-rw-r--r--src/google/protobuf/unknown_field_set.cc12
-rw-r--r--src/google/protobuf/unknown_field_set.h10
-rw-r--r--src/google/protobuf/wire_format.cc185
-rw-r--r--src/google/protobuf/wire_format_lite.cc175
-rw-r--r--src/google/protobuf/wire_format_lite.h156
-rw-r--r--src/google/protobuf/wire_format_lite_inl.h366
-rw-r--r--src/google/protobuf/wire_format_unittest.cc71
-rw-r--r--vsprojects/libprotobuf-lite.vcproj540
-rw-r--r--vsprojects/libprotobuf.vcproj860
-rw-r--r--vsprojects/lite-test.vcproj546
-rw-r--r--vsprojects/protobuf.sln160
-rw-r--r--vsprojects/tests.vcproj1146
153 files changed, 11619 insertions, 7474 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 34ba7367..02ce55cd 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,49 @@
+2009-12-17 version 2.3.0:
+
+ General
+ * Parsers for repeated numeric fields now always accept both packed and
+ unpacked input. The [packed=true] option only affects serializers.
+ Therefore, it is possible to switch a field to packed format without
+ breaking backwards-compatibility -- as long as all parties are using
+ protobuf 2.3.0 or above, at least.
+ * The generic RPC service code generated by the C++, Java, and Python
+ generators can be disabled via file options:
+ option cc_generic_services = false;
+ option java_generic_services = false;
+ option py_generic_services = false;
+ This allows plugins to generate alternative code, possibly specific to some
+ particular RPC implementation.
+
+ protoc
+ * Now supports a plugin system for code generators. Plugins can generate
+ code for new languages or inject additional code into the output of other
+ code generators. Plugins are just binaries which accept a protocol buffer
+ on stdin and write a protocol buffer to stdout, so they may be written in
+ any language. See src/google/protobuf/compiler/plugin.proto.
+ * inf, -inf, and nan can now be used as default values for float and double
+ fields.
+
+ C++
+ * Various speed and code size optimizations.
+ * DynamicMessageFactory is now fully thread-safe.
+ * Message::Utf8DebugString() method is like DebugString() but avoids escaping
+ UTF-8 bytes.
+ * Compiled-in message types can now contain dynamic extensions, through use
+ of CodedInputStream::SetExtensionRegistry().
+
+ Java
+ * parseDelimitedFrom() and mergeDelimitedFrom() now detect EOF and return
+ false/null instead of throwing an exception.
+ * Fixed some initialization ordering bugs.
+ * Fixes for OpenJDK 7.
+
+ Python
+ * 10-25 times faster than 2.2.0, still pure-Python.
+ * Calling a mutating method on a sub-message always instantiates the message
+ in its parent even if the mutating method doesn't actually mutate anything
+ (e.g. parsing from an empty string).
+ * Expanded descriptors a bit.
+
2009-08-11 version 2.2.0:
C++
diff --git a/Makefile.am b/Makefile.am
index c311fe02..fbd36c1a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -114,18 +114,12 @@ EXTRA_DIST = \
python/google/protobuf/internal/generator_test.py \
python/google/protobuf/internal/containers.py \
python/google/protobuf/internal/decoder.py \
- python/google/protobuf/internal/decoder_test.py \
python/google/protobuf/internal/descriptor_test.py \
python/google/protobuf/internal/encoder.py \
- python/google/protobuf/internal/encoder_test.py \
- 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 \
- python/google/protobuf/internal/output_stream_test.py \
python/google/protobuf/internal/reflection_test.py \
python/google/protobuf/internal/service_reflection_test.py \
python/google/protobuf/internal/test_util.py \
diff --git a/autogen.sh b/autogen.sh
index 519bb8f3..04d65b16 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -4,6 +4,8 @@
# be included in the distribution. These files are not checked in because they
# are automatically generated.
+set -e
+
# Check that we're being run from the right directory.
if test ! -f src/google/protobuf/stubs/common.h; then
cat >&2 << __EOF__
@@ -13,6 +15,14 @@ __EOF__
exit 1
fi
+# Check that gtest is present. Usually it is already there since the
+# directory is set up as an SVN external.
+if test ! -e gtest; then
+ echo "Google Test not present. Fetching gtest-1.3.0 from the web..."
+ curl http://googletest.googlecode.com/files/gtest-1.3.0.tar.bz2 | tar jx
+ mv gtest-1.3.0 gtest
+fi
+
set -ex
# Temporary hack: Must change C runtime library to "multi-threaded DLL",
diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh
index 69dd7dae..07219dc1 100755
--- a/generate_descriptor_proto.sh
+++ b/generate_descriptor_proto.sh
@@ -27,5 +27,7 @@ __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 && \
+ ./protoc --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:. google/protobuf/compiler/plugin.proto
cd ..
diff --git a/java/pom.xml b/java/pom.xml
index 849ef5da..307bc0b7 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -113,6 +113,7 @@
<arg value="../src/google/protobuf/unittest_import_lite.proto" />
<arg value="../src/google/protobuf/unittest_lite_imports_nonlite.proto" />
<arg value="../src/google/protobuf/unittest_enormous_descriptor.proto" />
+ <arg value="../src/google/protobuf/unittest_no_generic_services.proto" />
</exec>
</tasks>
<testSourceRoot>target/generated-test-sources</testSourceRoot>
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java
index e5bdefe3..b059bc98 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -311,6 +311,12 @@ public abstract class AbstractMessage extends AbstractMessageLite
} else {
field = extension.descriptor;
defaultInstance = extension.defaultInstance;
+ if (defaultInstance == null &&
+ field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ throw new IllegalStateException(
+ "Message-typed extension lacked default instance: " +
+ field.getFullName());
+ }
}
} else {
field = null;
@@ -319,15 +325,28 @@ public abstract class AbstractMessage extends AbstractMessageLite
field = type.findFieldByNumber(fieldNumber);
}
- if (field == null || wireType !=
- FieldSet.getWireFormatForFieldType(
- field.getLiteType(),
- field.getOptions().getPacked())) {
- // Unknown field or wrong wire type. Skip.
+ boolean unknown = false;
+ boolean packed = false;
+ if (field == null) {
+ unknown = true; // Unknown field.
+ } else if (wireType == FieldSet.getWireFormatForFieldType(
+ field.getLiteType(),
+ false /* isPacked */)) {
+ packed = false;
+ } else if (field.isPackable() &&
+ wireType == FieldSet.getWireFormatForFieldType(
+ field.getLiteType(),
+ true /* isPacked */)) {
+ packed = true;
+ } else {
+ unknown = true; // Unknown wire type.
+ }
+
+ if (unknown) { // Unknown field or wrong wire type. Skip.
return unknownFields.mergeFieldFrom(tag, input);
}
- if (field.getOptions().getPacked()) {
+ if (packed) {
final int length = input.readRawVarint32();
final int limit = input.pushLimit(length);
if (field.getLiteType() == WireFormat.FieldType.ENUM) {
@@ -673,13 +692,13 @@ public abstract class AbstractMessage extends AbstractMessageLite
}
@Override
- public BuilderType mergeDelimitedFrom(final InputStream input)
+ public boolean mergeDelimitedFrom(final InputStream input)
throws IOException {
return super.mergeDelimitedFrom(input);
}
@Override
- public BuilderType mergeDelimitedFrom(
+ public boolean mergeDelimitedFrom(
final InputStream input,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
index 86bf02d8..9210d853 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -86,7 +86,7 @@ public abstract class AbstractMessageLite implements MessageLite {
CodedOutputStream.computeRawVarint32Size(serialized) + serialized);
final CodedOutputStream codedOutput =
CodedOutputStream.newInstance(output, bufferSize);
- codedOutput.writeRawVarint32(getSerializedSize());
+ codedOutput.writeRawVarint32(serialized);
writeTo(codedOutput);
codedOutput.flush();
}
@@ -105,13 +105,7 @@ public abstract class AbstractMessageLite implements MessageLite {
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);
+ return mergeFrom(input, ExtensionRegistryLite.getEmptyRegistry());
}
// Re-defined here for return type covariance.
@@ -275,20 +269,24 @@ public abstract class AbstractMessageLite implements MessageLite {
}
}
- public BuilderType mergeDelimitedFrom(
+ public boolean mergeDelimitedFrom(
final InputStream input,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
- final int size = CodedInputStream.readRawVarint32(input);
+ final int firstByte = input.read();
+ if (firstByte == -1) {
+ return false;
+ }
+ final int size = CodedInputStream.readRawVarint32(firstByte, input);
final InputStream limitedInput = new LimitedInputStream(input, size);
- return mergeFrom(limitedInput, extensionRegistry);
+ mergeFrom(limitedInput, extensionRegistry);
+ return true;
}
- public BuilderType mergeDelimitedFrom(final InputStream input)
+ public boolean mergeDelimitedFrom(final InputStream input)
throws IOException {
- final int size = CodedInputStream.readRawVarint32(input);
- final InputStream limitedInput = new LimitedInputStream(input, size);
- return mergeFrom(limitedInput);
+ return mergeDelimitedFrom(input,
+ ExtensionRegistryLite.getEmptyRegistry());
}
/**
diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java
index c83c335c..c043df8b 100644
--- a/java/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/src/main/java/com/google/protobuf/ByteString.java
@@ -99,6 +99,24 @@ public final class ByteString {
}
/**
+ * Copies {@code size} bytes from a {@code java.nio.ByteBuffer} into
+ * a {@code ByteString}.
+ */
+ public static ByteString copyFrom(final ByteBuffer bytes, final int size) {
+ final byte[] copy = new byte[size];
+ bytes.get(copy);
+ return new ByteString(copy);
+ }
+
+ /**
+ * Copies the remaining bytes from a {@code java.nio.ByteBuffer} into
+ * a {@code ByteString}.
+ */
+ public static ByteString copyFrom(final ByteBuffer bytes) {
+ return copyFrom(bytes, bytes.remaining());
+ }
+
+ /**
* Encodes {@code text} into a sequence of bytes using the named charset
* and returns the result as a {@code ByteString}.
*/
diff --git a/java/src/main/java/com/google/protobuf/CodedInputStream.java b/java/src/main/java/com/google/protobuf/CodedInputStream.java
index f339c00e..f0c1051d 100644
--- a/java/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -84,8 +84,9 @@ public final class CodedInputStream {
}
lastTag = readRawVarint32();
- if (lastTag == 0) {
- // If we actually read zero, that's not a valid tag.
+ if (WireFormat.getTagFieldNumber(lastTag) == 0) {
+ // If we actually read zero (or any tag number corresponding to field
+ // number zero), that's not a valid tag.
throw InvalidProtocolBufferException.invalidTag();
}
return lastTag;
@@ -355,8 +356,26 @@ public final class CodedInputStream {
* CodedInputStream buffers its input.
*/
static int readRawVarint32(final InputStream input) throws IOException {
- int result = 0;
- int offset = 0;
+ final int firstByte = input.read();
+ if (firstByte == -1) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return readRawVarint32(firstByte, input);
+ }
+
+ /**
+ * Like {@link #readRawVarint32(InputStream)}, but expects that the caller
+ * has already read one byte. This allows the caller to determine if EOF
+ * has been reached before attempting to read.
+ */
+ static int readRawVarint32(final int firstByte,
+ final InputStream input) throws IOException {
+ if ((firstByte & 0x80) == 0) {
+ return firstByte;
+ }
+
+ int result = firstByte & 0x7f;
+ int offset = 7;
for (; offset < 32; offset += 7) {
final int b = input.read();
if (b == -1) {
diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java
index 0c162d5d..c5e9a04b 100644
--- a/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -48,7 +48,7 @@ import java.io.UnsupportedEncodingException;
* (given a message object of the type) {@code message.getDescriptorForType()}.
*
* Descriptors are built from DescriptorProtos, as defined in
- * {@code net/proto2/proto/descriptor.proto}.
+ * {@code google/protobuf/descriptor.proto}.
*
* @author kenton@google.com Kenton Varda
*/
@@ -699,6 +699,11 @@ public final class Descriptors {
return getOptions().getPacked();
}
+ /** Can this field be packed? i.e. is it a repeated primitive field? */
+ public boolean isPackable() {
+ return isRepeated() && getLiteType().isPackable();
+ }
+
/** Returns true if the field had an explicitly-defined default value. */
public boolean hasDefaultValue() { return proto.hasDefaultValue(); }
@@ -810,39 +815,34 @@ public final class Descriptors {
private Object defaultValue;
public enum Type {
- DOUBLE (FieldDescriptorProto.Type.TYPE_DOUBLE , JavaType.DOUBLE ),
- FLOAT (FieldDescriptorProto.Type.TYPE_FLOAT , JavaType.FLOAT ),
- INT64 (FieldDescriptorProto.Type.TYPE_INT64 , JavaType.LONG ),
- UINT64 (FieldDescriptorProto.Type.TYPE_UINT64 , JavaType.LONG ),
- INT32 (FieldDescriptorProto.Type.TYPE_INT32 , JavaType.INT ),
- FIXED64 (FieldDescriptorProto.Type.TYPE_FIXED64 , JavaType.LONG ),
- FIXED32 (FieldDescriptorProto.Type.TYPE_FIXED32 , JavaType.INT ),
- BOOL (FieldDescriptorProto.Type.TYPE_BOOL , JavaType.BOOLEAN ),
- STRING (FieldDescriptorProto.Type.TYPE_STRING , JavaType.STRING ),
- GROUP (FieldDescriptorProto.Type.TYPE_GROUP , JavaType.MESSAGE ),
- MESSAGE (FieldDescriptorProto.Type.TYPE_MESSAGE , JavaType.MESSAGE ),
- BYTES (FieldDescriptorProto.Type.TYPE_BYTES , JavaType.BYTE_STRING),
- UINT32 (FieldDescriptorProto.Type.TYPE_UINT32 , JavaType.INT ),
- ENUM (FieldDescriptorProto.Type.TYPE_ENUM , JavaType.ENUM ),
- SFIXED32(FieldDescriptorProto.Type.TYPE_SFIXED32, JavaType.INT ),
- SFIXED64(FieldDescriptorProto.Type.TYPE_SFIXED64, JavaType.LONG ),
- SINT32 (FieldDescriptorProto.Type.TYPE_SINT32 , JavaType.INT ),
- SINT64 (FieldDescriptorProto.Type.TYPE_SINT64 , JavaType.LONG );
-
- Type(final FieldDescriptorProto.Type proto, final JavaType javaType) {
- this.proto = proto;
+ DOUBLE (JavaType.DOUBLE ),
+ FLOAT (JavaType.FLOAT ),
+ INT64 (JavaType.LONG ),
+ UINT64 (JavaType.LONG ),
+ INT32 (JavaType.INT ),
+ FIXED64 (JavaType.LONG ),
+ FIXED32 (JavaType.INT ),
+ BOOL (JavaType.BOOLEAN ),
+ STRING (JavaType.STRING ),
+ GROUP (JavaType.MESSAGE ),
+ MESSAGE (JavaType.MESSAGE ),
+ BYTES (JavaType.BYTE_STRING),
+ UINT32 (JavaType.INT ),
+ ENUM (JavaType.ENUM ),
+ SFIXED32(JavaType.INT ),
+ SFIXED64(JavaType.LONG ),
+ SINT32 (JavaType.INT ),
+ SINT64 (JavaType.LONG );
+
+ Type(final JavaType javaType) {
this.javaType = javaType;
-
- if (ordinal() != proto.getNumber() - 1) {
- throw new RuntimeException(
- "descriptor.proto changed but Desrciptors.java wasn't updated.");
- }
}
- private FieldDescriptorProto.Type proto;
private JavaType javaType;
- public FieldDescriptorProto.Type toProto() { return proto; }
+ public FieldDescriptorProto.Type toProto() {
+ return FieldDescriptorProto.Type.valueOf(ordinal() + 1);
+ }
public JavaType getJavaType() { return javaType; }
public static Type valueOf(final FieldDescriptorProto.Type type) {
@@ -902,16 +902,10 @@ public final class Descriptors {
}
// Only repeated primitive fields may be packed.
- if (proto.getOptions().getPacked()) {
- if (proto.getLabel() != FieldDescriptorProto.Label.LABEL_REPEATED ||
- proto.getType() == FieldDescriptorProto.Type.TYPE_STRING ||
- proto.getType() == FieldDescriptorProto.Type.TYPE_GROUP ||
- proto.getType() == FieldDescriptorProto.Type.TYPE_MESSAGE ||
- proto.getType() == FieldDescriptorProto.Type.TYPE_BYTES) {
- throw new DescriptorValidationException(this,
- "[packed = true] can only be specified for repeated primitive " +
- "fields.");
- }
+ if (proto.getOptions().getPacked() && !isPackable()) {
+ throw new DescriptorValidationException(this,
+ "[packed = true] can only be specified for repeated primitive " +
+ "fields.");
}
if (isExtension) {
@@ -1030,10 +1024,26 @@ public final class Descriptors {
defaultValue = TextFormat.parseUInt64(proto.getDefaultValue());
break;
case FLOAT:
- defaultValue = Float.valueOf(proto.getDefaultValue());
+ if (proto.getDefaultValue().equals("inf")) {
+ defaultValue = Float.POSITIVE_INFINITY;
+ } else if (proto.getDefaultValue().equals("-inf")) {
+ defaultValue = Float.NEGATIVE_INFINITY;
+ } else if (proto.getDefaultValue().equals("nan")) {
+ defaultValue = Float.NaN;
+ } else {
+ defaultValue = Float.valueOf(proto.getDefaultValue());
+ }
break;
case DOUBLE:
- defaultValue = Double.valueOf(proto.getDefaultValue());
+ if (proto.getDefaultValue().equals("inf")) {
+ defaultValue = Double.POSITIVE_INFINITY;
+ } else if (proto.getDefaultValue().equals("-inf")) {
+ defaultValue = Double.NEGATIVE_INFINITY;
+ } else if (proto.getDefaultValue().equals("nan")) {
+ defaultValue = Double.NaN;
+ } else {
+ defaultValue = Double.valueOf(proto.getDefaultValue());
+ }
break;
case BOOL:
defaultValue = Boolean.valueOf(proto.getDefaultValue());
@@ -1064,12 +1074,9 @@ public final class Descriptors {
"Message type had default value.");
}
} catch (NumberFormatException e) {
- final DescriptorValidationException validationException =
- new DescriptorValidationException(this,
- "Could not parse default value: \"" +
- proto.getDefaultValue() + '\"');
- validationException.initCause(e);
- throw validationException;
+ throw new DescriptorValidationException(this,
+ "Could not parse default value: \"" +
+ proto.getDefaultValue() + '\"', e);
}
} else {
// Determine the default default for this field.
@@ -1536,14 +1543,7 @@ public final class Descriptors {
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);
+ super(problemDescriptor.getFullName() + ": " + description);
// Note that problemDescriptor may be partially uninitialized, so we
// don't want to expose it directly to the user. So, we only provide
@@ -1554,6 +1554,14 @@ public final class Descriptors {
}
private DescriptorValidationException(
+ final GenericDescriptor problemDescriptor,
+ final String description,
+ final Throwable cause) {
+ this(problemDescriptor, description);
+ initCause(cause);
+ }
+
+ private DescriptorValidationException(
final FileDescriptor problemDescriptor,
final String description) {
super(problemDescriptor.getName() + ": " + description);
diff --git a/java/src/main/java/com/google/protobuf/ExtensionRegistry.java b/java/src/main/java/com/google/protobuf/ExtensionRegistry.java
index 87bbd6eb..d4f6ba9e 100644
--- a/java/src/main/java/com/google/protobuf/ExtensionRegistry.java
+++ b/java/src/main/java/com/google/protobuf/ExtensionRegistry.java
@@ -157,6 +157,11 @@ public final class ExtensionRegistry extends ExtensionRegistryLite {
public void add(final GeneratedMessage.GeneratedExtension<?, ?> extension) {
if (extension.getDescriptor().getJavaType() ==
FieldDescriptor.JavaType.MESSAGE) {
+ if (extension.getMessageDefaultInstance() == null) {
+ throw new IllegalStateException(
+ "Registered message-type extension had null default instance: " +
+ extension.getDescriptor().getFullName());
+ }
add(new ExtensionInfo(extension.getDescriptor(),
extension.getMessageDefaultInstance()));
} else {
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
index 4994faad..b5583ba3 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -789,6 +789,10 @@ public abstract class GeneratedMessage extends AbstractMessage {
messageDefaultInstance =
(Message) invokeOrDie(getMethodOrDie(type, "getDefaultInstance"),
null);
+ if (messageDefaultInstance == null) {
+ throw new IllegalStateException(
+ type.getName() + ".getDefaultInstance() returned null.");
+ }
break;
case ENUM:
enumValueOf = getMethodOrDie(type, "valueOf",
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index c68414bd..e327f745 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -303,7 +303,7 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite {
final ExtensionRegistryLite extensionRegistry,
final int tag) throws IOException {
final FieldSet<ExtensionDescriptor> extensions =
- internalGetResult().extensions;
+ ((ExtendableMessage) internalGetResult()).extensions;
final int wireType = WireFormat.getTagWireType(tag);
final int fieldNumber = WireFormat.getTagFieldNumber(tag);
@@ -312,15 +312,29 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite {
extensionRegistry.findLiteExtensionByNumber(
getDefaultInstanceForType(), fieldNumber);
- if (extension == null || wireType !=
- FieldSet.getWireFormatForFieldType(
- extension.descriptor.getLiteType(),
- extension.descriptor.isPacked())) {
- // Unknown field or wrong wire type. Skip.
+ boolean unknown = false;
+ boolean packed = false;
+ if (extension == null) {
+ unknown = true; // Unknown field.
+ } else if (wireType == FieldSet.getWireFormatForFieldType(
+ extension.descriptor.getLiteType(),
+ false /* isPacked */)) {
+ packed = false; // Normal, unpacked value.
+ } else if (extension.descriptor.isRepeated &&
+ extension.descriptor.type.isPackable() &&
+ wireType == FieldSet.getWireFormatForFieldType(
+ extension.descriptor.getLiteType(),
+ true /* isPacked */)) {
+ packed = true; // Packed value.
+ } else {
+ unknown = true; // Wrong wire type.
+ }
+
+ if (unknown) { // Unknown field or wrong wire type. Skip.
return input.skipField(tag);
}
- if (extension.descriptor.isPacked()) {
+ if (packed) {
final int length = input.readRawVarint32();
final int limit = input.pushLimit(length);
if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
@@ -396,7 +410,8 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite {
}
protected final void mergeExtensionFields(final MessageType other) {
- internalGetResult().extensions.mergeFrom(other.extensions);
+ ((ExtendableMessage) internalGetResult()).extensions.mergeFrom(
+ ((ExtendableMessage) other).extensions);
}
}
diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java
index c11abdc5..8c29e212 100644
--- a/java/src/main/java/com/google/protobuf/Message.java
+++ b/java/src/main/java/com/google/protobuf/Message.java
@@ -296,9 +296,9 @@ public interface Message extends MessageLite {
Builder mergeFrom(InputStream input,
ExtensionRegistryLite extensionRegistry)
throws IOException;
- Builder mergeDelimitedFrom(InputStream input)
+ boolean mergeDelimitedFrom(InputStream input)
throws IOException;
- Builder mergeDelimitedFrom(InputStream input,
+ boolean mergeDelimitedFrom(InputStream input,
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
index 3ebe9bba..cf7f39e2 100644
--- a/java/src/main/java/com/google/protobuf/MessageLite.java
+++ b/java/src/main/java/com/google/protobuf/MessageLite.java
@@ -317,14 +317,18 @@ public interface MessageLite {
* then the message data. Use
* {@link MessageLite#writeDelimitedTo(OutputStream)} to write messages in
* this format.
+ *
+ * @returns True if successful, or false if the stream is at EOF when the
+ * method starts. Any other error (including reaching EOF during
+ * parsing) will cause an exception to be thrown.
*/
- Builder mergeDelimitedFrom(InputStream input)
+ boolean mergeDelimitedFrom(InputStream input)
throws IOException;
/**
* Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions.
*/
- Builder mergeDelimitedFrom(InputStream input,
+ boolean mergeDelimitedFrom(InputStream input,
ExtensionRegistryLite extensionRegistry)
throws IOException;
}
diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java
index a855720b..698992f0 100644
--- a/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -426,7 +426,7 @@ public final class TextFormat {
Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE);
private static final Pattern TOKEN = Pattern.compile(
"[a-zA-Z_][0-9a-zA-Z_+-]*+|" + // an identifier
- "[0-9+-][0-9a-zA-Z_.+-]*+|" + // a number
+ "[.]?[0-9+-][0-9a-zA-Z_.+-]*+|" + // a number
"\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" + // a double-quoted string
"\'([^\"\n\\\\]|\\\\.)*+(\'|\\\\?$)", // a single-quoted string
Pattern.MULTILINE);
diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
index 7f7e4939..26a15d00 100644
--- a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -30,6 +30,8 @@
package com.google.protobuf;
+import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -551,19 +553,23 @@ public final class UnknownFieldSet implements MessageLite {
return this;
}
- public Builder mergeDelimitedFrom(InputStream input)
+ public boolean mergeDelimitedFrom(InputStream input)
throws IOException {
- final int size = CodedInputStream.readRawVarint32(input);
- final InputStream limitedInput =
- new AbstractMessage.Builder.LimitedInputStream(input, size);
- return mergeFrom(limitedInput, null);
+ final int firstByte = input.read();
+ if (firstByte == -1) {
+ return false;
+ }
+ final int size = CodedInputStream.readRawVarint32(firstByte, input);
+ final InputStream limitedInput = new LimitedInputStream(input, size);
+ mergeFrom(limitedInput);
+ return true;
}
- public Builder mergeDelimitedFrom(
+ public boolean mergeDelimitedFrom(
InputStream input,
ExtensionRegistryLite extensionRegistry) throws IOException {
// UnknownFieldSet has no extensions.
- return mergeFrom(input);
+ return mergeDelimitedFrom(input);
}
public Builder mergeFrom(
diff --git a/java/src/main/java/com/google/protobuf/WireFormat.java b/java/src/main/java/com/google/protobuf/WireFormat.java
index 3b0bdcd0..c46f7b0a 100644
--- a/java/src/main/java/com/google/protobuf/WireFormat.java
+++ b/java/src/main/java/com/google/protobuf/WireFormat.java
@@ -113,10 +113,18 @@ public final class WireFormat {
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),
+ STRING (JavaType.STRING , WIRETYPE_LENGTH_DELIMITED) {
+ public boolean isPackable() { return false; }
+ },
+ GROUP (JavaType.MESSAGE , WIRETYPE_START_GROUP ) {
+ public boolean isPackable() { return false; }
+ },
+ MESSAGE (JavaType.MESSAGE , WIRETYPE_LENGTH_DELIMITED) {
+ public boolean isPackable() { return false; }
+ },
+ BYTES (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED) {
+ public boolean isPackable() { return false; }
+ },
UINT32 (JavaType.INT , WIRETYPE_VARINT ),
ENUM (JavaType.ENUM , WIRETYPE_VARINT ),
SFIXED32(JavaType.INT , WIRETYPE_FIXED32 ),
@@ -134,6 +142,8 @@ public final class WireFormat {
public JavaType getJavaType() { return javaType; }
public int getWireType() { return wireType; }
+
+ public boolean isPackable() { return true; }
}
// Field numbers for feilds in MessageSet wire format.
diff --git a/java/src/test/java/com/google/protobuf/AbstractMessageTest.java b/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
index 2c59fd0d..c44d6605 100644
--- a/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
@@ -38,6 +38,7 @@ import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestPackedTypes;
import protobuf_unittest.UnittestProto.TestRequired;
import protobuf_unittest.UnittestProto.TestRequiredForeign;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
import junit.framework.TestCase;
@@ -238,6 +239,43 @@ public class AbstractMessageTest extends TestCase {
TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
}
+ public void testUnpackedSerialization() throws Exception {
+ Message abstractMessage =
+ new AbstractMessageWrapper(TestUtil.getUnpackedSet());
+
+ TestUtil.assertUnpackedFieldsSet(
+ TestUnpackedTypes.parseFrom(abstractMessage.toByteString()));
+
+ assertEquals(TestUtil.getUnpackedSet().toByteString(),
+ abstractMessage.toByteString());
+ }
+
+ public void testParsePackedToUnpacked() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+ TestUtil.assertUnpackedFieldsSet(
+ (TestUnpackedTypes) message.wrappedMessage);
+ }
+
+ public void testParseUnpackedToPacked() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+ TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
+ }
+
+ public void testUnpackedParsing() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+ TestUtil.assertUnpackedFieldsSet(
+ (TestUnpackedTypes) message.wrappedMessage);
+ }
+
public void testOptimizedForSize() throws Exception {
// We're mostly only checking that this class was compiled successfully.
TestOptimizedForSize message =
diff --git a/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
index a75a400b..6acd3223 100644
--- a/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
+++ b/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
@@ -490,4 +490,18 @@ public class CodedInputStreamTest extends TestCase {
assertEquals(0, in.readTag());
assertEquals(5, in.getTotalBytesRead());
}
+
+ public void testInvalidTag() throws Exception {
+ // Any tag number which corresponds to field number zero is invalid and
+ // should throw InvalidProtocolBufferException.
+ for (int i = 0; i < 8; i++) {
+ try {
+ CodedInputStream.newInstance(bytes(i)).readTag();
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(InvalidProtocolBufferException.invalidTag().getMessage(),
+ e.getMessage());
+ }
+ }
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
index c5c38b27..f41d070e 100644
--- a/java/src/test/java/com/google/protobuf/DescriptorsTest.java
+++ b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -30,6 +30,10 @@
package com.google.protobuf;
+import com.google.protobuf.DescriptorProtos.DescriptorProto;
+import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
+import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
+import com.google.protobuf.Descriptors.DescriptorValidationException;
import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
@@ -63,6 +67,22 @@ import java.util.Collections;
* @author kenton@google.com Kenton Varda
*/
public class DescriptorsTest extends TestCase {
+
+ // Regression test for bug where referencing a FieldDescriptor.Type value
+ // before a FieldDescriptorProto.Type value would yield a
+ // ExceptionInInitializerError.
+ private static final Object STATIC_INIT_TEST = FieldDescriptor.Type.BOOL;
+
+ public void testFieldTypeEnumMapping() throws Exception {
+ assertEquals(FieldDescriptor.Type.values().length,
+ FieldDescriptorProto.Type.values().length);
+ for (FieldDescriptor.Type type : FieldDescriptor.Type.values()) {
+ FieldDescriptorProto.Type protoType = type.toProto();
+ assertEquals("TYPE_" + type.name(), protoType.name());
+ assertEquals(type, FieldDescriptor.Type.valueOf(protoType));
+ }
+ }
+
public void testFileDescriptor() throws Exception {
FileDescriptor file = UnittestProto.getDescriptor();
@@ -405,4 +425,35 @@ public class DescriptorsTest extends TestCase {
UnittestEnormousDescriptor.getDescriptor()
.toProto().getSerializedSize() > 65536);
}
+
+ /**
+ * Tests that the DescriptorValidationException works as intended.
+ */
+ public void testDescriptorValidatorException() throws Exception {
+ FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setType(FieldDescriptorProto.Type.TYPE_INT32)
+ .setName("foo")
+ .setNumber(1)
+ .setDefaultValue("invalid")
+ .build())
+ .build())
+ .build();
+ try {
+ Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
+ new FileDescriptor[0]);
+ fail("DescriptorValidationException expected");
+ } catch (DescriptorValidationException e) {
+ // Expected; check that the error message contains some useful hints
+ assertTrue(e.getMessage().indexOf("foo") != -1);
+ assertTrue(e.getMessage().indexOf("Foo") != -1);
+ assertTrue(e.getMessage().indexOf("invalid") != -1);
+ assertTrue(e.getCause() instanceof NumberFormatException);
+ assertTrue(e.getCause().getMessage().indexOf("invalid") != -1);
+ }
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index cdf60c5e..73c71f31 100644
--- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -39,6 +39,8 @@ import protobuf_unittest.UnittestProto.ForeignEnum;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
import protobuf_unittest.MultipleFilesTestProto;
import protobuf_unittest.MessageWithNoOuter;
import protobuf_unittest.EnumWithNoOuter;
@@ -303,8 +305,15 @@ public class GeneratedMessageTest extends TestCase {
TestUtil.assertClear(TestAllTypes.getDefaultInstance());
TestUtil.assertClear(TestAllTypes.newBuilder().build());
- assertEquals("\u1234",
- TestExtremeDefaultValues.getDefaultInstance().getUtf8String());
+ TestExtremeDefaultValues message =
+ TestExtremeDefaultValues.getDefaultInstance();
+ assertEquals("\u1234", message.getUtf8String());
+ assertEquals(Double.POSITIVE_INFINITY, message.getInfDouble());
+ assertEquals(Double.NEGATIVE_INFINITY, message.getNegInfDouble());
+ assertTrue(Double.isNaN(message.getNanDouble()));
+ assertEquals(Float.POSITIVE_INFINITY, message.getInfFloat());
+ assertEquals(Float.NEGATIVE_INFINITY, message.getNegInfFloat());
+ assertTrue(Float.isNaN(message.getNanFloat()));
}
public void testReflectionGetters() throws Exception {
@@ -361,6 +370,20 @@ public class GeneratedMessageTest extends TestCase {
assertTrue(map.findValueByNumber(12345) == null);
}
+ public void testParsePackedToUnpacked() throws Exception {
+ TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder();
+ TestUnpackedTypes message =
+ builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+ TestUtil.assertUnpackedFieldsSet(message);
+ }
+
+ public void testParseUnpackedToPacked() throws Exception {
+ TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+ TestPackedTypes message =
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+ TestUtil.assertPackedFieldsSet(message);
+ }
+
// =================================================================
// Extensions.
@@ -615,4 +638,12 @@ public class GeneratedMessageTest extends TestCase {
UnittestProto.REPEATED_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 48);
assertEquals(UnittestProto.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 51);
}
+
+ public void testRecursiveMessageDefaultInstance() throws Exception {
+ UnittestProto.TestRecursiveMessage message =
+ UnittestProto.TestRecursiveMessage.getDefaultInstance();
+ assertTrue(message != null);
+ assertTrue(message.getA() != null);
+ assertTrue(message.getA() == message);
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/ServiceTest.java b/java/src/test/java/com/google/protobuf/ServiceTest.java
index d8523ea3..e10322dc 100644
--- a/java/src/test/java/com/google/protobuf/ServiceTest.java
+++ b/java/src/test/java/com/google/protobuf/ServiceTest.java
@@ -30,7 +30,9 @@
package com.google.protobuf;
+import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.Descriptors.MethodDescriptor;
+import google.protobuf.no_generic_services_test.UnittestNoGenericServices;
import protobuf_unittest.MessageWithNoOuter;
import protobuf_unittest.ServiceWithNoOuter;
import protobuf_unittest.UnittestProto.TestAllTypes;
@@ -44,6 +46,9 @@ import org.easymock.classextension.EasyMock;
import org.easymock.classextension.IMocksControl;
import org.easymock.IArgumentMatcher;
+import java.util.HashSet;
+import java.util.Set;
+
import junit.framework.TestCase;
/**
@@ -220,6 +225,48 @@ public class ServiceTest extends TestCase {
control.verify();
}
+ public void testNoGenericServices() throws Exception {
+ // Non-services should be usable.
+ UnittestNoGenericServices.TestMessage message =
+ UnittestNoGenericServices.TestMessage.newBuilder()
+ .setA(123)
+ .setExtension(UnittestNoGenericServices.testExtension, 456)
+ .build();
+ assertEquals(123, message.getA());
+ assertEquals(1, UnittestNoGenericServices.TestEnum.FOO.getNumber());
+
+ // Build a list of the class names nested in UnittestNoGenericServices.
+ String outerName = "google.protobuf.no_generic_services_test." +
+ "UnittestNoGenericServices";
+ Class<?> outerClass = Class.forName(outerName);
+
+ Set<String> innerClassNames = new HashSet<String>();
+ for (Class<?> innerClass : outerClass.getClasses()) {
+ String fullName = innerClass.getName();
+ // Figure out the unqualified name of the inner class.
+ // Note: Surprisingly, the full name of an inner class will be separated
+ // from the outer class name by a '$' rather than a '.'. This is not
+ // mentioned in the documentation for java.lang.Class. I don't want to
+ // make assumptions, so I'm just going to accept any character as the
+ // separator.
+ assertTrue(fullName.startsWith(outerName));
+ innerClassNames.add(fullName.substring(outerName.length() + 1));
+ }
+
+ // No service class should have been generated.
+ assertTrue(innerClassNames.contains("TestMessage"));
+ assertTrue(innerClassNames.contains("TestEnum"));
+ assertFalse(innerClassNames.contains("TestService"));
+
+ // But descriptors are there.
+ FileDescriptor file = UnittestNoGenericServices.getDescriptor();
+ assertEquals(1, file.getServices().size());
+ assertEquals("TestService", file.getServices().get(0).getName());
+ assertEquals(1, file.getServices().get(0).getMethods().size());
+ assertEquals("Foo",
+ file.getServices().get(0).getMethods().get(0).getName());
+ }
+
// =================================================================
/**
diff --git a/java/src/test/java/com/google/protobuf/TestUtil.java b/java/src/test/java/com/google/protobuf/TestUtil.java
index 805c42ae..db6acb07 100644
--- a/java/src/test/java/com/google/protobuf/TestUtil.java
+++ b/java/src/test/java/com/google/protobuf/TestUtil.java
@@ -217,6 +217,7 @@ import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestPackedExtensions;
import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
import protobuf_unittest.UnittestProto.ForeignMessage;
import protobuf_unittest.UnittestProto.ForeignEnum;
import com.google.protobuf.test.UnittestImport.ImportMessage;
@@ -289,6 +290,12 @@ class TestUtil {
return builder.build();
}
+ public static TestUnpackedTypes getUnpackedSet() {
+ TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder();
+ setUnpackedFields(builder);
+ return builder.build();
+ }
+
public static TestPackedExtensions getPackedExtensionsSet() {
TestPackedExtensions.Builder builder = TestPackedExtensions.newBuilder();
setPackedExtensions(builder);
@@ -956,6 +963,42 @@ class TestUtil {
}
/**
+ * Set every field of {@code message} to a unique value. Must correspond with
+ * the values applied by {@code setPackedFields}.
+ */
+ public static void setUnpackedFields(TestUnpackedTypes.Builder message) {
+ message.addUnpackedInt32 (601);
+ message.addUnpackedInt64 (602);
+ message.addUnpackedUint32 (603);
+ message.addUnpackedUint64 (604);
+ message.addUnpackedSint32 (605);
+ message.addUnpackedSint64 (606);
+ message.addUnpackedFixed32 (607);
+ message.addUnpackedFixed64 (608);
+ message.addUnpackedSfixed32(609);
+ message.addUnpackedSfixed64(610);
+ message.addUnpackedFloat (611);
+ message.addUnpackedDouble (612);
+ message.addUnpackedBool (true);
+ message.addUnpackedEnum (ForeignEnum.FOREIGN_BAR);
+ // Add a second one of each field.
+ message.addUnpackedInt32 (701);
+ message.addUnpackedInt64 (702);
+ message.addUnpackedUint32 (703);
+ message.addUnpackedUint64 (704);
+ message.addUnpackedSint32 (705);
+ message.addUnpackedSint64 (706);
+ message.addUnpackedFixed32 (707);
+ message.addUnpackedFixed64 (708);
+ message.addUnpackedSfixed32(709);
+ message.addUnpackedSfixed64(710);
+ message.addUnpackedFloat (711);
+ message.addUnpackedDouble (712);
+ message.addUnpackedBool (false);
+ message.addUnpackedEnum (ForeignEnum.FOREIGN_BAZ);
+ }
+
+ /**
* Assert (using {@code junit.framework.Assert}} that all fields of
* {@code message} are set to the values assigned by {@code setPackedFields}.
*/
@@ -1004,6 +1047,55 @@ class TestUtil {
Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1));
}
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setUnpackedFields}.
+ */
+ public static void assertUnpackedFieldsSet(TestUnpackedTypes message) {
+ Assert.assertEquals(2, message.getUnpackedInt32Count ());
+ Assert.assertEquals(2, message.getUnpackedInt64Count ());
+ Assert.assertEquals(2, message.getUnpackedUint32Count ());
+ Assert.assertEquals(2, message.getUnpackedUint64Count ());
+ Assert.assertEquals(2, message.getUnpackedSint32Count ());
+ Assert.assertEquals(2, message.getUnpackedSint64Count ());
+ Assert.assertEquals(2, message.getUnpackedFixed32Count ());
+ Assert.assertEquals(2, message.getUnpackedFixed64Count ());
+ Assert.assertEquals(2, message.getUnpackedSfixed32Count());
+ Assert.assertEquals(2, message.getUnpackedSfixed64Count());
+ Assert.assertEquals(2, message.getUnpackedFloatCount ());
+ Assert.assertEquals(2, message.getUnpackedDoubleCount ());
+ Assert.assertEquals(2, message.getUnpackedBoolCount ());
+ Assert.assertEquals(2, message.getUnpackedEnumCount ());
+ Assert.assertEquals(601 , message.getUnpackedInt32 (0));
+ Assert.assertEquals(602 , message.getUnpackedInt64 (0));
+ Assert.assertEquals(603 , message.getUnpackedUint32 (0));
+ Assert.assertEquals(604 , message.getUnpackedUint64 (0));
+ Assert.assertEquals(605 , message.getUnpackedSint32 (0));
+ Assert.assertEquals(606 , message.getUnpackedSint64 (0));
+ Assert.assertEquals(607 , message.getUnpackedFixed32 (0));
+ Assert.assertEquals(608 , message.getUnpackedFixed64 (0));
+ Assert.assertEquals(609 , message.getUnpackedSfixed32(0));
+ Assert.assertEquals(610 , message.getUnpackedSfixed64(0));
+ Assert.assertEquals(611 , message.getUnpackedFloat (0), 0.0);
+ Assert.assertEquals(612 , message.getUnpackedDouble (0), 0.0);
+ Assert.assertEquals(true , message.getUnpackedBool (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getUnpackedEnum(0));
+ Assert.assertEquals(701 , message.getUnpackedInt32 (1));
+ Assert.assertEquals(702 , message.getUnpackedInt64 (1));
+ Assert.assertEquals(703 , message.getUnpackedUint32 (1));
+ Assert.assertEquals(704 , message.getUnpackedUint64 (1));
+ Assert.assertEquals(705 , message.getUnpackedSint32 (1));
+ Assert.assertEquals(706 , message.getUnpackedSint64 (1));
+ Assert.assertEquals(707 , message.getUnpackedFixed32 (1));
+ Assert.assertEquals(708 , message.getUnpackedFixed64 (1));
+ Assert.assertEquals(709 , message.getUnpackedSfixed32(1));
+ Assert.assertEquals(710 , message.getUnpackedSfixed64(1));
+ Assert.assertEquals(711 , message.getUnpackedFloat (1), 0.0);
+ Assert.assertEquals(712 , message.getUnpackedDouble (1), 0.0);
+ Assert.assertEquals(false, message.getUnpackedBool (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getUnpackedEnum(1));
+ }
+
// ===================================================================
// Like above, but for extensions
diff --git a/java/src/test/java/com/google/protobuf/TextFormatTest.java b/java/src/test/java/com/google/protobuf/TextFormatTest.java
index 1d73165e..3ea7b2cf 100644
--- a/java/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -68,7 +68,7 @@ public class TextFormatTest extends TestCase {
private static String allExtensionsSetText = TestUtil.readTextFromFile(
"text_format_unittest_extensions_data.txt");
- private String exoticText =
+ private static String exoticText =
"repeated_int32: -1\n" +
"repeated_int32: -2147483648\n" +
"repeated_int64: -1\n" +
@@ -80,7 +80,13 @@ public class TextFormatTest extends TestCase {
"repeated_double: 123.0\n" +
"repeated_double: 123.5\n" +
"repeated_double: 0.125\n" +
+ "repeated_double: .125\n" +
+ "repeated_double: -.125\n" +
"repeated_double: 1.23E17\n" +
+ "repeated_double: 1.23E+17\n" +
+ "repeated_double: -1.23e-17\n" +
+ "repeated_double: .23e+17\n" +
+ "repeated_double: -.23E17\n" +
"repeated_double: 1.235E22\n" +
"repeated_double: 1.235E-18\n" +
"repeated_double: 123.456789\n" +
@@ -91,6 +97,10 @@ public class TextFormatTest extends TestCase {
"\\341\\210\\264\"\n" +
"repeated_bytes: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\376\"\n";
+ private static String canonicalExoticText =
+ exoticText.replace(": .", ": 0.").replace(": -.", ": -0.") // short-form double
+ .replace("23e", "23E").replace("E+", "E").replace("0.23E17", "2.3E16");
+
private String messageSetText =
"[protobuf_unittest.TestMessageSetExtension1] {\n" +
" i: 123\n" +
@@ -231,7 +241,13 @@ public class TextFormatTest extends TestCase {
.addRepeatedDouble(123)
.addRepeatedDouble(123.5)
.addRepeatedDouble(0.125)
+ .addRepeatedDouble(.125)
+ .addRepeatedDouble(-.125)
+ .addRepeatedDouble(123e15)
.addRepeatedDouble(123e15)
+ .addRepeatedDouble(-1.23e-17)
+ .addRepeatedDouble(.23e17)
+ .addRepeatedDouble(-23e15)
.addRepeatedDouble(123.5e20)
.addRepeatedDouble(123.5e-20)
.addRepeatedDouble(123.456789)
@@ -244,7 +260,7 @@ public class TextFormatTest extends TestCase {
.addRepeatedBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\u00fe"))
.build();
- assertEquals(exoticText, message.toString());
+ assertEquals(canonicalExoticText, message.toString());
}
public void testPrintMessageSet() throws Exception {
@@ -319,7 +335,7 @@ public class TextFormatTest extends TestCase {
// Too lazy to check things individually. Don't try to debug this
// if testPrintExotic() is failing.
- assertEquals(exoticText, builder.build().toString());
+ assertEquals(canonicalExoticText, builder.build().toString());
}
public void testParseMessageSet() throws Exception {
diff --git a/java/src/test/java/com/google/protobuf/WireFormatTest.java b/java/src/test/java/com/google/protobuf/WireFormatTest.java
index 6a5bd5de..5ea1dd6a 100644
--- a/java/src/test/java/com/google/protobuf/WireFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -235,6 +235,9 @@ public class WireFormatTest extends TestCase {
TestUtil.assertPackedFieldsSet(TestPackedTypes.parseDelimitedFrom(input));
assertEquals(34, input.read());
assertEquals(-1, input.read());
+
+ // We're at EOF, so parsing again should return null.
+ assertTrue(TestAllTypes.parseDelimitedFrom(input) == null);
}
private void assertFieldsInOrder(ByteString data) throws Exception {
diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py
index 8e3fc2eb..aa4ab969 100755
--- a/python/google/protobuf/descriptor.py
+++ b/python/google/protobuf/descriptor.py
@@ -44,12 +44,24 @@ file, in types that make this information accessible in Python.
__author__ = 'robinson@google.com (Will Robinson)'
+
+class Error(Exception):
+ """Base error for this module."""
+
+
class DescriptorBase(object):
"""Descriptors base class.
This class is the base of all descriptor classes. It provides common options
related functionaility.
+
+ Attributes:
+ has_options: True if the descriptor has non-default options. Usually it
+ is not necessary to read this -- just call GetOptions() which will
+ happily return the default instance. However, it's sometimes useful
+ for efficiency, and also useful inside the protobuf implementation to
+ avoid some bootstrapping issues.
"""
def __init__(self, options, options_class_name):
@@ -60,6 +72,9 @@ class DescriptorBase(object):
self._options = options
self._options_class_name = options_class_name
+ # Does this descriptor have non-default options?
+ self.has_options = options is not None
+
def GetOptions(self):
"""Retrieves descriptor options.
@@ -78,7 +93,70 @@ class DescriptorBase(object):
return self._options
-class Descriptor(DescriptorBase):
+class _NestedDescriptorBase(DescriptorBase):
+ """Common class for descriptors that can be nested."""
+
+ def __init__(self, options, options_class_name, name, full_name,
+ file, containing_type, serialized_start=None,
+ serialized_end=None):
+ """Constructor.
+
+ Args:
+ options: Protocol message options or None
+ to use default message options.
+ options_class_name: (str) The class name of the above options.
+
+ name: (str) Name of this protocol message type.
+ full_name: (str) Fully-qualified name of this protocol message type,
+ which will include protocol "package" name and the name of any
+ enclosing types.
+ file: (FileDescriptor) Reference to file info.
+ containing_type: if provided, this is a nested descriptor, with this
+ descriptor as parent, otherwise None.
+ serialized_start: The start index (inclusive) in block in the
+ file.serialized_pb that describes this descriptor.
+ serialized_end: The end index (exclusive) in block in the
+ file.serialized_pb that describes this descriptor.
+ """
+ super(_NestedDescriptorBase, self).__init__(
+ options, options_class_name)
+
+ self.name = name
+ # TODO(falk): Add function to calculate full_name instead of having it in
+ # memory?
+ self.full_name = full_name
+ self.file = file
+ self.containing_type = containing_type
+
+ self._serialized_start = serialized_start
+ self._serialized_end = serialized_end
+
+ def GetTopLevelContainingType(self):
+ """Returns the root if this is a nested type, or itself if its the root."""
+ desc = self
+ while desc.containing_type is not None:
+ desc = desc.containing_type
+ return desc
+
+ def CopyToProto(self, proto):
+ """Copies this to the matching proto in descriptor_pb2.
+
+ Args:
+ proto: An empty proto instance from descriptor_pb2.
+
+ Raises:
+ Error: If self couldnt be serialized, due to to few constructor arguments.
+ """
+ if (self.file is not None and
+ self._serialized_start is not None and
+ self._serialized_end is not None):
+ proto.ParseFromString(self.file.serialized_pb[
+ self._serialized_start:self._serialized_end])
+ else:
+ raise Error('Descriptor does not contain serialization.')
+
+
+class Descriptor(_NestedDescriptorBase):
"""Descriptor for a protocol message type.
@@ -89,10 +167,8 @@ class Descriptor(DescriptorBase):
which will include protocol "package" name and the name of any
enclosing types.
- filename: (str) Name of the .proto file containing this message.
-
containing_type: (Descriptor) Reference to the descriptor of the
- type containing us, or None if we have no containing type.
+ type containing us, or None if this is top-level.
fields: (list of FieldDescriptors) Field descriptors for all
fields in this type.
@@ -123,20 +199,28 @@ class Descriptor(DescriptorBase):
objects as |extensions|, but indexed by "name" attribute of each
FieldDescriptor.
+ is_extendable: Does this type define any extension ranges?
+
options: (descriptor_pb2.MessageOptions) Protocol message options or None
to use default message options.
+
+ file: (FileDescriptor) Reference to file descriptor.
"""
- def __init__(self, name, full_name, filename, containing_type,
- fields, nested_types, enum_types, extensions, options=None):
+ def __init__(self, name, full_name, filename, containing_type, fields,
+ nested_types, enum_types, extensions, options=None,
+ is_extendable=True, extension_ranges=None, file=None,
+ serialized_start=None, serialized_end=None):
"""Arguments to __init__() are as described in the description
of Descriptor fields above.
+
+ Note that filename is an obsolete argument, that is not used anymore.
+ Please use file.name to access this as an attribute.
"""
- super(Descriptor, self).__init__(options, 'MessageOptions')
- self.name = name
- self.full_name = full_name
- self.filename = filename
- self.containing_type = containing_type
+ super(Descriptor, self).__init__(
+ options, 'MessageOptions', name, full_name, file,
+ containing_type, serialized_start=serialized_start,
+ serialized_end=serialized_start)
# We have fields in addition to fields_by_name and fields_by_number,
# so that:
@@ -163,6 +247,20 @@ class Descriptor(DescriptorBase):
for extension in self.extensions:
extension.extension_scope = self
self.extensions_by_name = dict((f.name, f) for f in extensions)
+ self.is_extendable = is_extendable
+ self.extension_ranges = extension_ranges
+
+ self._serialized_start = serialized_start
+ self._serialized_end = serialized_end
+
+ def CopyToProto(self, proto):
+ """Copies this to a descriptor_pb2.DescriptorProto.
+
+ Args:
+ proto: An empty descriptor_pb2.DescriptorProto.
+ """
+ # This function is overriden to give a better doc comment.
+ super(Descriptor, self).CopyToProto(proto)
# TODO(robinson): We should have aggressive checking here,
@@ -195,6 +293,8 @@ class FieldDescriptor(DescriptorBase):
label: (One of the LABEL_* constants below) Tells whether this
field is optional, required, or repeated.
+ has_default_value: (bool) True if this field has a default value defined,
+ otherwise false.
default_value: (Varies) Default value of this field. Only
meaningful for non-repeated scalar fields. Repeated fields
should always set this to [], and non-repeated composite
@@ -272,7 +372,8 @@ class FieldDescriptor(DescriptorBase):
def __init__(self, name, full_name, index, number, type, cpp_type, label,
default_value, message_type, enum_type, containing_type,
- is_extension, extension_scope, options=None):
+ is_extension, extension_scope, options=None,
+ has_default_value=True):
"""The arguments are as described in the description of FieldDescriptor
attributes above.
@@ -288,6 +389,7 @@ class FieldDescriptor(DescriptorBase):
self.type = type
self.cpp_type = cpp_type
self.label = label
+ self.has_default_value = has_default_value
self.default_value = default_value
self.containing_type = containing_type
self.message_type = message_type
@@ -296,7 +398,7 @@ class FieldDescriptor(DescriptorBase):
self.extension_scope = extension_scope
-class EnumDescriptor(DescriptorBase):
+class EnumDescriptor(_NestedDescriptorBase):
"""Descriptor for an enum defined in a .proto file.
@@ -305,7 +407,6 @@ class EnumDescriptor(DescriptorBase):
name: (str) Name of the enum type.
full_name: (str) Full name of the type, including package name
and any enclosing type(s).
- filename: (str) Name of the .proto file in which this appears.
values: (list of EnumValueDescriptors) List of the values
in this enum.
@@ -317,23 +418,41 @@ class EnumDescriptor(DescriptorBase):
type of this enum, or None if this is an enum defined at the
top level in a .proto file. Set by Descriptor's constructor
if we're passed into one.
+ file: (FileDescriptor) Reference to file descriptor.
options: (descriptor_pb2.EnumOptions) Enum options message or
None to use default enum options.
"""
def __init__(self, name, full_name, filename, values,
- containing_type=None, options=None):
- """Arguments are as described in the attribute description above."""
- super(EnumDescriptor, self).__init__(options, 'EnumOptions')
- self.name = name
- self.full_name = full_name
- self.filename = filename
+ containing_type=None, options=None, file=None,
+ serialized_start=None, serialized_end=None):
+ """Arguments are as described in the attribute description above.
+
+ Note that filename is an obsolete argument, that is not used anymore.
+ Please use file.name to access this as an attribute.
+ """
+ super(EnumDescriptor, self).__init__(
+ options, 'EnumOptions', name, full_name, file,
+ containing_type, serialized_start=serialized_start,
+ serialized_end=serialized_start)
+
self.values = values
for value in self.values:
value.type = self
self.values_by_name = dict((v.name, v) for v in values)
self.values_by_number = dict((v.number, v) for v in values)
- self.containing_type = containing_type
+
+ self._serialized_start = serialized_start
+ self._serialized_end = serialized_end
+
+ def CopyToProto(self, proto):
+ """Copies this to a descriptor_pb2.EnumDescriptorProto.
+
+ Args:
+ proto: An empty descriptor_pb2.EnumDescriptorProto.
+ """
+ # This function is overriden to give a better doc comment.
+ super(EnumDescriptor, self).CopyToProto(proto)
class EnumValueDescriptor(DescriptorBase):
@@ -360,7 +479,7 @@ class EnumValueDescriptor(DescriptorBase):
self.type = type
-class ServiceDescriptor(DescriptorBase):
+class ServiceDescriptor(_NestedDescriptorBase):
"""Descriptor for a service.
@@ -372,12 +491,15 @@ class ServiceDescriptor(DescriptorBase):
service.
options: (descriptor_pb2.ServiceOptions) Service options message or
None to use default service options.
+ file: (FileDescriptor) Reference to file info.
"""
- def __init__(self, name, full_name, index, methods, options=None):
- super(ServiceDescriptor, self).__init__(options, 'ServiceOptions')
- self.name = name
- self.full_name = full_name
+ def __init__(self, name, full_name, index, methods, options=None, file=None,
+ serialized_start=None, serialized_end=None):
+ super(ServiceDescriptor, self).__init__(
+ options, 'ServiceOptions', name, full_name, file,
+ None, serialized_start=serialized_start,
+ serialized_end=serialized_end)
self.index = index
self.methods = methods
# Set the containing service for each method in this service.
@@ -391,6 +513,15 @@ class ServiceDescriptor(DescriptorBase):
return method
return None
+ def CopyToProto(self, proto):
+ """Copies this to a descriptor_pb2.ServiceDescriptorProto.
+
+ Args:
+ proto: An empty descriptor_pb2.ServiceDescriptorProto.
+ """
+ # This function is overriden to give a better doc comment.
+ super(ServiceDescriptor, self).CopyToProto(proto)
+
class MethodDescriptor(DescriptorBase):
@@ -423,6 +554,32 @@ class MethodDescriptor(DescriptorBase):
self.output_type = output_type
+class FileDescriptor(DescriptorBase):
+ """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto.
+
+ name: name of file, relative to root of source tree.
+ package: name of the package
+ serialized_pb: (str) Byte string of serialized
+ descriptor_pb2.FileDescriptorProto.
+ """
+
+ def __init__(self, name, package, options=None, serialized_pb=None):
+ """Constructor."""
+ super(FileDescriptor, self).__init__(options, 'FileOptions')
+
+ self.name = name
+ self.package = package
+ self.serialized_pb = serialized_pb
+
+ def CopyToProto(self, proto):
+ """Copies this to a descriptor_pb2.FileDescriptorProto.
+
+ Args:
+ proto: An empty descriptor_pb2.FileDescriptorProto.
+ """
+ proto.ParseFromString(self.serialized_pb)
+
+
def _ParseOptions(message, string):
"""Parses serialized options.
@@ -430,4 +587,4 @@ def _ParseOptions(message, string):
proto2 files. It must not be used outside proto2.
"""
message.ParseFromString(string)
- return message;
+ return message
diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py
index d8a825df..5cc7d6d0 100755
--- a/python/google/protobuf/internal/containers.py
+++ b/python/google/protobuf/internal/containers.py
@@ -54,8 +54,7 @@ class BaseContainer(object):
Args:
message_listener: A MessageListener implementation.
The RepeatedScalarFieldContainer will call this object's
- TransitionToNonempty() method when it transitions from being empty to
- being nonempty.
+ Modified() method when it is modified.
"""
self._message_listener = message_listener
self._values = []
@@ -73,6 +72,9 @@ class BaseContainer(object):
# The concrete classes should define __eq__.
return not self == other
+ def __repr__(self):
+ return repr(self._values)
+
class RepeatedScalarFieldContainer(BaseContainer):
@@ -86,8 +88,7 @@ class RepeatedScalarFieldContainer(BaseContainer):
Args:
message_listener: A MessageListener implementation.
The RepeatedScalarFieldContainer will call this object's
- TransitionToNonempty() method when it transitions from being empty to
- being nonempty.
+ Modified() method when it is modified.
type_checker: A type_checkers.ValueChecker instance to run on elements
inserted into this container.
"""
@@ -96,44 +97,47 @@ class RepeatedScalarFieldContainer(BaseContainer):
def append(self, value):
"""Appends an item to the list. Similar to list.append()."""
- self.insert(len(self._values), value)
+ self._type_checker.CheckValue(value)
+ self._values.append(value)
+ if not self._message_listener.dirty:
+ self._message_listener.Modified()
def insert(self, key, value):
"""Inserts the item at the specified position. Similar to list.insert()."""
self._type_checker.CheckValue(value)
self._values.insert(key, value)
- self._message_listener.ByteSizeDirty()
- if len(self._values) == 1:
- self._message_listener.TransitionToNonempty()
+ if not self._message_listener.dirty:
+ self._message_listener.Modified()
def extend(self, elem_seq):
"""Extends by appending the given sequence. Similar to list.extend()."""
if not elem_seq:
return
- orig_empty = len(self._values) == 0
new_values = []
for elem in elem_seq:
self._type_checker.CheckValue(elem)
new_values.append(elem)
self._values.extend(new_values)
- self._message_listener.ByteSizeDirty()
- if orig_empty:
- self._message_listener.TransitionToNonempty()
+ self._message_listener.Modified()
+
+ def MergeFrom(self, other):
+ """Appends the contents of another repeated field of the same type to this
+ one. We do not check the types of the individual fields.
+ """
+ self._values.extend(other._values)
+ self._message_listener.Modified()
def remove(self, elem):
"""Removes an item from the list. Similar to list.remove()."""
self._values.remove(elem)
- self._message_listener.ByteSizeDirty()
+ self._message_listener.Modified()
def __setitem__(self, key, value):
"""Sets the item on the specified position."""
- # No need to call TransitionToNonempty(), since if we're able to
- # set the element at this index, we were already nonempty before
- # this method was called.
- self._message_listener.ByteSizeDirty()
self._type_checker.CheckValue(value)
self._values[key] = value
+ self._message_listener.Modified()
def __getslice__(self, start, stop):
"""Retrieves the subset of items from between the specified indices."""
@@ -146,17 +150,17 @@ class RepeatedScalarFieldContainer(BaseContainer):
self._type_checker.CheckValue(value)
new_values.append(value)
self._values[start:stop] = new_values
- self._message_listener.ByteSizeDirty()
+ self._message_listener.Modified()
def __delitem__(self, key):
"""Deletes the item at the specified position."""
del self._values[key]
- self._message_listener.ByteSizeDirty()
+ self._message_listener.Modified()
def __delslice__(self, start, stop):
"""Deletes the subset of items from between the specified indices."""
del self._values[start:stop]
- self._message_listener.ByteSizeDirty()
+ self._message_listener.Modified()
def __eq__(self, other):
"""Compares the current instance with another one."""
@@ -186,8 +190,7 @@ class RepeatedCompositeFieldContainer(BaseContainer):
Args:
message_listener: A MessageListener implementation.
The RepeatedCompositeFieldContainer will call this object's
- TransitionToNonempty() method when it transitions from being empty to
- being nonempty.
+ Modified() method when it is modified.
message_descriptor: A Descriptor instance describing the protocol type
that should be present in this container. We'll use the
_concrete_class field of this descriptor when the client calls add().
@@ -199,10 +202,24 @@ class RepeatedCompositeFieldContainer(BaseContainer):
new_element = self._message_descriptor._concrete_class()
new_element._SetListener(self._message_listener)
self._values.append(new_element)
- self._message_listener.ByteSizeDirty()
- self._message_listener.TransitionToNonempty()
+ if not self._message_listener.dirty:
+ self._message_listener.Modified()
return new_element
+ def MergeFrom(self, other):
+ """Appends the contents of another repeated field of the same type to this
+ one, copying each individual message.
+ """
+ message_class = self._message_descriptor._concrete_class
+ listener = self._message_listener
+ values = self._values
+ for message in other._values:
+ new_element = message_class()
+ new_element._SetListener(listener)
+ new_element.MergeFrom(message)
+ values.append(new_element)
+ listener.Modified()
+
def __getslice__(self, start, stop):
"""Retrieves the subset of items from between the specified indices."""
return self._values[start:stop]
@@ -210,12 +227,12 @@ class RepeatedCompositeFieldContainer(BaseContainer):
def __delitem__(self, key):
"""Deletes the item at the specified position."""
del self._values[key]
- self._message_listener.ByteSizeDirty()
+ self._message_listener.Modified()
def __delslice__(self, start, stop):
"""Deletes the subset of items from between the specified indices."""
del self._values[start:stop]
- self._message_listener.ByteSizeDirty()
+ self._message_listener.Modified()
def __eq__(self, other):
"""Compares the current instance with another one."""
diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py
index 83d6fe0c..461a30c0 100755
--- a/python/google/protobuf/internal/decoder.py
+++ b/python/google/protobuf/internal/decoder.py
@@ -28,182 +28,614 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Class for decoding protocol buffer primitives.
-
-Contains the logic for decoding every logical protocol field type
-from one of the 5 physical wire types.
+"""Code for decoding protocol buffer primitives.
+
+This code is very similar to encoder.py -- read the docs for that module first.
+
+A "decoder" is a function with the signature:
+ Decode(buffer, pos, end, message, field_dict)
+The arguments are:
+ buffer: The string containing the encoded message.
+ pos: The current position in the string.
+ end: The position in the string where the current message ends. May be
+ less than len(buffer) if we're reading a sub-message.
+ message: The message object into which we're parsing.
+ field_dict: message._fields (avoids a hashtable lookup).
+The decoder reads the field and stores it into field_dict, returning the new
+buffer position. A decoder for a repeated field may proactively decode all of
+the elements of that field, if they appear consecutively.
+
+Note that decoders may throw any of the following:
+ IndexError: Indicates a truncated message.
+ struct.error: Unpacking of a fixed-width field failed.
+ message.DecodeError: Other errors.
+
+Decoders are expected to raise an exception if they are called with pos > end.
+This allows callers to be lax about bounds checking: it's fineto read past
+"end" as long as you are sure that someone else will notice and throw an
+exception later on.
+
+Something up the call stack is expected to catch IndexError and struct.error
+and convert them to message.DecodeError.
+
+Decoders are constructed using decoder constructors with the signature:
+ MakeDecoder(field_number, is_repeated, is_packed, key, new_default)
+The arguments are:
+ field_number: The field number of the field we want to decode.
+ is_repeated: Is the field a repeated field? (bool)
+ is_packed: Is the field a packed field? (bool)
+ key: The key to use when looking up the field within field_dict.
+ (This is actually the FieldDescriptor but nothing in this
+ file should depend on that.)
+ new_default: A function which takes a message object as a parameter and
+ returns a new instance of the default value for this field.
+ (This is called for repeated fields and sub-messages, when an
+ instance does not already exist.)
+
+As with encoders, we define a decoder constructor for every type of field.
+Then, for every field of every message class we construct an actual decoder.
+That decoder goes into a dict indexed by tag, so when we decode a message
+we repeatedly read a tag, look up the corresponding decoder, and invoke it.
"""
-__author__ = 'robinson@google.com (Will Robinson)'
+__author__ = 'kenton@google.com (Kenton Varda)'
import struct
-from google.protobuf import message
-from google.protobuf.internal import input_stream
+from google.protobuf.internal import encoder
from google.protobuf.internal import wire_format
+from google.protobuf import message
+# This is not for optimization, but rather to avoid conflicts with local
+# variables named "message".
+_DecodeError = message.DecodeError
+
+
+def _VarintDecoder(mask):
+ """Return an encoder for a basic varint value (does not include tag).
+
+ Decoded values will be bitwise-anded with the given mask before being
+ returned, e.g. to limit them to 32 bits. The returned decoder does not
+ take the usual "end" parameter -- the caller is expected to do bounds checking
+ after the fact (often the caller can defer such checking until later). The
+ decoder returns a (value, new_pos) pair.
+ """
+
+ local_ord = ord
+ def DecodeVarint(buffer, pos):
+ result = 0
+ shift = 0
+ while 1:
+ b = local_ord(buffer[pos])
+ result |= ((b & 0x7f) << shift)
+ pos += 1
+ if not (b & 0x80):
+ result &= mask
+ return (result, pos)
+ shift += 7
+ if shift >= 64:
+ raise _DecodeError('Too many bytes when decoding varint.')
+ return DecodeVarint
+
+
+def _SignedVarintDecoder(mask):
+ """Like _VarintDecoder() but decodes signed values."""
+
+ local_ord = ord
+ def DecodeVarint(buffer, pos):
+ result = 0
+ shift = 0
+ while 1:
+ b = local_ord(buffer[pos])
+ result |= ((b & 0x7f) << shift)
+ pos += 1
+ if not (b & 0x80):
+ if result > 0x7fffffffffffffff:
+ result -= (1 << 64)
+ result |= ~mask
+ else:
+ result &= mask
+ return (result, pos)
+ shift += 7
+ if shift >= 64:
+ raise _DecodeError('Too many bytes when decoding varint.')
+ return DecodeVarint
+
+
+_DecodeVarint = _VarintDecoder((1 << 64) - 1)
+_DecodeSignedVarint = _SignedVarintDecoder((1 << 64) - 1)
+
+# Use these versions for values which must be limited to 32 bits.
+_DecodeVarint32 = _VarintDecoder((1 << 32) - 1)
+_DecodeSignedVarint32 = _SignedVarintDecoder((1 << 32) - 1)
+
+
+def ReadTag(buffer, pos):
+ """Read a tag from the buffer, and return a (tag_bytes, new_pos) tuple.
+
+ We return the raw bytes of the tag rather than decoding them. The raw
+ bytes can then be used to look up the proper decoder. This effectively allows
+ us to trade some work that would be done in pure-python (decoding a varint)
+ for work that is done in C (searching for a byte string in a hash table).
+ In a low-level language it would be much cheaper to decode the varint and
+ use that, but not in Python.
+ """
+
+ start = pos
+ while ord(buffer[pos]) & 0x80:
+ pos += 1
+ pos += 1
+ return (buffer[start:pos], pos)
+
+
+# --------------------------------------------------------------------
+
+
+def _SimpleDecoder(wire_type, decode_value):
+ """Return a constructor for a decoder for fields of a particular type.
+
+ Args:
+ wire_type: The field's wire type.
+ decode_value: A function which decodes an individual value, e.g.
+ _DecodeVarint()
+ """
+
+ def SpecificDecoder(field_number, is_repeated, is_packed, key, new_default):
+ if is_packed:
+ local_DecodeVarint = _DecodeVarint
+ def DecodePackedField(buffer, pos, end, message, field_dict):
+ value = field_dict.get(key)
+ if value is None:
+ value = field_dict.setdefault(key, new_default(message))
+ (endpoint, pos) = local_DecodeVarint(buffer, pos)
+ endpoint += pos
+ if endpoint > end:
+ raise _DecodeError('Truncated message.')
+ while pos < endpoint:
+ (element, pos) = decode_value(buffer, pos)
+ value.append(element)
+ if pos > endpoint:
+ del value[-1] # Discard corrupt value.
+ raise _DecodeError('Packed element was truncated.')
+ return pos
+ return DecodePackedField
+ elif is_repeated:
+ tag_bytes = encoder.TagBytes(field_number, wire_type)
+ tag_len = len(tag_bytes)
+ def DecodeRepeatedField(buffer, pos, end, message, field_dict):
+ value = field_dict.get(key)
+ if value is None:
+ value = field_dict.setdefault(key, new_default(message))
+ while 1:
+ (element, new_pos) = decode_value(buffer, pos)
+ value.append(element)
+ # Predict that the next tag is another copy of the same repeated
+ # field.
+ pos = new_pos + tag_len
+ if buffer[new_pos:pos] != tag_bytes or new_pos >= end:
+ # Prediction failed. Return.
+ if new_pos > end:
+ raise _DecodeError('Truncated message.')
+ return new_pos
+ return DecodeRepeatedField
+ else:
+ def DecodeField(buffer, pos, end, message, field_dict):
+ (field_dict[key], pos) = decode_value(buffer, pos)
+ if pos > end:
+ del field_dict[key] # Discard corrupt value.
+ raise _DecodeError('Truncated message.')
+ return pos
+ return DecodeField
+
+ return SpecificDecoder
+
+
+def _ModifiedDecoder(wire_type, decode_value, modify_value):
+ """Like SimpleDecoder but additionally invokes modify_value on every value
+ before storing it. Usually modify_value is ZigZagDecode.
+ """
+
+ # Reusing _SimpleDecoder is slightly slower than copying a bunch of code, but
+ # not enough to make a significant difference.
+
+ def InnerDecode(buffer, pos):
+ (result, new_pos) = decode_value(buffer, pos)
+ return (modify_value(result), new_pos)
+ return _SimpleDecoder(wire_type, InnerDecode)
+
+
+def _StructPackDecoder(wire_type, format):
+ """Return a constructor for a decoder for a fixed-width field.
+
+ Args:
+ wire_type: The field's wire type.
+ format: The format string to pass to struct.unpack().
+ """
+
+ value_size = struct.calcsize(format)
+ local_unpack = struct.unpack
+
+ # Reusing _SimpleDecoder is slightly slower than copying a bunch of code, but
+ # not enough to make a significant difference.
+
+ # Note that we expect someone up-stack to catch struct.error and convert
+ # it to _DecodeError -- this way we don't have to set up exception-
+ # handling blocks every time we parse one value.
+
+ def InnerDecode(buffer, pos):
+ new_pos = pos + value_size
+ result = local_unpack(format, buffer[pos:new_pos])[0]
+ return (result, new_pos)
+ return _SimpleDecoder(wire_type, InnerDecode)
+
+
+# --------------------------------------------------------------------
+
+
+Int32Decoder = EnumDecoder = _SimpleDecoder(
+ wire_format.WIRETYPE_VARINT, _DecodeSignedVarint32)
+
+Int64Decoder = _SimpleDecoder(
+ wire_format.WIRETYPE_VARINT, _DecodeSignedVarint)
+
+UInt32Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint32)
+UInt64Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint)
+
+SInt32Decoder = _ModifiedDecoder(
+ wire_format.WIRETYPE_VARINT, _DecodeVarint32, wire_format.ZigZagDecode)
+SInt64Decoder = _ModifiedDecoder(
+ wire_format.WIRETYPE_VARINT, _DecodeVarint, wire_format.ZigZagDecode)
+
+# Note that Python conveniently guarantees that when using the '<' prefix on
+# formats, they will also have the same size across all platforms (as opposed
+# to without the prefix, where their sizes depend on the C compiler's basic
+# type sizes).
+Fixed32Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, '<I')
+Fixed64Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, '<Q')
+SFixed32Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, '<i')
+SFixed64Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, '<q')
+FloatDecoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, '<f')
+DoubleDecoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, '<d')
+
+BoolDecoder = _ModifiedDecoder(
+ wire_format.WIRETYPE_VARINT, _DecodeVarint, bool)
+
+
+def StringDecoder(field_number, is_repeated, is_packed, key, new_default):
+ """Returns a decoder for a string field."""
+
+ local_DecodeVarint = _DecodeVarint
+ local_unicode = unicode
+
+ assert not is_packed
+ if is_repeated:
+ tag_bytes = encoder.TagBytes(field_number,
+ wire_format.WIRETYPE_LENGTH_DELIMITED)
+ tag_len = len(tag_bytes)
+ def DecodeRepeatedField(buffer, pos, end, message, field_dict):
+ value = field_dict.get(key)
+ if value is None:
+ value = field_dict.setdefault(key, new_default(message))
+ while 1:
+ (size, pos) = local_DecodeVarint(buffer, pos)
+ new_pos = pos + size
+ if new_pos > end:
+ raise _DecodeError('Truncated string.')
+ value.append(local_unicode(buffer[pos:new_pos], 'utf-8'))
+ # Predict that the next tag is another copy of the same repeated field.
+ pos = new_pos + tag_len
+ if buffer[new_pos:pos] != tag_bytes or new_pos == end:
+ # Prediction failed. Return.
+ return new_pos
+ return DecodeRepeatedField
+ else:
+ def DecodeField(buffer, pos, end, message, field_dict):
+ (size, pos) = local_DecodeVarint(buffer, pos)
+ new_pos = pos + size
+ if new_pos > end:
+ raise _DecodeError('Truncated string.')
+ field_dict[key] = local_unicode(buffer[pos:new_pos], 'utf-8')
+ return new_pos
+ return DecodeField
+
+
+def BytesDecoder(field_number, is_repeated, is_packed, key, new_default):
+ """Returns a decoder for a bytes field."""
+
+ local_DecodeVarint = _DecodeVarint
+
+ assert not is_packed
+ if is_repeated:
+ tag_bytes = encoder.TagBytes(field_number,
+ wire_format.WIRETYPE_LENGTH_DELIMITED)
+ tag_len = len(tag_bytes)
+ def DecodeRepeatedField(buffer, pos, end, message, field_dict):
+ value = field_dict.get(key)
+ if value is None:
+ value = field_dict.setdefault(key, new_default(message))
+ while 1:
+ (size, pos) = local_DecodeVarint(buffer, pos)
+ new_pos = pos + size
+ if new_pos > end:
+ raise _DecodeError('Truncated string.')
+ value.append(buffer[pos:new_pos])
+ # Predict that the next tag is another copy of the same repeated field.
+ pos = new_pos + tag_len
+ if buffer[new_pos:pos] != tag_bytes or new_pos == end:
+ # Prediction failed. Return.
+ return new_pos
+ return DecodeRepeatedField
+ else:
+ def DecodeField(buffer, pos, end, message, field_dict):
+ (size, pos) = local_DecodeVarint(buffer, pos)
+ new_pos = pos + size
+ if new_pos > end:
+ raise _DecodeError('Truncated string.')
+ field_dict[key] = buffer[pos:new_pos]
+ return new_pos
+ return DecodeField
+
+
+def GroupDecoder(field_number, is_repeated, is_packed, key, new_default):
+ """Returns a decoder for a group field."""
+
+ end_tag_bytes = encoder.TagBytes(field_number,
+ wire_format.WIRETYPE_END_GROUP)
+ end_tag_len = len(end_tag_bytes)
+
+ assert not is_packed
+ if is_repeated:
+ tag_bytes = encoder.TagBytes(field_number,
+ wire_format.WIRETYPE_START_GROUP)
+ tag_len = len(tag_bytes)
+ def DecodeRepeatedField(buffer, pos, end, message, field_dict):
+ value = field_dict.get(key)
+ if value is None:
+ value = field_dict.setdefault(key, new_default(message))
+ while 1:
+ value = field_dict.get(key)
+ if value is None:
+ value = field_dict.setdefault(key, new_default(message))
+ # Read sub-message.
+ pos = value.add()._InternalParse(buffer, pos, end)
+ # Read end tag.
+ new_pos = pos+end_tag_len
+ if buffer[pos:new_pos] != end_tag_bytes or new_pos > end:
+ raise _DecodeError('Missing group end tag.')
+ # Predict that the next tag is another copy of the same repeated field.
+ pos = new_pos + tag_len
+ if buffer[new_pos:pos] != tag_bytes or new_pos == end:
+ # Prediction failed. Return.
+ return new_pos
+ return DecodeRepeatedField
+ else:
+ def DecodeField(buffer, pos, end, message, field_dict):
+ value = field_dict.get(key)
+ if value is None:
+ value = field_dict.setdefault(key, new_default(message))
+ # Read sub-message.
+ pos = value._InternalParse(buffer, pos, end)
+ # Read end tag.
+ new_pos = pos+end_tag_len
+ if buffer[pos:new_pos] != end_tag_bytes or new_pos > end:
+ raise _DecodeError('Missing group end tag.')
+ return new_pos
+ return DecodeField
+
+
+def MessageDecoder(field_number, is_repeated, is_packed, key, new_default):
+ """Returns a decoder for a message field."""
+
+ local_DecodeVarint = _DecodeVarint
+
+ assert not is_packed
+ if is_repeated:
+ tag_bytes = encoder.TagBytes(field_number,
+ wire_format.WIRETYPE_LENGTH_DELIMITED)
+ tag_len = len(tag_bytes)
+ def DecodeRepeatedField(buffer, pos, end, message, field_dict):
+ value = field_dict.get(key)
+ if value is None:
+ value = field_dict.setdefault(key, new_default(message))
+ while 1:
+ value = field_dict.get(key)
+ if value is None:
+ value = field_dict.setdefault(key, new_default(message))
+ # Read length.
+ (size, pos) = local_DecodeVarint(buffer, pos)
+ new_pos = pos + size
+ if new_pos > end:
+ raise _DecodeError('Truncated message.')
+ # Read sub-message.
+ if value.add()._InternalParse(buffer, pos, new_pos) != new_pos:
+ # The only reason _InternalParse would return early is if it
+ # encountered an end-group tag.
+ raise _DecodeError('Unexpected end-group tag.')
+ # Predict that the next tag is another copy of the same repeated field.
+ pos = new_pos + tag_len
+ if buffer[new_pos:pos] != tag_bytes or new_pos == end:
+ # Prediction failed. Return.
+ return new_pos
+ return DecodeRepeatedField
+ else:
+ def DecodeField(buffer, pos, end, message, field_dict):
+ value = field_dict.get(key)
+ if value is None:
+ value = field_dict.setdefault(key, new_default(message))
+ # Read length.
+ (size, pos) = local_DecodeVarint(buffer, pos)
+ new_pos = pos + size
+ if new_pos > end:
+ raise _DecodeError('Truncated message.')
+ # Read sub-message.
+ if value._InternalParse(buffer, pos, new_pos) != new_pos:
+ # The only reason _InternalParse would return early is if it encountered
+ # an end-group tag.
+ raise _DecodeError('Unexpected end-group tag.')
+ return new_pos
+ return DecodeField
+
+
+# --------------------------------------------------------------------
+
+MESSAGE_SET_ITEM_TAG = encoder.TagBytes(1, wire_format.WIRETYPE_START_GROUP)
+
+def MessageSetItemDecoder(extensions_by_number):
+ """Returns a decoder for a MessageSet item.
+
+ The parameter is the _extensions_by_number map for the message class.
+
+ The message set message looks like this:
+ message MessageSet {
+ repeated group Item = 1 {
+ required int32 type_id = 2;
+ required string message = 3;
+ }
+ }
+ """
+
+ type_id_tag_bytes = encoder.TagBytes(2, wire_format.WIRETYPE_VARINT)
+ message_tag_bytes = encoder.TagBytes(3, wire_format.WIRETYPE_LENGTH_DELIMITED)
+ item_end_tag_bytes = encoder.TagBytes(1, wire_format.WIRETYPE_END_GROUP)
+
+ local_ReadTag = ReadTag
+ local_DecodeVarint = _DecodeVarint
+ local_SkipField = SkipField
+
+ def DecodeItem(buffer, pos, end, message, field_dict):
+ type_id = -1
+ message_start = -1
+ message_end = -1
+
+ # Technically, type_id and message can appear in any order, so we need
+ # a little loop here.
+ while 1:
+ (tag_bytes, pos) = local_ReadTag(buffer, pos)
+ if tag_bytes == type_id_tag_bytes:
+ (type_id, pos) = local_DecodeVarint(buffer, pos)
+ elif tag_bytes == message_tag_bytes:
+ (size, message_start) = local_DecodeVarint(buffer, pos)
+ pos = message_end = message_start + size
+ elif tag_bytes == item_end_tag_bytes:
+ break
+ else:
+ pos = SkipField(buffer, pos, end, tag_bytes)
+ if pos == -1:
+ raise _DecodeError('Missing group end tag.')
+
+ if pos > end:
+ raise _DecodeError('Truncated message.')
+
+ if type_id == -1:
+ raise _DecodeError('MessageSet item missing type_id.')
+ if message_start == -1:
+ raise _DecodeError('MessageSet item missing message.')
+
+ extension = extensions_by_number.get(type_id)
+ if extension is not None:
+ value = field_dict.get(extension)
+ if value is None:
+ value = field_dict.setdefault(
+ extension, extension.message_type._concrete_class())
+ if value._InternalParse(buffer, message_start,message_end) != message_end:
+ # The only reason _InternalParse would return early is if it encountered
+ # an end-group tag.
+ raise _DecodeError('Unexpected end-group tag.')
+
+ return pos
+
+ return DecodeItem
+
+# --------------------------------------------------------------------
+# Optimization is not as heavy here because calls to SkipField() are rare,
+# except for handling end-group tags.
+
+def _SkipVarint(buffer, pos, end):
+ """Skip a varint value. Returns the new position."""
+
+ while ord(buffer[pos]) & 0x80:
+ pos += 1
+ pos += 1
+ if pos > end:
+ raise _DecodeError('Truncated message.')
+ return pos
+
+def _SkipFixed64(buffer, pos, end):
+ """Skip a fixed64 value. Returns the new position."""
+
+ pos += 8
+ if pos > end:
+ raise _DecodeError('Truncated message.')
+ return pos
+
+def _SkipLengthDelimited(buffer, pos, end):
+ """Skip a length-delimited value. Returns the new position."""
+
+ (size, pos) = _DecodeVarint(buffer, pos)
+ pos += size
+ if pos > end:
+ raise _DecodeError('Truncated message.')
+ return pos
+
+def _SkipGroup(buffer, pos, end):
+ """Skip sub-group. Returns the new position."""
+
+ while 1:
+ (tag_bytes, pos) = ReadTag(buffer, pos)
+ new_pos = SkipField(buffer, pos, end, tag_bytes)
+ if new_pos == -1:
+ return pos
+ pos = new_pos
+
+def _EndGroup(buffer, pos, end):
+ """Skipping an END_GROUP tag returns -1 to tell the parent loop to break."""
+
+ return -1
+
+def _SkipFixed32(buffer, pos, end):
+ """Skip a fixed32 value. Returns the new position."""
+
+ pos += 4
+ if pos > end:
+ raise _DecodeError('Truncated message.')
+ return pos
+
+def _RaiseInvalidWireType(buffer, pos, end):
+ """Skip function for unknown wire types. Raises an exception."""
+
+ raise _DecodeError('Tag had invalid wire type.')
+
+def _FieldSkipper():
+ """Constructs the SkipField function."""
+
+ WIRETYPE_TO_SKIPPER = [
+ _SkipVarint,
+ _SkipFixed64,
+ _SkipLengthDelimited,
+ _SkipGroup,
+ _EndGroup,
+ _SkipFixed32,
+ _RaiseInvalidWireType,
+ _RaiseInvalidWireType,
+ ]
+
+ wiretype_mask = wire_format.TAG_TYPE_MASK
+ local_ord = ord
+
+ def SkipField(buffer, pos, end, tag_bytes):
+ """Skips a field with the specified tag.
+
+ |pos| should point to the byte immediately after the tag.
+
+ Returns:
+ The new position (after the tag value), or -1 if the tag is an end-group
+ tag (in which case the calling loop should break).
+ """
-# Note that much of this code is ported from //net/proto/ProtocolBuffer, and
-# that the interface is strongly inspired by WireFormat from the C++ proto2
-# implementation.
-
-
-class Decoder(object):
-
- """Decodes logical protocol buffer fields from the wire."""
+ # The wire type is always in the first byte since varints are little-endian.
+ wire_type = local_ord(tag_bytes[0]) & wiretype_mask
+ return WIRETYPE_TO_SKIPPER[wire_type](buffer, pos, end)
- def __init__(self, s):
- """Initializes the decoder to read from s.
+ return SkipField
- Args:
- s: An immutable sequence of bytes, which must be accessible
- via the Python buffer() primitive (i.e., buffer(s)).
- """
- self._stream = input_stream.InputStream(s)
-
- def EndOfStream(self):
- """Returns true iff we've reached the end of the bytes we're reading."""
- return self._stream.EndOfStream()
-
- def Position(self):
- """Returns the 0-indexed position in |s|."""
- return self._stream.Position()
-
- def ReadFieldNumberAndWireType(self):
- """Reads a tag from the wire. Returns a (field_number, wire_type) pair."""
- tag_and_type = self.ReadUInt32()
- return wire_format.UnpackTag(tag_and_type)
-
- def SkipBytes(self, bytes):
- """Skips the specified number of bytes on the wire."""
- self._stream.SkipBytes(bytes)
-
- # Note that the Read*() methods below are not exactly symmetrical with the
- # corresponding Encoder.Append*() methods. Those Encoder methods first
- # encode a tag, but the Read*() methods below assume that the tag has already
- # been read, and that the client wishes to read a field of the specified type
- # starting at the current position.
-
- def ReadInt32(self):
- """Reads and returns a signed, varint-encoded, 32-bit integer."""
- return self._stream.ReadVarint32()
-
- def ReadInt64(self):
- """Reads and returns a signed, varint-encoded, 64-bit integer."""
- return self._stream.ReadVarint64()
-
- def ReadUInt32(self):
- """Reads and returns an signed, varint-encoded, 32-bit integer."""
- return self._stream.ReadVarUInt32()
-
- def ReadUInt64(self):
- """Reads and returns an signed, varint-encoded,64-bit integer."""
- return self._stream.ReadVarUInt64()
-
- def ReadSInt32(self):
- """Reads and returns a signed, zigzag-encoded, varint-encoded,
- 32-bit integer."""
- return wire_format.ZigZagDecode(self._stream.ReadVarUInt32())
-
- def ReadSInt64(self):
- """Reads and returns a signed, zigzag-encoded, varint-encoded,
- 64-bit integer."""
- return wire_format.ZigZagDecode(self._stream.ReadVarUInt64())
-
- def ReadFixed32(self):
- """Reads and returns an unsigned, fixed-width, 32-bit integer."""
- return self._stream.ReadLittleEndian32()
-
- def ReadFixed64(self):
- """Reads and returns an unsigned, fixed-width, 64-bit integer."""
- return self._stream.ReadLittleEndian64()
-
- def ReadSFixed32(self):
- """Reads and returns a signed, fixed-width, 32-bit integer."""
- value = self._stream.ReadLittleEndian32()
- if value >= (1 << 31):
- value -= (1 << 32)
- return value
-
- def ReadSFixed64(self):
- """Reads and returns a signed, fixed-width, 64-bit integer."""
- value = self._stream.ReadLittleEndian64()
- if value >= (1 << 63):
- value -= (1 << 64)
- return value
-
- def ReadFloat(self):
- """Reads and returns a 4-byte floating-point number."""
- serialized = self._stream.ReadBytes(4)
- 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(wire_format.FORMAT_DOUBLE_LITTLE_ENDIAN, serialized)[0]
-
- def ReadBool(self):
- """Reads and returns a bool."""
- i = self._stream.ReadVarUInt32()
- return bool(i)
-
- def ReadEnum(self):
- """Reads and returns an enum value."""
- return self._stream.ReadVarUInt32()
-
- def ReadString(self):
- """Reads and returns a length-delimited string."""
- bytes = self.ReadBytes()
- return unicode(bytes, 'utf-8')
-
- def ReadBytes(self):
- """Reads and returns a length-delimited byte sequence."""
- length = self._stream.ReadVarUInt32()
- return self._stream.ReadBytes(length)
-
- def ReadMessageInto(self, msg):
- """Calls msg.MergeFromString() to merge
- length-delimited serialized message data into |msg|.
-
- REQUIRES: The decoder must be positioned at the serialized "length"
- prefix to a length-delmiited serialized message.
-
- POSTCONDITION: The decoder is positioned just after the
- serialized message, and we have merged those serialized
- contents into |msg|.
- """
- length = self._stream.ReadVarUInt32()
- sub_buffer = self._stream.GetSubBuffer(length)
- num_bytes_used = msg.MergeFromString(sub_buffer)
- if num_bytes_used != length:
- raise message.DecodeError(
- 'Submessage told to deserialize from %d-byte encoding, '
- 'but used only %d bytes' % (length, num_bytes_used))
- self._stream.SkipBytes(num_bytes_used)
-
- def ReadGroupInto(self, expected_field_number, group):
- """Calls group.MergeFromString() to merge
- END_GROUP-delimited serialized message data into |group|.
- We'll raise an exception if we don't find an END_GROUP
- tag immediately after the serialized message contents.
-
- REQUIRES: The decoder is positioned just after the START_GROUP
- tag for this group.
-
- POSTCONDITION: The decoder is positioned just after the
- END_GROUP tag for this group, and we have merged
- the contents of the group into |group|.
- """
- sub_buffer = self._stream.GetSubBuffer() # No a priori length limit.
- num_bytes_used = group.MergeFromString(sub_buffer)
- if num_bytes_used < 0:
- raise message.DecodeError('Group message reported negative bytes read.')
- self._stream.SkipBytes(num_bytes_used)
- field_number, field_type = self.ReadFieldNumberAndWireType()
- if field_type != wire_format.WIRETYPE_END_GROUP:
- raise message.DecodeError('Group message did not end with an END_GROUP.')
- if field_number != expected_field_number:
- raise message.DecodeError('END_GROUP tag had field '
- 'number %d, was expecting field number %d' % (
- field_number, expected_field_number))
- # We're now positioned just after the END_GROUP tag. Perfect.
+SkipField = _FieldSkipper()
diff --git a/python/google/protobuf/internal/decoder_test.py b/python/google/protobuf/internal/decoder_test.py
deleted file mode 100755
index 98e46472..00000000
--- a/python/google/protobuf/internal/decoder_test.py
+++ /dev/null
@@ -1,256 +0,0 @@
-#! /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.
-
-"""Test for google.protobuf.internal.decoder."""
-
-__author__ = 'robinson@google.com (Will Robinson)'
-
-import struct
-import unittest
-from google.protobuf.internal import decoder
-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
-
-
-class DecoderTest(unittest.TestCase):
-
- def setUp(self):
- self.mox = mox.Mox()
- self.mock_stream = self.mox.CreateMock(input_stream.InputStream)
- self.mock_message = self.mox.CreateMock(message.Message)
-
- def testReadFieldNumberAndWireType(self):
- # Test field numbers that will require various varint sizes.
- for expected_field_number in (1, 15, 16, 2047, 2048):
- for expected_wire_type in range(6): # Highest-numbered wiretype is 5.
- e = encoder.Encoder()
- e.AppendTag(expected_field_number, expected_wire_type)
- s = e.ToString()
- d = decoder.Decoder(s)
- field_number, wire_type = d.ReadFieldNumberAndWireType()
- self.assertEqual(expected_field_number, field_number)
- self.assertEqual(expected_wire_type, wire_type)
-
- def ReadScalarTestHelper(self, test_name, decoder_method, expected_result,
- expected_stream_method_name,
- stream_method_return, *args):
- """Helper for testReadScalars below.
-
- Calls one of the Decoder.Read*() methods and ensures that the results are
- as expected.
-
- Args:
- test_name: Name of this test, used for logging only.
- decoder_method: Unbound decoder.Decoder method to call.
- expected_result: Value we expect returned from decoder_method().
- expected_stream_method_name: (string) Name of the InputStream
- method we expect Decoder to call to actually read the value
- on the wire.
- stream_method_return: Value our mocked-out stream method should
- return to the decoder.
- args: Additional arguments that we expect to be passed to the
- stream method.
- """
- logging.info('Testing %s scalar input.\n'
- 'Calling %r(), and expecting that to call the '
- 'stream method %s(%r), which will return %r. Finally, '
- 'expecting the Decoder method to return %r'% (
- test_name, decoder_method,
- expected_stream_method_name, args, stream_method_return,
- expected_result))
-
- d = decoder.Decoder('')
- d._stream = self.mock_stream
- if decoder_method in (decoder.Decoder.ReadString,
- decoder.Decoder.ReadBytes):
- self.mock_stream.ReadVarUInt32().AndReturn(len(stream_method_return))
- # We have to use names instead of methods to work around some
- # mox weirdness. (ResetAll() is overzealous).
- expected_stream_method = getattr(self.mock_stream,
- expected_stream_method_name)
- expected_stream_method(*args).AndReturn(stream_method_return)
-
- self.mox.ReplayAll()
- result = decoder_method(d)
- self.assertEqual(expected_result, result)
- self.assert_(isinstance(result, type(expected_result)))
- 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 = [
- ['int32', decoder.Decoder.ReadInt32, 0, 'ReadVarint32', 0],
- ['int64', decoder.Decoder.ReadInt64, 0, 'ReadVarint64', 0],
- ['uint32', decoder.Decoder.ReadUInt32, 0, 'ReadVarUInt32', 0],
- ['uint64', decoder.Decoder.ReadUInt64, 0, 'ReadVarUInt64', 0],
- ['fixed32', decoder.Decoder.ReadFixed32, 0xffffffff,
- 'ReadLittleEndian32', 0xffffffff],
- ['fixed64', decoder.Decoder.ReadFixed64, 0xffffffffffffffff,
- 'ReadLittleEndian64', 0xffffffffffffffff],
- ['sfixed32', decoder.Decoder.ReadSFixed32, long(-1),
- 'ReadLittleEndian32', long(0xffffffff)],
- ['sfixed64', decoder.Decoder.ReadSFixed64, long(-1),
- 'ReadLittleEndian64', 0xffffffffffffffff],
- ['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,
- unicode(test_string, 'utf-8'), 'ReadBytes', test_string,
- len(test_string)],
- ['utf8-string', decoder.Decoder.ReadString,
- unicode(test_string, 'utf-8'), 'ReadBytes', test_string,
- len(test_string)],
- ['bytes', decoder.Decoder.ReadBytes,
- test_string, 'ReadBytes', test_string, len(test_string)],
- # We test zigzag decoding routines more extensively below.
- ['sint32', decoder.Decoder.ReadSInt32, -1, 'ReadVarUInt32', 1],
- ['sint64', decoder.Decoder.ReadSInt64, -1, 'ReadVarUInt64', 1],
- ]
- # Ensure that we're testing different Decoder methods and using
- # different test names in all test cases above.
- self.assertEqual(len(scalar_tests), len(set(t[0] for t in scalar_tests)))
- self.assert_(len(scalar_tests) >= len(set(t[1] for t in scalar_tests)))
- for args in scalar_tests:
- self.ReadScalarTestHelper(*args)
-
- def testReadMessageInto(self):
- length = 23
- def Test(simulate_error):
- d = decoder.Decoder('')
- d._stream = self.mock_stream
- self.mock_stream.ReadVarUInt32().AndReturn(length)
- sub_buffer = object()
- self.mock_stream.GetSubBuffer(length).AndReturn(sub_buffer)
-
- if simulate_error:
- self.mock_message.MergeFromString(sub_buffer).AndReturn(length - 1)
- self.mox.ReplayAll()
- self.assertRaises(
- message.DecodeError, d.ReadMessageInto, self.mock_message)
- else:
- self.mock_message.MergeFromString(sub_buffer).AndReturn(length)
- self.mock_stream.SkipBytes(length)
- self.mox.ReplayAll()
- d.ReadMessageInto(self.mock_message)
-
- self.mox.VerifyAll()
- self.mox.ResetAll()
-
- Test(simulate_error=False)
- Test(simulate_error=True)
-
- def testReadGroupInto_Success(self):
- # Test both the empty and nonempty cases.
- for num_bytes in (5, 0):
- field_number = expected_field_number = 10
- d = decoder.Decoder('')
- d._stream = self.mock_stream
- sub_buffer = object()
- self.mock_stream.GetSubBuffer().AndReturn(sub_buffer)
- self.mock_message.MergeFromString(sub_buffer).AndReturn(num_bytes)
- self.mock_stream.SkipBytes(num_bytes)
- self.mock_stream.ReadVarUInt32().AndReturn(wire_format.PackTag(
- field_number, wire_format.WIRETYPE_END_GROUP))
- self.mox.ReplayAll()
- d.ReadGroupInto(expected_field_number, self.mock_message)
- self.mox.VerifyAll()
- self.mox.ResetAll()
-
- def ReadGroupInto_FailureTestHelper(self, bytes_read):
- d = decoder.Decoder('')
- d._stream = self.mock_stream
- sub_buffer = object()
- self.mock_stream.GetSubBuffer().AndReturn(sub_buffer)
- self.mock_message.MergeFromString(sub_buffer).AndReturn(bytes_read)
- return d
-
- def testReadGroupInto_NegativeBytesReported(self):
- expected_field_number = 10
- d = self.ReadGroupInto_FailureTestHelper(bytes_read=-1)
- self.mox.ReplayAll()
- self.assertRaises(message.DecodeError,
- d.ReadGroupInto, expected_field_number,
- self.mock_message)
- self.mox.VerifyAll()
-
- def testReadGroupInto_NoEndGroupTag(self):
- field_number = expected_field_number = 10
- num_bytes = 5
- d = self.ReadGroupInto_FailureTestHelper(bytes_read=num_bytes)
- self.mock_stream.SkipBytes(num_bytes)
- # Right field number, wrong wire type.
- self.mock_stream.ReadVarUInt32().AndReturn(wire_format.PackTag(
- field_number, wire_format.WIRETYPE_LENGTH_DELIMITED))
- self.mox.ReplayAll()
- self.assertRaises(message.DecodeError,
- d.ReadGroupInto, expected_field_number,
- self.mock_message)
- self.mox.VerifyAll()
-
- def testReadGroupInto_WrongFieldNumberInEndGroupTag(self):
- expected_field_number = 10
- field_number = expected_field_number + 1
- num_bytes = 5
- d = self.ReadGroupInto_FailureTestHelper(bytes_read=num_bytes)
- self.mock_stream.SkipBytes(num_bytes)
- # Wrong field number, right wire type.
- self.mock_stream.ReadVarUInt32().AndReturn(wire_format.PackTag(
- field_number, wire_format.WIRETYPE_END_GROUP))
- self.mox.ReplayAll()
- self.assertRaises(message.DecodeError,
- d.ReadGroupInto, expected_field_number,
- self.mock_message)
- self.mox.VerifyAll()
-
- def testSkipBytes(self):
- d = decoder.Decoder('')
- num_bytes = 1024
- self.mock_stream.SkipBytes(num_bytes)
- d._stream = self.mock_stream
- self.mox.ReplayAll()
- d.SkipBytes(num_bytes)
- self.mox.VerifyAll()
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py
index eb9f2be8..05c27452 100755
--- a/python/google/protobuf/internal/descriptor_test.py
+++ b/python/google/protobuf/internal/descriptor_test.py
@@ -35,16 +35,30 @@
__author__ = 'robinson@google.com (Will Robinson)'
import unittest
+from google.protobuf import unittest_import_pb2
+from google.protobuf import unittest_pb2
from google.protobuf import descriptor_pb2
from google.protobuf import descriptor
+from google.protobuf import text_format
+
+
+TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII = """
+name: 'TestEmptyMessage'
+"""
+
class DescriptorTest(unittest.TestCase):
def setUp(self):
+ self.my_file = descriptor.FileDescriptor(
+ name='some/filename/some.proto',
+ package='protobuf_unittest'
+ )
self.my_enum = descriptor.EnumDescriptor(
name='ForeignEnum',
full_name='protobuf_unittest.ForeignEnum',
- filename='ForeignEnum',
+ filename=None,
+ file=self.my_file,
values=[
descriptor.EnumValueDescriptor(name='FOREIGN_FOO', index=0, number=4),
descriptor.EnumValueDescriptor(name='FOREIGN_BAR', index=1, number=5),
@@ -53,7 +67,8 @@ class DescriptorTest(unittest.TestCase):
self.my_message = descriptor.Descriptor(
name='NestedMessage',
full_name='protobuf_unittest.TestAllTypes.NestedMessage',
- filename='some/filename/some.proto',
+ filename=None,
+ file=self.my_file,
containing_type=None,
fields=[
descriptor.FieldDescriptor(
@@ -61,7 +76,7 @@ class DescriptorTest(unittest.TestCase):
full_name='protobuf_unittest.TestAllTypes.NestedMessage.bb',
index=0, number=1,
type=5, cpp_type=1, label=1,
- default_value=0,
+ has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None),
],
@@ -80,6 +95,7 @@ class DescriptorTest(unittest.TestCase):
self.my_service = descriptor.ServiceDescriptor(
name='TestServiceWithOptions',
full_name='protobuf_unittest.TestServiceWithOptions',
+ file=self.my_file,
index=0,
methods=[
self.my_method
@@ -109,5 +125,210 @@ class DescriptorTest(unittest.TestCase):
self.assertEqual(self.my_service.GetOptions(),
descriptor_pb2.ServiceOptions())
+ def testFileDescriptorReferences(self):
+ self.assertEqual(self.my_enum.file, self.my_file)
+ self.assertEqual(self.my_message.file, self.my_file)
+
+ def testFileDescriptor(self):
+ self.assertEqual(self.my_file.name, 'some/filename/some.proto')
+ self.assertEqual(self.my_file.package, 'protobuf_unittest')
+
+
+class DescriptorCopyToProtoTest(unittest.TestCase):
+ """Tests for CopyTo functions of Descriptor."""
+
+ def _AssertProtoEqual(self, actual_proto, expected_class, expected_ascii):
+ expected_proto = expected_class()
+ text_format.Merge(expected_ascii, expected_proto)
+
+ self.assertEqual(
+ actual_proto, expected_proto,
+ 'Not equal,\nActual:\n%s\nExpected:\n%s\n'
+ % (str(actual_proto), str(expected_proto)))
+
+ def _InternalTestCopyToProto(self, desc, expected_proto_class,
+ expected_proto_ascii):
+ actual = expected_proto_class()
+ desc.CopyToProto(actual)
+ self._AssertProtoEqual(
+ actual, expected_proto_class, expected_proto_ascii)
+
+ def testCopyToProto_EmptyMessage(self):
+ self._InternalTestCopyToProto(
+ unittest_pb2.TestEmptyMessage.DESCRIPTOR,
+ descriptor_pb2.DescriptorProto,
+ TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII)
+
+ def testCopyToProto_NestedMessage(self):
+ TEST_NESTED_MESSAGE_ASCII = """
+ name: 'NestedMessage'
+ field: <
+ name: 'bb'
+ number: 1
+ label: 1 # Optional
+ type: 5 # TYPE_INT32
+ >
+ """
+
+ self._InternalTestCopyToProto(
+ unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR,
+ descriptor_pb2.DescriptorProto,
+ TEST_NESTED_MESSAGE_ASCII)
+
+ def testCopyToProto_ForeignNestedMessage(self):
+ TEST_FOREIGN_NESTED_ASCII = """
+ name: 'TestForeignNested'
+ field: <
+ name: 'foreign_nested'
+ number: 1
+ label: 1 # Optional
+ type: 11 # TYPE_MESSAGE
+ type_name: '.protobuf_unittest.TestAllTypes.NestedMessage'
+ >
+ """
+
+ self._InternalTestCopyToProto(
+ unittest_pb2.TestForeignNested.DESCRIPTOR,
+ descriptor_pb2.DescriptorProto,
+ TEST_FOREIGN_NESTED_ASCII)
+
+ def testCopyToProto_ForeignEnum(self):
+ TEST_FOREIGN_ENUM_ASCII = """
+ name: 'ForeignEnum'
+ value: <
+ name: 'FOREIGN_FOO'
+ number: 4
+ >
+ value: <
+ name: 'FOREIGN_BAR'
+ number: 5
+ >
+ value: <
+ name: 'FOREIGN_BAZ'
+ number: 6
+ >
+ """
+
+ self._InternalTestCopyToProto(
+ unittest_pb2._FOREIGNENUM,
+ descriptor_pb2.EnumDescriptorProto,
+ TEST_FOREIGN_ENUM_ASCII)
+
+ def testCopyToProto_Options(self):
+ TEST_DEPRECATED_FIELDS_ASCII = """
+ name: 'TestDeprecatedFields'
+ field: <
+ name: 'deprecated_int32'
+ number: 1
+ label: 1 # Optional
+ type: 5 # TYPE_INT32
+ options: <
+ deprecated: true
+ >
+ >
+ """
+
+ self._InternalTestCopyToProto(
+ unittest_pb2.TestDeprecatedFields.DESCRIPTOR,
+ descriptor_pb2.DescriptorProto,
+ TEST_DEPRECATED_FIELDS_ASCII)
+
+ def testCopyToProto_AllExtensions(self):
+ TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII = """
+ name: 'TestEmptyMessageWithExtensions'
+ extension_range: <
+ start: 1
+ end: 536870912
+ >
+ """
+
+ self._InternalTestCopyToProto(
+ unittest_pb2.TestEmptyMessageWithExtensions.DESCRIPTOR,
+ descriptor_pb2.DescriptorProto,
+ TEST_EMPTY_MESSAGE_WITH_EXTENSIONS_ASCII)
+
+ def testCopyToProto_SeveralExtensions(self):
+ TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII = """
+ name: 'TestMultipleExtensionRanges'
+ extension_range: <
+ start: 42
+ end: 43
+ >
+ extension_range: <
+ start: 4143
+ end: 4244
+ >
+ extension_range: <
+ start: 65536
+ end: 536870912
+ >
+ """
+
+ self._InternalTestCopyToProto(
+ unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR,
+ descriptor_pb2.DescriptorProto,
+ TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII)
+
+ def testCopyToProto_FileDescriptor(self):
+ UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = ("""
+ name: 'google/protobuf/unittest_import.proto'
+ package: 'protobuf_unittest_import'
+ message_type: <
+ name: 'ImportMessage'
+ field: <
+ name: 'd'
+ number: 1
+ label: 1 # Optional
+ type: 5 # TYPE_INT32
+ >
+ >
+ """ +
+ """enum_type: <
+ name: 'ImportEnum'
+ value: <
+ name: 'IMPORT_FOO'
+ number: 7
+ >
+ value: <
+ name: 'IMPORT_BAR'
+ number: 8
+ >
+ value: <
+ name: 'IMPORT_BAZ'
+ number: 9
+ >
+ >
+ options: <
+ java_package: 'com.google.protobuf.test'
+ optimize_for: 1 # SPEED
+ >
+ """)
+
+ self._InternalTestCopyToProto(
+ unittest_import_pb2.DESCRIPTOR,
+ descriptor_pb2.FileDescriptorProto,
+ UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII)
+
+ def testCopyToProto_ServiceDescriptor(self):
+ TEST_SERVICE_ASCII = """
+ name: 'TestService'
+ method: <
+ name: 'Foo'
+ input_type: '.protobuf_unittest.FooRequest'
+ output_type: '.protobuf_unittest.FooResponse'
+ >
+ method: <
+ name: 'Bar'
+ input_type: '.protobuf_unittest.BarRequest'
+ output_type: '.protobuf_unittest.BarResponse'
+ >
+ """
+
+ self._InternalTestCopyToProto(
+ unittest_pb2.TestService.DESCRIPTOR,
+ descriptor_pb2.ServiceDescriptorProto,
+ TEST_SERVICE_ASCII)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/python/google/protobuf/internal/encoder.py b/python/google/protobuf/internal/encoder.py
index 3ec3b2b1..aa05d5b3 100755
--- a/python/google/protobuf/internal/encoder.py
+++ b/python/google/protobuf/internal/encoder.py
@@ -28,253 +28,659 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Class for encoding protocol message primitives.
+"""Code for encoding protocol message primitives.
Contains the logic for encoding every logical protocol field type
into one of the 5 physical wire types.
+
+This code is designed to push the Python interpreter's performance to the
+limits.
+
+The basic idea is that at startup time, for every field (i.e. every
+FieldDescriptor) we construct two functions: a "sizer" and an "encoder". The
+sizer takes a value of this field's type and computes its byte size. The
+encoder takes a writer function and a value. It encodes the value into byte
+strings and invokes the writer function to write those strings. Typically the
+writer function is the write() method of a cStringIO.
+
+We try to do as much work as possible when constructing the writer and the
+sizer rather than when calling them. In particular:
+* We copy any needed global functions to local variables, so that we do not need
+ to do costly global table lookups at runtime.
+* Similarly, we try to do any attribute lookups at startup time if possible.
+* Every field's tag is encoded to bytes at startup, since it can't change at
+ runtime.
+* Whatever component of the field size we can compute at startup, we do.
+* We *avoid* sharing code if doing so would make the code slower and not sharing
+ does not burden us too much. For example, encoders for repeated fields do
+ not just call the encoders for singular fields in a loop because this would
+ add an extra function call overhead for every loop iteration; instead, we
+ manually inline the single-value encoder into the loop.
+* If a Python function lacks a return statement, Python actually generates
+ instructions to pop the result of the last statement off the stack, push
+ None onto the stack, and then return that. If we really don't care what
+ value is returned, then we can save two instructions by returning the
+ result of the last statement. It looks funny but it helps.
+* We assume that type and bounds checking has happened at a higher level.
"""
-__author__ = 'robinson@google.com (Will Robinson)'
+__author__ = 'kenton@google.com (Kenton Varda)'
import struct
-from google.protobuf import message
from google.protobuf.internal import wire_format
-from google.protobuf.internal import output_stream
-
-
-# Note that much of this code is ported from //net/proto/ProtocolBuffer, and
-# that the interface is strongly inspired by WireFormat from the C++ proto2
-# implementation.
-
-
-class Encoder(object):
-
- """Encodes logical protocol buffer fields to the wire format."""
-
- def __init__(self):
- self._stream = output_stream.OutputStream()
-
- def ToString(self):
- """Returns all values encoded in this object as a string."""
- return self._stream.ToString()
-
- # Append*NoTag methods. These are necessary for serializing packed
- # repeated fields. The Append*() methods call these methods to do
- # the actual serialization.
- def AppendInt32NoTag(self, value):
- """Appends a 32-bit integer to our buffer, varint-encoded."""
- self._stream.AppendVarint32(value)
-
- def AppendInt64NoTag(self, value):
- """Appends a 64-bit integer to our buffer, varint-encoded."""
- self._stream.AppendVarint64(value)
-
- def AppendUInt32NoTag(self, unsigned_value):
- """Appends an unsigned 32-bit integer to our buffer, varint-encoded."""
- self._stream.AppendVarUInt32(unsigned_value)
-
- def AppendUInt64NoTag(self, unsigned_value):
- """Appends an unsigned 64-bit integer to our buffer, varint-encoded."""
- self._stream.AppendVarUInt64(unsigned_value)
-
- def AppendSInt32NoTag(self, value):
- """Appends a 32-bit integer to our buffer, zigzag-encoded and then
- varint-encoded.
- """
- zigzag_value = wire_format.ZigZagEncode(value)
- self._stream.AppendVarUInt32(zigzag_value)
-
- def AppendSInt64NoTag(self, value):
- """Appends a 64-bit integer to our buffer, zigzag-encoded and then
- varint-encoded.
- """
- zigzag_value = wire_format.ZigZagEncode(value)
- self._stream.AppendVarUInt64(zigzag_value)
-
- def AppendFixed32NoTag(self, unsigned_value):
- """Appends an unsigned 32-bit integer to our buffer, in little-endian
- byte-order.
- """
- self._stream.AppendLittleEndian32(unsigned_value)
-
- def AppendFixed64NoTag(self, unsigned_value):
- """Appends an unsigned 64-bit integer to our buffer, in little-endian
- byte-order.
- """
- self._stream.AppendLittleEndian64(unsigned_value)
-
- def AppendSFixed32NoTag(self, value):
- """Appends a signed 32-bit integer to our buffer, in little-endian
- byte-order.
- """
- sign = (value & 0x80000000) and -1 or 0
- if value >> 32 != sign:
- raise message.EncodeError('SFixed32 out of range: %d' % value)
- self._stream.AppendLittleEndian32(value & 0xffffffff)
-
- def AppendSFixed64NoTag(self, value):
- """Appends a signed 64-bit integer to our buffer, in little-endian
- byte-order.
- """
- sign = (value & 0x8000000000000000) and -1 or 0
- if value >> 64 != sign:
- raise message.EncodeError('SFixed64 out of range: %d' % value)
- self._stream.AppendLittleEndian64(value & 0xffffffffffffffff)
-
- def AppendFloatNoTag(self, value):
- """Appends a floating-point number to our buffer."""
- 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(wire_format.FORMAT_DOUBLE_LITTLE_ENDIAN, value))
-
- def AppendBoolNoTag(self, value):
- """Appends a boolean to our buffer."""
- self.AppendInt32NoTag(value)
-
- def AppendEnumNoTag(self, value):
- """Appends an enum value to our buffer."""
- self.AppendInt32NoTag(value)
-
-
- # All the Append*() methods below first append a tag+type pair to the buffer
- # before appending the specified value.
-
- def AppendInt32(self, field_number, value):
- """Appends a 32-bit integer to our buffer, varint-encoded."""
- self.AppendTag(field_number, wire_format.WIRETYPE_VARINT)
- self.AppendInt32NoTag(value)
-
- def AppendInt64(self, field_number, value):
- """Appends a 64-bit integer to our buffer, varint-encoded."""
- self.AppendTag(field_number, wire_format.WIRETYPE_VARINT)
- self.AppendInt64NoTag(value)
-
- def AppendUInt32(self, field_number, unsigned_value):
- """Appends an unsigned 32-bit integer to our buffer, varint-encoded."""
- self.AppendTag(field_number, wire_format.WIRETYPE_VARINT)
- self.AppendUInt32NoTag(unsigned_value)
-
- def AppendUInt64(self, field_number, unsigned_value):
- """Appends an unsigned 64-bit integer to our buffer, varint-encoded."""
- self.AppendTag(field_number, wire_format.WIRETYPE_VARINT)
- self.AppendUInt64NoTag(unsigned_value)
-
- def AppendSInt32(self, field_number, value):
- """Appends a 32-bit integer to our buffer, zigzag-encoded and then
- varint-encoded.
- """
- self.AppendTag(field_number, wire_format.WIRETYPE_VARINT)
- self.AppendSInt32NoTag(value)
-
- def AppendSInt64(self, field_number, value):
- """Appends a 64-bit integer to our buffer, zigzag-encoded and then
- varint-encoded.
- """
- self.AppendTag(field_number, wire_format.WIRETYPE_VARINT)
- self.AppendSInt64NoTag(value)
-
- def AppendFixed32(self, field_number, unsigned_value):
- """Appends an unsigned 32-bit integer to our buffer, in little-endian
- byte-order.
- """
- self.AppendTag(field_number, wire_format.WIRETYPE_FIXED32)
- self.AppendFixed32NoTag(unsigned_value)
-
- def AppendFixed64(self, field_number, unsigned_value):
- """Appends an unsigned 64-bit integer to our buffer, in little-endian
- byte-order.
- """
- self.AppendTag(field_number, wire_format.WIRETYPE_FIXED64)
- self.AppendFixed64NoTag(unsigned_value)
-
- def AppendSFixed32(self, field_number, value):
- """Appends a signed 32-bit integer to our buffer, in little-endian
- byte-order.
- """
- self.AppendTag(field_number, wire_format.WIRETYPE_FIXED32)
- self.AppendSFixed32NoTag(value)
-
- def AppendSFixed64(self, field_number, value):
- """Appends a signed 64-bit integer to our buffer, in little-endian
- byte-order.
- """
- self.AppendTag(field_number, wire_format.WIRETYPE_FIXED64)
- self.AppendSFixed64NoTag(value)
-
- def AppendFloat(self, field_number, value):
- """Appends a floating-point number to our buffer."""
- self.AppendTag(field_number, wire_format.WIRETYPE_FIXED32)
- self.AppendFloatNoTag(value)
-
- def AppendDouble(self, field_number, value):
- """Appends a double-precision floating-point number to our buffer."""
- self.AppendTag(field_number, wire_format.WIRETYPE_FIXED64)
- self.AppendDoubleNoTag(value)
-
- def AppendBool(self, field_number, value):
- """Appends a boolean to our buffer."""
- self.AppendInt32(field_number, value)
-
- def AppendEnum(self, field_number, value):
- """Appends an enum value to our buffer."""
- self.AppendInt32(field_number, value)
-
- def AppendString(self, field_number, value):
- """Appends a length-prefixed unicode string, encoded as UTF-8 to our buffer,
- with the length varint-encoded.
- """
- self.AppendBytes(field_number, value.encode('utf-8'))
-
- def AppendBytes(self, field_number, value):
- """Appends a length-prefixed sequence of bytes to our buffer, with the
- length varint-encoded.
- """
- self.AppendTag(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
- self._stream.AppendVarUInt32(len(value))
- self._stream.AppendRawBytes(value)
-
- # TODO(robinson): For AppendGroup() and AppendMessage(), we'd really like to
- # avoid the extra string copy here. We can do so if we widen the Message
- # interface to be able to serialize to a stream in addition to a string. The
- # challenge when thinking ahead to the Python/C API implementation of Message
- # is finding a stream-like Python thing to which we can write raw bytes
- # from C. I'm not sure such a thing exists(?). (array.array is pretty much
- # what we want, but it's not directly exposed in the Python/C API).
-
- def AppendGroup(self, field_number, group):
- """Appends a group to our buffer.
- """
- self.AppendTag(field_number, wire_format.WIRETYPE_START_GROUP)
- self._stream.AppendRawBytes(group.SerializeToString())
- self.AppendTag(field_number, wire_format.WIRETYPE_END_GROUP)
-
- def AppendMessage(self, field_number, msg):
- """Appends a nested message to our buffer.
- """
- self.AppendTag(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
- self._stream.AppendVarUInt32(msg.ByteSize())
- self._stream.AppendRawBytes(msg.SerializeToString())
-
- def AppendMessageSetItem(self, field_number, msg):
- """Appends an item using the message set wire format.
-
- The message set message looks like this:
- message MessageSet {
- repeated group Item = 1 {
- required int32 type_id = 2;
- required string message = 3;
- }
+
+
+def _VarintSize(value):
+ """Compute the size of a varint value."""
+ if value <= 0x7f: return 1
+ if value <= 0x3fff: return 2
+ if value <= 0x1fffff: return 3
+ if value <= 0xfffffff: return 4
+ if value <= 0x7ffffffff: return 5
+ if value <= 0x3ffffffffff: return 6
+ if value <= 0x1ffffffffffff: return 7
+ if value <= 0xffffffffffffff: return 8
+ if value <= 0x7fffffffffffffff: return 9
+ return 10
+
+
+def _SignedVarintSize(value):
+ """Compute the size of a signed varint value."""
+ if value < 0: return 10
+ if value <= 0x7f: return 1
+ if value <= 0x3fff: return 2
+ if value <= 0x1fffff: return 3
+ if value <= 0xfffffff: return 4
+ if value <= 0x7ffffffff: return 5
+ if value <= 0x3ffffffffff: return 6
+ if value <= 0x1ffffffffffff: return 7
+ if value <= 0xffffffffffffff: return 8
+ if value <= 0x7fffffffffffffff: return 9
+ return 10
+
+
+def _TagSize(field_number):
+ """Returns the number of bytes required to serialize a tag with this field
+ number."""
+ # Just pass in type 0, since the type won't affect the tag+type size.
+ return _VarintSize(wire_format.PackTag(field_number, 0))
+
+
+# --------------------------------------------------------------------
+# In this section we define some generic sizers. Each of these functions
+# takes parameters specific to a particular field type, e.g. int32 or fixed64.
+# It returns another function which in turn takes parameters specific to a
+# particular field, e.g. the field number and whether it is repeated or packed.
+# Look at the next section to see how these are used.
+
+
+def _SimpleSizer(compute_value_size):
+ """A sizer which uses the function compute_value_size to compute the size of
+ each value. Typically compute_value_size is _VarintSize."""
+
+ def SpecificSizer(field_number, is_repeated, is_packed):
+ tag_size = _TagSize(field_number)
+ if is_packed:
+ local_VarintSize = _VarintSize
+ def PackedFieldSize(value):
+ result = 0
+ for element in value:
+ result += compute_value_size(element)
+ return result + local_VarintSize(result) + tag_size
+ return PackedFieldSize
+ elif is_repeated:
+ def RepeatedFieldSize(value):
+ result = tag_size * len(value)
+ for element in value:
+ result += compute_value_size(element)
+ return result
+ return RepeatedFieldSize
+ else:
+ def FieldSize(value):
+ return tag_size + compute_value_size(value)
+ return FieldSize
+
+ return SpecificSizer
+
+
+def _ModifiedSizer(compute_value_size, modify_value):
+ """Like SimpleSizer, but modify_value is invoked on each value before it is
+ passed to compute_value_size. modify_value is typically ZigZagEncode."""
+
+ def SpecificSizer(field_number, is_repeated, is_packed):
+ tag_size = _TagSize(field_number)
+ if is_packed:
+ local_VarintSize = _VarintSize
+ def PackedFieldSize(value):
+ result = 0
+ for element in value:
+ result += compute_value_size(modify_value(element))
+ return result + local_VarintSize(result) + tag_size
+ return PackedFieldSize
+ elif is_repeated:
+ def RepeatedFieldSize(value):
+ result = tag_size * len(value)
+ for element in value:
+ result += compute_value_size(modify_value(element))
+ return result
+ return RepeatedFieldSize
+ else:
+ def FieldSize(value):
+ return tag_size + compute_value_size(modify_value(value))
+ return FieldSize
+
+ return SpecificSizer
+
+
+def _FixedSizer(value_size):
+ """Like _SimpleSizer except for a fixed-size field. The input is the size
+ of one value."""
+
+ def SpecificSizer(field_number, is_repeated, is_packed):
+ tag_size = _TagSize(field_number)
+ if is_packed:
+ local_VarintSize = _VarintSize
+ def PackedFieldSize(value):
+ result = len(value) * value_size
+ return result + local_VarintSize(result) + tag_size
+ return PackedFieldSize
+ elif is_repeated:
+ element_size = value_size + tag_size
+ def RepeatedFieldSize(value):
+ return len(value) * element_size
+ return RepeatedFieldSize
+ else:
+ field_size = value_size + tag_size
+ def FieldSize(value):
+ return field_size
+ return FieldSize
+
+ return SpecificSizer
+
+
+# ====================================================================
+# Here we declare a sizer constructor for each field type. Each "sizer
+# constructor" is a function that takes (field_number, is_repeated, is_packed)
+# as parameters and returns a sizer, which in turn takes a field value as
+# a parameter and returns its encoded size.
+
+
+Int32Sizer = Int64Sizer = EnumSizer = _SimpleSizer(_SignedVarintSize)
+
+UInt32Sizer = UInt64Sizer = _SimpleSizer(_VarintSize)
+
+SInt32Sizer = SInt64Sizer = _ModifiedSizer(
+ _SignedVarintSize, wire_format.ZigZagEncode)
+
+Fixed32Sizer = SFixed32Sizer = FloatSizer = _FixedSizer(4)
+Fixed64Sizer = SFixed64Sizer = DoubleSizer = _FixedSizer(8)
+
+BoolSizer = _FixedSizer(1)
+
+
+def StringSizer(field_number, is_repeated, is_packed):
+ """Returns a sizer for a string field."""
+
+ tag_size = _TagSize(field_number)
+ local_VarintSize = _VarintSize
+ local_len = len
+ assert not is_packed
+ if is_repeated:
+ def RepeatedFieldSize(value):
+ result = tag_size * len(value)
+ for element in value:
+ l = local_len(element.encode('utf-8'))
+ result += local_VarintSize(l) + l
+ return result
+ return RepeatedFieldSize
+ else:
+ def FieldSize(value):
+ l = local_len(value.encode('utf-8'))
+ return tag_size + local_VarintSize(l) + l
+ return FieldSize
+
+
+def BytesSizer(field_number, is_repeated, is_packed):
+ """Returns a sizer for a bytes field."""
+
+ tag_size = _TagSize(field_number)
+ local_VarintSize = _VarintSize
+ local_len = len
+ assert not is_packed
+ if is_repeated:
+ def RepeatedFieldSize(value):
+ result = tag_size * len(value)
+ for element in value:
+ l = local_len(element)
+ result += local_VarintSize(l) + l
+ return result
+ return RepeatedFieldSize
+ else:
+ def FieldSize(value):
+ l = local_len(value)
+ return tag_size + local_VarintSize(l) + l
+ return FieldSize
+
+
+def GroupSizer(field_number, is_repeated, is_packed):
+ """Returns a sizer for a group field."""
+
+ tag_size = _TagSize(field_number) * 2
+ assert not is_packed
+ if is_repeated:
+ def RepeatedFieldSize(value):
+ result = tag_size * len(value)
+ for element in value:
+ result += element.ByteSize()
+ return result
+ return RepeatedFieldSize
+ else:
+ def FieldSize(value):
+ return tag_size + value.ByteSize()
+ return FieldSize
+
+
+def MessageSizer(field_number, is_repeated, is_packed):
+ """Returns a sizer for a message field."""
+
+ tag_size = _TagSize(field_number)
+ local_VarintSize = _VarintSize
+ assert not is_packed
+ if is_repeated:
+ def RepeatedFieldSize(value):
+ result = tag_size * len(value)
+ for element in value:
+ l = element.ByteSize()
+ result += local_VarintSize(l) + l
+ return result
+ return RepeatedFieldSize
+ else:
+ def FieldSize(value):
+ l = value.ByteSize()
+ return tag_size + local_VarintSize(l) + l
+ return FieldSize
+
+
+# --------------------------------------------------------------------
+# MessageSet is special.
+
+
+def MessageSetItemSizer(field_number):
+ """Returns a sizer for extensions of MessageSet.
+
+ The message set message looks like this:
+ message MessageSet {
+ repeated group Item = 1 {
+ required int32 type_id = 2;
+ required string message = 3;
+ }
+ }
+ """
+ static_size = (_TagSize(1) * 2 + _TagSize(2) + _VarintSize(field_number) +
+ _TagSize(3))
+ local_VarintSize = _VarintSize
+
+ def FieldSize(value):
+ l = value.ByteSize()
+ return static_size + local_VarintSize(l) + l
+
+ return FieldSize
+
+
+# ====================================================================
+# Encoders!
+
+
+def _VarintEncoder():
+ """Return an encoder for a basic varint value (does not include tag)."""
+
+ local_chr = chr
+ def EncodeVarint(write, value):
+ bits = value & 0x7f
+ value >>= 7
+ while value:
+ write(local_chr(0x80|bits))
+ bits = value & 0x7f
+ value >>= 7
+ return write(local_chr(bits))
+
+ return EncodeVarint
+
+
+def _SignedVarintEncoder():
+ """Return an encoder for a basic signed varint value (does not include
+ tag)."""
+
+ local_chr = chr
+ def EncodeSignedVarint(write, value):
+ if value < 0:
+ value += (1 << 64)
+ bits = value & 0x7f
+ value >>= 7
+ while value:
+ write(local_chr(0x80|bits))
+ bits = value & 0x7f
+ value >>= 7
+ return write(local_chr(bits))
+
+ return EncodeSignedVarint
+
+
+_EncodeVarint = _VarintEncoder()
+_EncodeSignedVarint = _SignedVarintEncoder()
+
+
+def _VarintBytes(value):
+ """Encode the given integer as a varint and return the bytes. This is only
+ called at startup time so it doesn't need to be fast."""
+
+ pieces = []
+ _EncodeVarint(pieces.append, value)
+ return "".join(pieces)
+
+
+def TagBytes(field_number, wire_type):
+ """Encode the given tag and return the bytes. Only called at startup."""
+
+ return _VarintBytes(wire_format.PackTag(field_number, wire_type))
+
+# --------------------------------------------------------------------
+# As with sizers (see above), we have a number of common encoder
+# implementations.
+
+
+def _SimpleEncoder(wire_type, encode_value, compute_value_size):
+ """Return a constructor for an encoder for fields of a particular type.
+
+ Args:
+ wire_type: The field's wire type, for encoding tags.
+ encode_value: A function which encodes an individual value, e.g.
+ _EncodeVarint().
+ compute_value_size: A function which computes the size of an individual
+ value, e.g. _VarintSize().
+ """
+
+ def SpecificEncoder(field_number, is_repeated, is_packed):
+ if is_packed:
+ tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+ local_EncodeVarint = _EncodeVarint
+ def EncodePackedField(write, value):
+ write(tag_bytes)
+ size = 0
+ for element in value:
+ size += compute_value_size(element)
+ local_EncodeVarint(write, size)
+ for element in value:
+ encode_value(write, element)
+ return EncodePackedField
+ elif is_repeated:
+ tag_bytes = TagBytes(field_number, wire_type)
+ def EncodeRepeatedField(write, value):
+ for element in value:
+ write(tag_bytes)
+ encode_value(write, element)
+ return EncodeRepeatedField
+ else:
+ tag_bytes = TagBytes(field_number, wire_type)
+ def EncodeField(write, value):
+ write(tag_bytes)
+ return encode_value(write, value)
+ return EncodeField
+
+ return SpecificEncoder
+
+
+def _ModifiedEncoder(wire_type, encode_value, compute_value_size, modify_value):
+ """Like SimpleEncoder but additionally invokes modify_value on every value
+ before passing it to encode_value. Usually modify_value is ZigZagEncode."""
+
+ def SpecificEncoder(field_number, is_repeated, is_packed):
+ if is_packed:
+ tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+ local_EncodeVarint = _EncodeVarint
+ def EncodePackedField(write, value):
+ write(tag_bytes)
+ size = 0
+ for element in value:
+ size += compute_value_size(modify_value(element))
+ local_EncodeVarint(write, size)
+ for element in value:
+ encode_value(write, modify_value(element))
+ return EncodePackedField
+ elif is_repeated:
+ tag_bytes = TagBytes(field_number, wire_type)
+ def EncodeRepeatedField(write, value):
+ for element in value:
+ write(tag_bytes)
+ encode_value(write, modify_value(element))
+ return EncodeRepeatedField
+ else:
+ tag_bytes = TagBytes(field_number, wire_type)
+ def EncodeField(write, value):
+ write(tag_bytes)
+ return encode_value(write, modify_value(value))
+ return EncodeField
+
+ return SpecificEncoder
+
+
+def _StructPackEncoder(wire_type, format):
+ """Return a constructor for an encoder for a fixed-width field.
+
+ Args:
+ wire_type: The field's wire type, for encoding tags.
+ format: The format string to pass to struct.pack().
+ """
+
+ value_size = struct.calcsize(format)
+
+ def SpecificEncoder(field_number, is_repeated, is_packed):
+ local_struct_pack = struct.pack
+ if is_packed:
+ tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+ local_EncodeVarint = _EncodeVarint
+ def EncodePackedField(write, value):
+ write(tag_bytes)
+ local_EncodeVarint(write, len(value) * value_size)
+ for element in value:
+ write(local_struct_pack(format, element))
+ return EncodePackedField
+ elif is_repeated:
+ tag_bytes = TagBytes(field_number, wire_type)
+ def EncodeRepeatedField(write, value):
+ for element in value:
+ write(tag_bytes)
+ write(local_struct_pack(format, element))
+ return EncodeRepeatedField
+ else:
+ tag_bytes = TagBytes(field_number, wire_type)
+ def EncodeField(write, value):
+ write(tag_bytes)
+ return write(local_struct_pack(format, value))
+ return EncodeField
+
+ return SpecificEncoder
+
+
+# ====================================================================
+# Here we declare an encoder constructor for each field type. These work
+# very similarly to sizer constructors, described earlier.
+
+
+Int32Encoder = Int64Encoder = EnumEncoder = _SimpleEncoder(
+ wire_format.WIRETYPE_VARINT, _EncodeSignedVarint, _SignedVarintSize)
+
+UInt32Encoder = UInt64Encoder = _SimpleEncoder(
+ wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize)
+
+SInt32Encoder = SInt64Encoder = _ModifiedEncoder(
+ wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize,
+ wire_format.ZigZagEncode)
+
+# Note that Python conveniently guarantees that when using the '<' prefix on
+# formats, they will also have the same size across all platforms (as opposed
+# to without the prefix, where their sizes depend on the C compiler's basic
+# type sizes).
+Fixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<I')
+Fixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<Q')
+SFixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<i')
+SFixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<q')
+FloatEncoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<f')
+DoubleEncoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<d')
+
+
+def BoolEncoder(field_number, is_repeated, is_packed):
+ """Returns an encoder for a boolean field."""
+
+ false_byte = chr(0)
+ true_byte = chr(1)
+ if is_packed:
+ tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+ local_EncodeVarint = _EncodeVarint
+ def EncodePackedField(write, value):
+ write(tag_bytes)
+ local_EncodeVarint(write, len(value))
+ for element in value:
+ if element:
+ write(true_byte)
+ else:
+ write(false_byte)
+ return EncodePackedField
+ elif is_repeated:
+ tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
+ def EncodeRepeatedField(write, value):
+ for element in value:
+ write(tag_bytes)
+ if element:
+ write(true_byte)
+ else:
+ write(false_byte)
+ return EncodeRepeatedField
+ else:
+ tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
+ def EncodeField(write, value):
+ write(tag_bytes)
+ if value:
+ return write(true_byte)
+ return write(false_byte)
+ return EncodeField
+
+
+def StringEncoder(field_number, is_repeated, is_packed):
+ """Returns an encoder for a string field."""
+
+ tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+ local_EncodeVarint = _EncodeVarint
+ local_len = len
+ assert not is_packed
+ if is_repeated:
+ def EncodeRepeatedField(write, value):
+ for element in value:
+ encoded = element.encode('utf-8')
+ write(tag)
+ local_EncodeVarint(write, local_len(encoded))
+ write(encoded)
+ return EncodeRepeatedField
+ else:
+ def EncodeField(write, value):
+ encoded = value.encode('utf-8')
+ write(tag)
+ local_EncodeVarint(write, local_len(encoded))
+ return write(encoded)
+ return EncodeField
+
+
+def BytesEncoder(field_number, is_repeated, is_packed):
+ """Returns an encoder for a bytes field."""
+
+ tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+ local_EncodeVarint = _EncodeVarint
+ local_len = len
+ assert not is_packed
+ if is_repeated:
+ def EncodeRepeatedField(write, value):
+ for element in value:
+ write(tag)
+ local_EncodeVarint(write, local_len(element))
+ write(element)
+ return EncodeRepeatedField
+ else:
+ def EncodeField(write, value):
+ write(tag)
+ local_EncodeVarint(write, local_len(value))
+ return write(value)
+ return EncodeField
+
+
+def GroupEncoder(field_number, is_repeated, is_packed):
+ """Returns an encoder for a group field."""
+
+ start_tag = TagBytes(field_number, wire_format.WIRETYPE_START_GROUP)
+ end_tag = TagBytes(field_number, wire_format.WIRETYPE_END_GROUP)
+ assert not is_packed
+ if is_repeated:
+ def EncodeRepeatedField(write, value):
+ for element in value:
+ write(start_tag)
+ element._InternalSerialize(write)
+ write(end_tag)
+ return EncodeRepeatedField
+ else:
+ def EncodeField(write, value):
+ write(start_tag)
+ value._InternalSerialize(write)
+ return write(end_tag)
+ return EncodeField
+
+
+def MessageEncoder(field_number, is_repeated, is_packed):
+ """Returns an encoder for a message field."""
+
+ tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
+ local_EncodeVarint = _EncodeVarint
+ assert not is_packed
+ if is_repeated:
+ def EncodeRepeatedField(write, value):
+ for element in value:
+ write(tag)
+ local_EncodeVarint(write, element.ByteSize())
+ element._InternalSerialize(write)
+ return EncodeRepeatedField
+ else:
+ def EncodeField(write, value):
+ write(tag)
+ local_EncodeVarint(write, value.ByteSize())
+ return value._InternalSerialize(write)
+ return EncodeField
+
+
+# --------------------------------------------------------------------
+# As before, MessageSet is special.
+
+
+def MessageSetItemEncoder(field_number):
+ """Encoder for extensions of MessageSet.
+
+ The message set message looks like this:
+ message MessageSet {
+ repeated group Item = 1 {
+ required int32 type_id = 2;
+ required string message = 3;
}
- """
- self.AppendTag(1, wire_format.WIRETYPE_START_GROUP)
- self.AppendInt32(2, field_number)
- self.AppendMessage(3, msg)
- self.AppendTag(1, wire_format.WIRETYPE_END_GROUP)
-
- def AppendTag(self, field_number, wire_type):
- """Appends a tag containing field number and wire type information."""
- self._stream.AppendVarUInt32(wire_format.PackTag(field_number, wire_type))
+ }
+ """
+ start_bytes = "".join([
+ TagBytes(1, wire_format.WIRETYPE_START_GROUP),
+ TagBytes(2, wire_format.WIRETYPE_VARINT),
+ _VarintBytes(field_number),
+ TagBytes(3, wire_format.WIRETYPE_LENGTH_DELIMITED)])
+ end_bytes = TagBytes(1, wire_format.WIRETYPE_END_GROUP)
+ local_EncodeVarint = _EncodeVarint
+
+ def EncodeField(write, value):
+ write(start_bytes)
+ local_EncodeVarint(write, value.ByteSize())
+ value._InternalSerialize(write)
+ return write(end_bytes)
+
+ return EncodeField
diff --git a/python/google/protobuf/internal/encoder_test.py b/python/google/protobuf/internal/encoder_test.py
deleted file mode 100755
index bf75ea80..00000000
--- a/python/google/protobuf/internal/encoder_test.py
+++ /dev/null
@@ -1,286 +0,0 @@
-#! /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.
-
-"""Test for google.protobuf.internal.encoder."""
-
-__author__ = 'robinson@google.com (Will Robinson)'
-
-import struct
-import logging
-import unittest
-from google.protobuf.internal import wire_format
-from google.protobuf.internal import encoder
-from google.protobuf.internal import output_stream
-from google.protobuf import message
-import mox
-
-
-class EncoderTest(unittest.TestCase):
-
- def setUp(self):
- self.mox = mox.Mox()
- self.encoder = encoder.Encoder()
- self.mock_stream = self.mox.CreateMock(output_stream.OutputStream)
- self.mock_message = self.mox.CreateMock(message.Message)
- self.encoder._stream = self.mock_stream
-
- def PackTag(self, field_number, wire_type):
- return wire_format.PackTag(field_number, wire_type)
-
- def AppendScalarTestHelper(self, test_name, encoder_method,
- expected_stream_method_name,
- wire_type, field_value,
- expected_value=None, expected_length=None,
- is_tag_test=True):
- """Helper for testAppendScalars.
-
- Calls one of the Encoder methods, and ensures that the Encoder
- in turn makes the expected calls into its OutputStream.
-
- Args:
- test_name: Name of this test, used only for logging.
- encoder_method: Callable on self.encoder. This is the Encoder
- method we're testing. If is_tag_test=True, the encoder method
- accepts a field_number and field_value. if is_tag_test=False,
- the encoder method accepts a field_value.
- expected_stream_method_name: (string) Name of the OutputStream
- method we expect Encoder to call to actually put the value
- on the wire.
- wire_type: The WIRETYPE_* constant we expect encoder to
- use in the specified encoder_method.
- field_value: The value we're trying to encode. Passed
- into encoder_method.
- expected_value: The value we expect Encoder to pass into
- the OutputStream method. If None, we expect field_value
- to pass through unmodified.
- expected_length: The length we expect Encoder to pass to the
- AppendVarUInt32 method. If None we expect the length of the
- field_value.
- is_tag_test: A Boolean. If True (the default), we append the
- the packed field number and wire_type to the stream before
- the field value.
- """
- if expected_value is None:
- expected_value = field_value
-
- logging.info('Testing %s scalar output.\n'
- 'Calling %r(%r), and expecting that to call the '
- 'stream method %s(%r).' % (
- test_name, encoder_method, field_value,
- expected_stream_method_name, expected_value))
-
- if is_tag_test:
- field_number = 10
- # Should first append the field number and type information.
- self.mock_stream.AppendVarUInt32(self.PackTag(field_number, wire_type))
- # If we're length-delimited, we should then append the length.
- if wire_type == wire_format.WIRETYPE_LENGTH_DELIMITED:
- if expected_length is None:
- expected_length = len(field_value)
- self.mock_stream.AppendVarUInt32(expected_length)
-
- # Should then append the value itself.
- # We have to use names instead of methods to work around some
- # mox weirdness. (ResetAll() is overzealous).
- expected_stream_method = getattr(self.mock_stream,
- expected_stream_method_name)
- expected_stream_method(expected_value)
-
- self.mox.ReplayAll()
- if is_tag_test:
- encoder_method(field_number, field_value)
- else:
- encoder_method(field_value)
- 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')
- scalar_tests = [
- ['int32', self.encoder.AppendInt32, 'AppendVarint32',
- wire_format.WIRETYPE_VARINT, 0],
- ['int64', self.encoder.AppendInt64, 'AppendVarint64',
- wire_format.WIRETYPE_VARINT, 0],
- ['uint32', self.encoder.AppendUInt32, 'AppendVarUInt32',
- wire_format.WIRETYPE_VARINT, 0],
- ['uint64', self.encoder.AppendUInt64, 'AppendVarUInt64',
- wire_format.WIRETYPE_VARINT, 0],
- ['fixed32', self.encoder.AppendFixed32, 'AppendLittleEndian32',
- wire_format.WIRETYPE_FIXED32, 0],
- ['fixed64', self.encoder.AppendFixed64, 'AppendLittleEndian64',
- wire_format.WIRETYPE_FIXED64, 0],
- ['sfixed32', self.encoder.AppendSFixed32, 'AppendLittleEndian32',
- wire_format.WIRETYPE_FIXED32, -1, 0xffffffff],
- ['sfixed64', self.encoder.AppendSFixed64, 'AppendLittleEndian64',
- wire_format.WIRETYPE_FIXED64, -1, 0xffffffffffffffff],
- ['float', self.encoder.AppendFloat, 'AppendRawBytes',
- wire_format.WIRETYPE_FIXED32, self.VAL, self.LITTLE_FLOAT_VAL],
- ['double', self.encoder.AppendDouble, 'AppendRawBytes',
- 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',
- wire_format.WIRETYPE_VARINT, 0],
- ['string', self.encoder.AppendString, 'AppendRawBytes',
- wire_format.WIRETYPE_LENGTH_DELIMITED,
- "You're in a maze of twisty little passages, all alike."],
- ['utf8-string', self.encoder.AppendString, 'AppendRawBytes',
- wire_format.WIRETYPE_LENGTH_DELIMITED, utf8_string,
- utf8_bytes, len(utf8_bytes)],
- # We test zigzag encoding routines more extensively below.
- ['sint32', self.encoder.AppendSInt32, 'AppendVarUInt32',
- wire_format.WIRETYPE_VARINT, -1, 1],
- ['sint64', self.encoder.AppendSInt64, 'AppendVarUInt64',
- wire_format.WIRETYPE_VARINT, -1, 1],
- ]
- # Ensure that we're testing different Encoder methods and using
- # different test names in all test cases above.
- self.assertEqual(len(scalar_tests), len(set(t[0] for t in scalar_tests)))
- self.assert_(len(scalar_tests) >= len(set(t[1] for t in scalar_tests)))
- for args in scalar_tests:
- self.AppendScalarTestHelper(*args)
-
- def testAppendScalarsWithoutTags(self):
- scalar_no_tag_tests = [
- ['int32', self.encoder.AppendInt32NoTag, 'AppendVarint32', None, 0],
- ['int64', self.encoder.AppendInt64NoTag, 'AppendVarint64', None, 0],
- ['uint32', self.encoder.AppendUInt32NoTag, 'AppendVarUInt32', None, 0],
- ['uint64', self.encoder.AppendUInt64NoTag, 'AppendVarUInt64', None, 0],
- ['fixed32', self.encoder.AppendFixed32NoTag,
- 'AppendLittleEndian32', None, 0],
- ['fixed64', self.encoder.AppendFixed64NoTag,
- 'AppendLittleEndian64', None, 0],
- ['sfixed32', self.encoder.AppendSFixed32NoTag,
- 'AppendLittleEndian32', None, 0],
- ['sfixed64', self.encoder.AppendSFixed64NoTag,
- 'AppendLittleEndian64', None, 0],
- ['float', self.encoder.AppendFloatNoTag,
- 'AppendRawBytes', None, self.VAL, self.LITTLE_FLOAT_VAL],
- ['double', self.encoder.AppendDoubleNoTag,
- '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,
- 'AppendVarUInt32', None, -1, 1],
- ['sint64', self.encoder.AppendSInt64NoTag,
- 'AppendVarUInt64', None, -1, 1],
- ]
-
- self.assertEqual(len(scalar_no_tag_tests),
- len(set(t[0] for t in scalar_no_tag_tests)))
- self.assert_(len(scalar_no_tag_tests) >=
- len(set(t[1] for t in scalar_no_tag_tests)))
- for args in scalar_no_tag_tests:
- # For no tag tests, the wire_type is not used, so we put in None.
- self.AppendScalarTestHelper(is_tag_test=False, *args)
-
- def testAppendGroup(self):
- field_number = 23
- # Should first append the start-group marker.
- self.mock_stream.AppendVarUInt32(
- self.PackTag(field_number, wire_format.WIRETYPE_START_GROUP))
- # Should then serialize itself.
- self.mock_message.SerializeToString().AndReturn('foo')
- self.mock_stream.AppendRawBytes('foo')
- # Should finally append the end-group marker.
- self.mock_stream.AppendVarUInt32(
- self.PackTag(field_number, wire_format.WIRETYPE_END_GROUP))
-
- self.mox.ReplayAll()
- self.encoder.AppendGroup(field_number, self.mock_message)
- self.mox.VerifyAll()
-
- def testAppendMessage(self):
- field_number = 23
- byte_size = 42
- # Should first append the field number and type information.
- self.mock_stream.AppendVarUInt32(
- self.PackTag(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED))
- # Should then append its length.
- self.mock_message.ByteSize().AndReturn(byte_size)
- self.mock_stream.AppendVarUInt32(byte_size)
- # Should then serialize itself to the encoder.
- self.mock_message.SerializeToString().AndReturn('foo')
- self.mock_stream.AppendRawBytes('foo')
-
- self.mox.ReplayAll()
- self.encoder.AppendMessage(field_number, self.mock_message)
- self.mox.VerifyAll()
-
- def testAppendMessageSetItem(self):
- field_number = 23
- byte_size = 42
- # Should first append the field number and type information.
- self.mock_stream.AppendVarUInt32(
- self.PackTag(1, wire_format.WIRETYPE_START_GROUP))
- self.mock_stream.AppendVarUInt32(
- self.PackTag(2, wire_format.WIRETYPE_VARINT))
- self.mock_stream.AppendVarint32(field_number)
- self.mock_stream.AppendVarUInt32(
- self.PackTag(3, wire_format.WIRETYPE_LENGTH_DELIMITED))
- # Should then append its length.
- self.mock_message.ByteSize().AndReturn(byte_size)
- self.mock_stream.AppendVarUInt32(byte_size)
- # Should then serialize itself to the encoder.
- self.mock_message.SerializeToString().AndReturn('foo')
- self.mock_stream.AppendRawBytes('foo')
- self.mock_stream.AppendVarUInt32(
- self.PackTag(1, wire_format.WIRETYPE_END_GROUP))
-
- self.mox.ReplayAll()
- self.encoder.AppendMessageSetItem(field_number, self.mock_message)
- self.mox.VerifyAll()
-
- def testAppendSFixed(self):
- # Most of our bounds-checking is done in output_stream.py,
- # but encoder.py is responsible for transforming signed
- # fixed-width integers into unsigned ones, so we test here
- # to ensure that we're not losing any entropy when we do
- # that conversion.
- field_number = 10
- self.assertRaises(message.EncodeError, self.encoder.AppendSFixed32,
- 10, wire_format.UINT32_MAX + 1)
- self.assertRaises(message.EncodeError, self.encoder.AppendSFixed32,
- 10, -(1 << 32))
- self.assertRaises(message.EncodeError, self.encoder.AppendSFixed64,
- 10, wire_format.UINT64_MAX + 1)
- self.assertRaises(message.EncodeError, self.encoder.AppendSFixed64,
- 10, -(1 << 64))
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/python/google/protobuf/internal/generator_test.py b/python/google/protobuf/internal/generator_test.py
index 11fcfa0c..dd27c9a3 100755
--- a/python/google/protobuf/internal/generator_test.py
+++ b/python/google/protobuf/internal/generator_test.py
@@ -35,15 +35,20 @@
# indirect testing of the protocol compiler output.
"""Unittest that directly tests the output of the pure-Python protocol
-compiler. See //net/proto2/internal/reflection_test.py for a test which
+compiler. See //google/protobuf/reflection_test.py for a test which
further ensures that we can use Python protocol message objects as we expect.
"""
__author__ = 'robinson@google.com (Will Robinson)'
import unittest
+from google.protobuf import unittest_import_pb2
from google.protobuf import unittest_mset_pb2
from google.protobuf import unittest_pb2
+from google.protobuf import unittest_no_generic_services_pb2
+
+
+MAX_EXTENSION = 536870912
class GeneratorTest(unittest.TestCase):
@@ -71,6 +76,31 @@ class GeneratorTest(unittest.TestCase):
self.assertEqual(3, proto.BAZ)
self.assertEqual(3, unittest_pb2.TestAllTypes.BAZ)
+ def testExtremeDefaultValues(self):
+ message = unittest_pb2.TestExtremeDefaultValues()
+ self.assertEquals(float('inf'), message.inf_double)
+ self.assertEquals(float('-inf'), message.neg_inf_double)
+ self.assert_(message.nan_double != message.nan_double)
+ self.assertEquals(float('inf'), message.inf_float)
+ self.assertEquals(float('-inf'), message.neg_inf_float)
+ self.assert_(message.nan_float != message.nan_float)
+
+ def testHasDefaultValues(self):
+ desc = unittest_pb2.TestAllTypes.DESCRIPTOR
+
+ expected_has_default_by_name = {
+ 'optional_int32': False,
+ 'repeated_int32': False,
+ 'optional_nested_message': False,
+ 'default_int32': True,
+ }
+
+ has_default_by_name = dict(
+ [(f.name, f.has_default_value)
+ for f in desc.fields
+ if f.name in expected_has_default_by_name])
+ self.assertEqual(expected_has_default_by_name, has_default_by_name)
+
def testContainingTypeBehaviorForExtensions(self):
self.assertEqual(unittest_pb2.optional_int32_extension.containing_type,
unittest_pb2.TestAllExtensions.DESCRIPTOR)
@@ -95,6 +125,81 @@ class GeneratorTest(unittest.TestCase):
proto = unittest_mset_pb2.TestMessageSet()
self.assertTrue(proto.DESCRIPTOR.GetOptions().message_set_wire_format)
+ def testNestedTypes(self):
+ self.assertEquals(
+ set(unittest_pb2.TestAllTypes.DESCRIPTOR.nested_types),
+ set([
+ unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR,
+ unittest_pb2.TestAllTypes.OptionalGroup.DESCRIPTOR,
+ unittest_pb2.TestAllTypes.RepeatedGroup.DESCRIPTOR,
+ ]))
+ self.assertEqual(unittest_pb2.TestEmptyMessage.DESCRIPTOR.nested_types, [])
+ self.assertEqual(
+ unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.nested_types, [])
+
+ def testContainingType(self):
+ self.assertTrue(
+ unittest_pb2.TestEmptyMessage.DESCRIPTOR.containing_type is None)
+ self.assertTrue(
+ unittest_pb2.TestAllTypes.DESCRIPTOR.containing_type is None)
+ self.assertEqual(
+ unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.containing_type,
+ unittest_pb2.TestAllTypes.DESCRIPTOR)
+ self.assertEqual(
+ unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR.containing_type,
+ unittest_pb2.TestAllTypes.DESCRIPTOR)
+ self.assertEqual(
+ unittest_pb2.TestAllTypes.RepeatedGroup.DESCRIPTOR.containing_type,
+ unittest_pb2.TestAllTypes.DESCRIPTOR)
+
+ def testContainingTypeInEnumDescriptor(self):
+ self.assertTrue(unittest_pb2._FOREIGNENUM.containing_type is None)
+ self.assertEqual(unittest_pb2._TESTALLTYPES_NESTEDENUM.containing_type,
+ unittest_pb2.TestAllTypes.DESCRIPTOR)
+
+ def testPackage(self):
+ self.assertEqual(
+ unittest_pb2.TestAllTypes.DESCRIPTOR.file.package,
+ 'protobuf_unittest')
+ desc = unittest_pb2.TestAllTypes.NestedMessage.DESCRIPTOR
+ self.assertEqual(desc.file.package, 'protobuf_unittest')
+ self.assertEqual(
+ unittest_import_pb2.ImportMessage.DESCRIPTOR.file.package,
+ 'protobuf_unittest_import')
+
+ self.assertEqual(
+ unittest_pb2._FOREIGNENUM.file.package, 'protobuf_unittest')
+ self.assertEqual(
+ unittest_pb2._TESTALLTYPES_NESTEDENUM.file.package,
+ 'protobuf_unittest')
+ self.assertEqual(
+ unittest_import_pb2._IMPORTENUM.file.package,
+ 'protobuf_unittest_import')
+
+ def testExtensionRange(self):
+ self.assertEqual(
+ unittest_pb2.TestAllTypes.DESCRIPTOR.extension_ranges, [])
+ self.assertEqual(
+ unittest_pb2.TestAllExtensions.DESCRIPTOR.extension_ranges,
+ [(1, MAX_EXTENSION)])
+ self.assertEqual(
+ unittest_pb2.TestMultipleExtensionRanges.DESCRIPTOR.extension_ranges,
+ [(42, 43), (4143, 4244), (65536, MAX_EXTENSION)])
+
+ def testFileDescriptor(self):
+ self.assertEqual(unittest_pb2.DESCRIPTOR.name,
+ 'google/protobuf/unittest.proto')
+ self.assertEqual(unittest_pb2.DESCRIPTOR.package, 'protobuf_unittest')
+ self.assertFalse(unittest_pb2.DESCRIPTOR.serialized_pb is None)
+
+ def testNoGenericServices(self):
+ # unittest_no_generic_services.proto should contain defs for everything
+ # except services.
+ self.assertTrue(hasattr(unittest_no_generic_services_pb2, "TestMessage"))
+ self.assertTrue(hasattr(unittest_no_generic_services_pb2, "FOO"))
+ self.assertTrue(hasattr(unittest_no_generic_services_pb2, "test_extension"))
+ self.assertFalse(hasattr(unittest_no_generic_services_pb2, "TestService"))
+
if __name__ == '__main__':
unittest.main()
diff --git a/python/google/protobuf/internal/input_stream.py b/python/google/protobuf/internal/input_stream.py
deleted file mode 100755
index 7bda17e3..00000000
--- a/python/google/protobuf/internal/input_stream.py
+++ /dev/null
@@ -1,338 +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.
-
-"""InputStream is the primitive interface for reading bits from the wire.
-
-All protocol buffer deserialization can be expressed in terms of
-the InputStream primitives provided here.
-"""
-
-__author__ = 'robinson@google.com (Will Robinson)'
-
-import array
-import struct
-from google.protobuf import message
-from google.protobuf.internal import wire_format
-
-
-# Note that much of this code is ported from //net/proto/ProtocolBuffer, and
-# that the interface is strongly inspired by CodedInputStream from the C++
-# proto2 implementation.
-
-
-class InputStreamBuffer(object):
-
- """Contains all logic for reading bits, and dealing with stream position.
-
- If an InputStream method ever raises an exception, the stream is left
- in an indeterminate state and is not safe for further use.
- """
-
- def __init__(self, s):
- # What we really want is something like array('B', s), where elements we
- # read from the array are already given to us as one-byte integers. BUT
- # using array() instead of buffer() would force full string copies to result
- # from each GetSubBuffer() call.
- #
- # So, if the N serialized bytes of a single protocol buffer object are
- # split evenly between 2 child messages, and so on recursively, using
- # array('B', s) instead of buffer() would incur an additional N*logN bytes
- # copied during deserialization.
- #
- # The higher constant overhead of having to ord() for every byte we read
- # from the buffer in _ReadVarintHelper() could definitely lead to worse
- # performance in many real-world scenarios, even if the asymptotic
- # complexity is better. However, our real answer is that the mythical
- # Python/C extension module output mode for the protocol compiler will
- # be blazing-fast and will eliminate most use of this class anyway.
- self._buffer = buffer(s)
- self._pos = 0
-
- def EndOfStream(self):
- """Returns true iff we're at the end of the stream.
- If this returns true, then a call to any other InputStream method
- will raise an exception.
- """
- return self._pos >= len(self._buffer)
-
- def Position(self):
- """Returns the current position in the stream, or equivalently, the
- number of bytes read so far.
- """
- return self._pos
-
- def GetSubBuffer(self, size=None):
- """Returns a sequence-like object that represents a portion of our
- underlying sequence.
-
- Position 0 in the returned object corresponds to self.Position()
- in this stream.
-
- If size is specified, then the returned object ends after the
- next "size" bytes in this stream. If size is not specified,
- then the returned object ends at the end of this stream.
-
- We guarantee that the returned object R supports the Python buffer
- interface (and thus that the call buffer(R) will work).
-
- Note that the returned buffer is read-only.
-
- The intended use for this method is for nested-message and nested-group
- deserialization, where we want to make a recursive MergeFromString()
- call on the portion of the original sequence that contains the serialized
- nested message. (And we'd like to do so without making unnecessary string
- copies).
-
- REQUIRES: size is nonnegative.
- """
- # Note that buffer() doesn't perform any actual string copy.
- if size is None:
- return buffer(self._buffer, self._pos)
- else:
- if size < 0:
- raise message.DecodeError('Negative size %d' % size)
- return buffer(self._buffer, self._pos, size)
-
- def SkipBytes(self, num_bytes):
- """Skip num_bytes bytes ahead, or go to the end of the stream, whichever
- comes first.
-
- REQUIRES: num_bytes is nonnegative.
- """
- if num_bytes < 0:
- raise message.DecodeError('Negative num_bytes %d' % num_bytes)
- self._pos += num_bytes
- self._pos = min(self._pos, len(self._buffer))
-
- def ReadBytes(self, size):
- """Reads up to 'size' bytes from the stream, stopping early
- only if we reach the end of the stream. Returns the bytes read
- as a string.
- """
- if size < 0:
- raise message.DecodeError('Negative size %d' % size)
- s = (self._buffer[self._pos : self._pos + size])
- self._pos += len(s) # Only advance by the number of bytes actually read.
- return s
-
- def ReadLittleEndian32(self):
- """Interprets the next 4 bytes of the stream as a little-endian
- encoded, unsiged 32-bit integer, and returns that integer.
- """
- try:
- i = struct.unpack(wire_format.FORMAT_UINT32_LITTLE_ENDIAN,
- self._buffer[self._pos : self._pos + 4])
- self._pos += 4
- return i[0] # unpack() result is a 1-element tuple.
- except struct.error, e:
- raise message.DecodeError(e)
-
- def ReadLittleEndian64(self):
- """Interprets the next 8 bytes of the stream as a little-endian
- encoded, unsiged 64-bit integer, and returns that integer.
- """
- try:
- i = struct.unpack(wire_format.FORMAT_UINT64_LITTLE_ENDIAN,
- self._buffer[self._pos : self._pos + 8])
- self._pos += 8
- return i[0] # unpack() result is a 1-element tuple.
- except struct.error, e:
- raise message.DecodeError(e)
-
- def ReadVarint32(self):
- """Reads a varint from the stream, interprets this varint
- as a signed, 32-bit integer, and returns the integer.
- """
- i = self.ReadVarint64()
- if not wire_format.INT32_MIN <= i <= wire_format.INT32_MAX:
- raise message.DecodeError('Value out of range for int32: %d' % i)
- return int(i)
-
- def ReadVarUInt32(self):
- """Reads a varint from the stream, interprets this varint
- as an unsigned, 32-bit integer, and returns the integer.
- """
- i = self.ReadVarUInt64()
- if i > wire_format.UINT32_MAX:
- raise message.DecodeError('Value out of range for uint32: %d' % i)
- return i
-
- def ReadVarint64(self):
- """Reads a varint from the stream, interprets this varint
- as a signed, 64-bit integer, and returns the integer.
- """
- i = self.ReadVarUInt64()
- if i > wire_format.INT64_MAX:
- i -= (1 << 64)
- return i
-
- def ReadVarUInt64(self):
- """Reads a varint from the stream, interprets this varint
- as an unsigned, 64-bit integer, and returns the integer.
- """
- i = self._ReadVarintHelper()
- if not 0 <= i <= wire_format.UINT64_MAX:
- raise message.DecodeError('Value out of range for uint64: %d' % i)
- return i
-
- def _ReadVarintHelper(self):
- """Helper for the various varint-reading methods above.
- Reads an unsigned, varint-encoded integer from the stream and
- returns this integer.
-
- Does no bounds checking except to ensure that we read at most as many bytes
- as could possibly be present in a varint-encoded 64-bit number.
- """
- result = 0
- shift = 0
- while 1:
- if shift >= 64:
- raise message.DecodeError('Too many bytes when decoding varint.')
- try:
- b = ord(self._buffer[self._pos])
- except IndexError:
- raise message.DecodeError('Truncated varint.')
- self._pos += 1
- result |= ((b & 0x7f) << shift)
- shift += 7
- if not (b & 0x80):
- return result
-
-
-class InputStreamArray(object):
-
- """Contains all logic for reading bits, and dealing with stream position.
-
- If an InputStream method ever raises an exception, the stream is left
- in an indeterminate state and is not safe for further use.
-
- This alternative to InputStreamBuffer is used in environments where buffer()
- is unavailble, such as Google App Engine.
- """
-
- def __init__(self, s):
- self._buffer = array.array('B', s)
- self._pos = 0
-
- def EndOfStream(self):
- return self._pos >= len(self._buffer)
-
- def Position(self):
- return self._pos
-
- def GetSubBuffer(self, size=None):
- if size is None:
- return self._buffer[self._pos : ].tostring()
- else:
- if size < 0:
- raise message.DecodeError('Negative size %d' % size)
- return self._buffer[self._pos : self._pos + size].tostring()
-
- def SkipBytes(self, num_bytes):
- if num_bytes < 0:
- raise message.DecodeError('Negative num_bytes %d' % num_bytes)
- self._pos += num_bytes
- self._pos = min(self._pos, len(self._buffer))
-
- def ReadBytes(self, size):
- if size < 0:
- raise message.DecodeError('Negative size %d' % size)
- s = self._buffer[self._pos : self._pos + size].tostring()
- self._pos += len(s) # Only advance by the number of bytes actually read.
- return s
-
- def ReadLittleEndian32(self):
- try:
- i = struct.unpack(wire_format.FORMAT_UINT32_LITTLE_ENDIAN,
- self._buffer[self._pos : self._pos + 4])
- self._pos += 4
- return i[0] # unpack() result is a 1-element tuple.
- except struct.error, e:
- raise message.DecodeError(e)
-
- def ReadLittleEndian64(self):
- try:
- i = struct.unpack(wire_format.FORMAT_UINT64_LITTLE_ENDIAN,
- self._buffer[self._pos : self._pos + 8])
- self._pos += 8
- return i[0] # unpack() result is a 1-element tuple.
- except struct.error, e:
- raise message.DecodeError(e)
-
- def ReadVarint32(self):
- i = self.ReadVarint64()
- if not wire_format.INT32_MIN <= i <= wire_format.INT32_MAX:
- raise message.DecodeError('Value out of range for int32: %d' % i)
- return int(i)
-
- def ReadVarUInt32(self):
- i = self.ReadVarUInt64()
- if i > wire_format.UINT32_MAX:
- raise message.DecodeError('Value out of range for uint32: %d' % i)
- return i
-
- def ReadVarint64(self):
- i = self.ReadVarUInt64()
- if i > wire_format.INT64_MAX:
- i -= (1 << 64)
- return i
-
- def ReadVarUInt64(self):
- i = self._ReadVarintHelper()
- if not 0 <= i <= wire_format.UINT64_MAX:
- raise message.DecodeError('Value out of range for uint64: %d' % i)
- return i
-
- def _ReadVarintHelper(self):
- result = 0
- shift = 0
- while 1:
- if shift >= 64:
- raise message.DecodeError('Too many bytes when decoding varint.')
- try:
- b = self._buffer[self._pos]
- except IndexError:
- raise message.DecodeError('Truncated varint.')
- self._pos += 1
- result |= ((b & 0x7f) << shift)
- shift += 7
- if not (b & 0x80):
- return result
-
-
-try:
- buffer('')
- InputStream = InputStreamBuffer
-except NotImplementedError:
- # Google App Engine: dev_appserver.py
- InputStream = InputStreamArray
-except RuntimeError:
- # Google App Engine: production
- InputStream = InputStreamArray
diff --git a/python/google/protobuf/internal/input_stream_test.py b/python/google/protobuf/internal/input_stream_test.py
deleted file mode 100755
index ecec7f7d..00000000
--- a/python/google/protobuf/internal/input_stream_test.py
+++ /dev/null
@@ -1,314 +0,0 @@
-#! /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.
-
-"""Test for google.protobuf.internal.input_stream."""
-
-__author__ = 'robinson@google.com (Will Robinson)'
-
-import unittest
-from google.protobuf import message
-from google.protobuf.internal import wire_format
-from google.protobuf.internal import input_stream
-
-
-class InputStreamBufferTest(unittest.TestCase):
-
- def setUp(self):
- self.__original_input_stream = input_stream.InputStream
- input_stream.InputStream = input_stream.InputStreamBuffer
-
- def tearDown(self):
- input_stream.InputStream = self.__original_input_stream
-
- def testEndOfStream(self):
- stream = input_stream.InputStream('abcd')
- self.assertFalse(stream.EndOfStream())
- self.assertEqual('abcd', stream.ReadBytes(10))
- self.assertTrue(stream.EndOfStream())
-
- def testPosition(self):
- stream = input_stream.InputStream('abcd')
- self.assertEqual(0, stream.Position())
- self.assertEqual(0, stream.Position()) # No side-effects.
- stream.ReadBytes(1)
- self.assertEqual(1, stream.Position())
- stream.ReadBytes(1)
- self.assertEqual(2, stream.Position())
- stream.ReadBytes(10)
- self.assertEqual(4, stream.Position()) # Can't go past end of stream.
-
- def testGetSubBuffer(self):
- stream = input_stream.InputStream('abcd')
- # Try leaving out the size.
- self.assertEqual('abcd', str(stream.GetSubBuffer()))
- stream.SkipBytes(1)
- # GetSubBuffer() always starts at current size.
- self.assertEqual('bcd', str(stream.GetSubBuffer()))
- # Try 0-size.
- self.assertEqual('', str(stream.GetSubBuffer(0)))
- # Negative sizes should raise an error.
- self.assertRaises(message.DecodeError, stream.GetSubBuffer, -1)
- # Positive sizes should work as expected.
- self.assertEqual('b', str(stream.GetSubBuffer(1)))
- self.assertEqual('bc', str(stream.GetSubBuffer(2)))
- # Sizes longer than remaining bytes in the buffer should
- # return the whole remaining buffer.
- self.assertEqual('bcd', str(stream.GetSubBuffer(1000)))
-
- def testSkipBytes(self):
- stream = input_stream.InputStream('')
- # Skipping bytes when at the end of stream
- # should have no effect.
- stream.SkipBytes(0)
- stream.SkipBytes(1)
- stream.SkipBytes(2)
- self.assertTrue(stream.EndOfStream())
- self.assertEqual(0, stream.Position())
-
- # Try skipping within a stream.
- stream = input_stream.InputStream('abcd')
- self.assertEqual(0, stream.Position())
- stream.SkipBytes(1)
- self.assertEqual(1, stream.Position())
- stream.SkipBytes(10) # Can't skip past the end.
- self.assertEqual(4, stream.Position())
-
- # Ensure that a negative skip raises an exception.
- stream = input_stream.InputStream('abcd')
- stream.SkipBytes(1)
- self.assertRaises(message.DecodeError, stream.SkipBytes, -1)
-
- def testReadBytes(self):
- s = 'abcd'
- # Also test going past the total stream length.
- for i in range(len(s) + 10):
- stream = input_stream.InputStream(s)
- self.assertEqual(s[:i], stream.ReadBytes(i))
- self.assertEqual(min(i, len(s)), stream.Position())
- stream = input_stream.InputStream(s)
- self.assertRaises(message.DecodeError, stream.ReadBytes, -1)
-
- def EnsureFailureOnEmptyStream(self, input_stream_method):
- """Helper for integer-parsing tests below.
- Ensures that the given InputStream method raises a DecodeError
- if called on a stream with no bytes remaining.
- """
- stream = input_stream.InputStream('')
- self.assertRaises(message.DecodeError, input_stream_method, stream)
-
- def testReadLittleEndian32(self):
- self.EnsureFailureOnEmptyStream(input_stream.InputStream.ReadLittleEndian32)
- s = ''
- # Read 0.
- s += '\x00\x00\x00\x00'
- # Read 1.
- s += '\x01\x00\x00\x00'
- # Read a bunch of different bytes.
- s += '\x01\x02\x03\x04'
- # Read max unsigned 32-bit int.
- s += '\xff\xff\xff\xff'
- # Try a read with fewer than 4 bytes left in the stream.
- s += '\x00\x00\x00'
- stream = input_stream.InputStream(s)
- self.assertEqual(0, stream.ReadLittleEndian32())
- self.assertEqual(4, stream.Position())
- self.assertEqual(1, stream.ReadLittleEndian32())
- self.assertEqual(8, stream.Position())
- self.assertEqual(0x04030201, stream.ReadLittleEndian32())
- self.assertEqual(12, stream.Position())
- self.assertEqual(wire_format.UINT32_MAX, stream.ReadLittleEndian32())
- self.assertEqual(16, stream.Position())
- self.assertRaises(message.DecodeError, stream.ReadLittleEndian32)
-
- def testReadLittleEndian64(self):
- self.EnsureFailureOnEmptyStream(input_stream.InputStream.ReadLittleEndian64)
- s = ''
- # Read 0.
- s += '\x00\x00\x00\x00\x00\x00\x00\x00'
- # Read 1.
- s += '\x01\x00\x00\x00\x00\x00\x00\x00'
- # Read a bunch of different bytes.
- s += '\x01\x02\x03\x04\x05\x06\x07\x08'
- # Read max unsigned 64-bit int.
- s += '\xff\xff\xff\xff\xff\xff\xff\xff'
- # Try a read with fewer than 8 bytes left in the stream.
- s += '\x00\x00\x00'
- stream = input_stream.InputStream(s)
- self.assertEqual(0, stream.ReadLittleEndian64())
- self.assertEqual(8, stream.Position())
- self.assertEqual(1, stream.ReadLittleEndian64())
- self.assertEqual(16, stream.Position())
- self.assertEqual(0x0807060504030201, stream.ReadLittleEndian64())
- self.assertEqual(24, stream.Position())
- self.assertEqual(wire_format.UINT64_MAX, stream.ReadLittleEndian64())
- self.assertEqual(32, stream.Position())
- self.assertRaises(message.DecodeError, stream.ReadLittleEndian64)
-
- def ReadVarintSuccessTestHelper(self, varints_and_ints, read_method):
- """Helper for tests below that test successful reads of various varints.
-
- Args:
- varints_and_ints: Iterable of (str, integer) pairs, where the string
- gives the wire encoding and the integer gives the value we expect
- to be returned by the read_method upon encountering this string.
- read_method: Unbound InputStream method that is capable of reading
- the encoded strings provided in the first elements of varints_and_ints.
- """
- s = ''.join(s for s, i in varints_and_ints)
- stream = input_stream.InputStream(s)
- expected_pos = 0
- self.assertEqual(expected_pos, stream.Position())
- for s, expected_int in varints_and_ints:
- self.assertEqual(expected_int, read_method(stream))
- expected_pos += len(s)
- self.assertEqual(expected_pos, stream.Position())
-
- def testReadVarint32Success(self):
- varints_and_ints = [
- ('\x00', 0),
- ('\x01', 1),
- ('\x7f', 127),
- ('\x80\x01', 128),
- ('\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01', -1),
- ('\xff\xff\xff\xff\x07', wire_format.INT32_MAX),
- ('\x80\x80\x80\x80\xf8\xff\xff\xff\xff\x01', wire_format.INT32_MIN),
- ]
- self.ReadVarintSuccessTestHelper(varints_and_ints,
- input_stream.InputStream.ReadVarint32)
-
- def testReadVarint32Failure(self):
- self.EnsureFailureOnEmptyStream(input_stream.InputStream.ReadVarint32)
-
- # Try and fail to read INT32_MAX + 1.
- s = '\x80\x80\x80\x80\x08'
- stream = input_stream.InputStream(s)
- self.assertRaises(message.DecodeError, stream.ReadVarint32)
-
- # Try and fail to read INT32_MIN - 1.
- s = '\xfe\xff\xff\xff\xf7\xff\xff\xff\xff\x01'
- stream = input_stream.InputStream(s)
- self.assertRaises(message.DecodeError, stream.ReadVarint32)
-
- # Try and fail to read something that looks like
- # a varint with more than 10 bytes.
- s = '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00'
- stream = input_stream.InputStream(s)
- self.assertRaises(message.DecodeError, stream.ReadVarint32)
-
- def testReadVarUInt32Success(self):
- varints_and_ints = [
- ('\x00', 0),
- ('\x01', 1),
- ('\x7f', 127),
- ('\x80\x01', 128),
- ('\xff\xff\xff\xff\x0f', wire_format.UINT32_MAX),
- ]
- self.ReadVarintSuccessTestHelper(varints_and_ints,
- input_stream.InputStream.ReadVarUInt32)
-
- def testReadVarUInt32Failure(self):
- self.EnsureFailureOnEmptyStream(input_stream.InputStream.ReadVarUInt32)
- # Try and fail to read UINT32_MAX + 1
- s = '\x80\x80\x80\x80\x10'
- stream = input_stream.InputStream(s)
- self.assertRaises(message.DecodeError, stream.ReadVarUInt32)
-
- # Try and fail to read something that looks like
- # a varint with more than 10 bytes.
- s = '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00'
- stream = input_stream.InputStream(s)
- self.assertRaises(message.DecodeError, stream.ReadVarUInt32)
-
- def testReadVarint64Success(self):
- varints_and_ints = [
- ('\x00', 0),
- ('\x01', 1),
- ('\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01', -1),
- ('\x7f', 127),
- ('\x80\x01', 128),
- ('\xff\xff\xff\xff\xff\xff\xff\xff\x7f', wire_format.INT64_MAX),
- ('\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01', wire_format.INT64_MIN),
- ]
- self.ReadVarintSuccessTestHelper(varints_and_ints,
- input_stream.InputStream.ReadVarint64)
-
- def testReadVarint64Failure(self):
- self.EnsureFailureOnEmptyStream(input_stream.InputStream.ReadVarint64)
- # Try and fail to read something with the mythical 64th bit set.
- s = '\x80\x80\x80\x80\x80\x80\x80\x80\x80\x02'
- stream = input_stream.InputStream(s)
- self.assertRaises(message.DecodeError, stream.ReadVarint64)
-
- # Try and fail to read something that looks like
- # a varint with more than 10 bytes.
- s = '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00'
- stream = input_stream.InputStream(s)
- self.assertRaises(message.DecodeError, stream.ReadVarint64)
-
- def testReadVarUInt64Success(self):
- varints_and_ints = [
- ('\x00', 0),
- ('\x01', 1),
- ('\x7f', 127),
- ('\x80\x01', 128),
- ('\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01', 1 << 63),
- ]
- self.ReadVarintSuccessTestHelper(varints_and_ints,
- input_stream.InputStream.ReadVarUInt64)
-
- def testReadVarUInt64Failure(self):
- self.EnsureFailureOnEmptyStream(input_stream.InputStream.ReadVarUInt64)
- # Try and fail to read something with the mythical 64th bit set.
- s = '\x80\x80\x80\x80\x80\x80\x80\x80\x80\x02'
- stream = input_stream.InputStream(s)
- self.assertRaises(message.DecodeError, stream.ReadVarUInt64)
-
- # Try and fail to read something that looks like
- # a varint with more than 10 bytes.
- s = '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00'
- stream = input_stream.InputStream(s)
- self.assertRaises(message.DecodeError, stream.ReadVarUInt64)
-
-
-class InputStreamArrayTest(InputStreamBufferTest):
-
- def setUp(self):
- # Test InputStreamArray against the same tests in InputStreamBuffer
- self.__original_input_stream = input_stream.InputStream
- input_stream.InputStream = input_stream.InputStreamArray
-
- def tearDown(self):
- input_stream.InputStream = self.__original_input_stream
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/python/google/protobuf/internal/message_listener.py b/python/google/protobuf/internal/message_listener.py
index 43978952..1080234d 100755
--- a/python/google/protobuf/internal/message_listener.py
+++ b/python/google/protobuf/internal/message_listener.py
@@ -39,22 +39,34 @@ __author__ = 'robinson@google.com (Will Robinson)'
class MessageListener(object):
- """Listens for transitions to nonempty and for invalidations of cached
- byte sizes. Meant to be registered via Message._SetListener().
+ """Listens for modifications made to a message. Meant to be registered via
+ Message._SetListener().
+
+ Attributes:
+ dirty: If True, then calling Modified() would be a no-op. This can be
+ used to avoid these calls entirely in the common case.
"""
- def TransitionToNonempty(self):
- """Called the *first* time that this message becomes nonempty.
- Implementations are free (but not required) to call this method multiple
- times after the message has become nonempty.
- """
- raise NotImplementedError
+ def Modified(self):
+ """Called every time the message is modified in such a way that the parent
+ message may need to be updated. This currently means either:
+ (a) The message was modified for the first time, so the parent message
+ should henceforth mark the message as present.
+ (b) The message's cached byte size became dirty -- i.e. the message was
+ modified for the first time after a previous call to ByteSize().
+ Therefore the parent should also mark its byte size as dirty.
+ Note that (a) implies (b), since new objects start out with a client cached
+ size (zero). However, we document (a) explicitly because it is important.
+
+ Modified() will *only* be called in response to one of these two events --
+ not every time the sub-message is modified.
- def ByteSizeDirty(self):
- """Called *every* time the cached byte size value
- for this object is invalidated (transitions from being
- "clean" to "dirty").
+ Note that if the listener's |dirty| attribute is true, then calling
+ Modified at the moment would be a no-op, so it can be skipped. Performance-
+ sensitive callers should check this attribute directly before calling since
+ it will be true most of the time.
"""
+
raise NotImplementedError
@@ -62,8 +74,5 @@ class NullMessageListener(object):
"""No-op MessageListener implementation."""
- def TransitionToNonempty(self):
- pass
-
- def ByteSizeDirty(self):
+ def Modified(self):
pass
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index df344cf0..73a9a3a3 100755
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -30,7 +30,16 @@
# (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."""
+"""Tests python protocol buffers against the golden message.
+
+Note that the golden messages exercise every known field type, thus this
+test ends up exercising and verifying nearly all of the parsing and
+serialization code in the whole library.
+
+TODO(kenton): Merge with wire_format_test? It doesn't make a whole lot of
+sense to call this a test of the "message" module, which only declares an
+abstract interface.
+"""
__author__ = 'gps@google.com (Gregory P. Smith)'
@@ -40,14 +49,41 @@ from google.protobuf import unittest_pb2
from google.protobuf.internal import test_util
-class MessageTest(test_util.GoldenMessageTestCase):
+class MessageTest(unittest.TestCase):
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)
+ test_util.ExpectAllFieldsSet(self, golden_message)
+ self.assertTrue(golden_message.SerializeToString() == golden_data)
+
+ def testGoldenExtensions(self):
+ golden_data = test_util.GoldenFile('golden_message').read()
+ golden_message = unittest_pb2.TestAllExtensions()
+ golden_message.ParseFromString(golden_data)
+ all_set = unittest_pb2.TestAllExtensions()
+ test_util.SetAllExtensions(all_set)
+ self.assertEquals(all_set, golden_message)
+ self.assertTrue(golden_message.SerializeToString() == golden_data)
+
+ def testGoldenPackedMessage(self):
+ golden_data = test_util.GoldenFile('golden_packed_fields_message').read()
+ golden_message = unittest_pb2.TestPackedTypes()
+ golden_message.ParseFromString(golden_data)
+ all_set = unittest_pb2.TestPackedTypes()
+ test_util.SetAllPackedFields(all_set)
+ self.assertEquals(all_set, golden_message)
+ self.assertTrue(all_set.SerializeToString() == golden_data)
+ def testGoldenPackedExtensions(self):
+ golden_data = test_util.GoldenFile('golden_packed_fields_message').read()
+ golden_message = unittest_pb2.TestPackedExtensions()
+ golden_message.ParseFromString(golden_data)
+ all_set = unittest_pb2.TestPackedExtensions()
+ test_util.SetAllPackedExtensions(all_set)
+ self.assertEquals(all_set, golden_message)
+ self.assertTrue(all_set.SerializeToString() == golden_data)
if __name__ == '__main__':
unittest.main()
diff --git a/python/google/protobuf/internal/output_stream.py b/python/google/protobuf/internal/output_stream.py
deleted file mode 100755
index 6c2d6f6b..00000000
--- a/python/google/protobuf/internal/output_stream.py
+++ /dev/null
@@ -1,125 +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.
-
-"""OutputStream is the primitive interface for sticking bits on the wire.
-
-All protocol buffer serialization can be expressed in terms of
-the OutputStream primitives provided here.
-"""
-
-__author__ = 'robinson@google.com (Will Robinson)'
-
-import array
-import struct
-from google.protobuf import message
-from google.protobuf.internal import wire_format
-
-
-
-# Note that much of this code is ported from //net/proto/ProtocolBuffer, and
-# that the interface is strongly inspired by CodedOutputStream from the C++
-# proto2 implementation.
-
-
-class OutputStream(object):
-
- """Contains all logic for writing bits, and ToString() to get the result."""
-
- def __init__(self):
- self._buffer = array.array('B')
-
- def AppendRawBytes(self, raw_bytes):
- """Appends raw_bytes to our internal buffer."""
- self._buffer.fromstring(raw_bytes)
-
- def AppendLittleEndian32(self, unsigned_value):
- """Appends an unsigned 32-bit integer to the internal buffer,
- in little-endian byte order.
- """
- if not 0 <= unsigned_value <= wire_format.UINT32_MAX:
- raise message.EncodeError(
- 'Unsigned 32-bit out of range: %d' % unsigned_value)
- self._buffer.fromstring(struct.pack(
- wire_format.FORMAT_UINT32_LITTLE_ENDIAN, unsigned_value))
-
- def AppendLittleEndian64(self, unsigned_value):
- """Appends an unsigned 64-bit integer to the internal buffer,
- in little-endian byte order.
- """
- if not 0 <= unsigned_value <= wire_format.UINT64_MAX:
- raise message.EncodeError(
- 'Unsigned 64-bit out of range: %d' % unsigned_value)
- self._buffer.fromstring(struct.pack(
- wire_format.FORMAT_UINT64_LITTLE_ENDIAN, unsigned_value))
-
- def AppendVarint32(self, value):
- """Appends a signed 32-bit integer to the internal buffer,
- encoded as a varint. (Note that a negative varint32 will
- always require 10 bytes of space.)
- """
- if not wire_format.INT32_MIN <= value <= wire_format.INT32_MAX:
- raise message.EncodeError('Value out of range: %d' % value)
- self.AppendVarint64(value)
-
- def AppendVarUInt32(self, value):
- """Appends an unsigned 32-bit integer to the internal buffer,
- encoded as a varint.
- """
- if not 0 <= value <= wire_format.UINT32_MAX:
- raise message.EncodeError('Value out of range: %d' % value)
- self.AppendVarUInt64(value)
-
- def AppendVarint64(self, value):
- """Appends a signed 64-bit integer to the internal buffer,
- encoded as a varint.
- """
- if not wire_format.INT64_MIN <= value <= wire_format.INT64_MAX:
- raise message.EncodeError('Value out of range: %d' % value)
- if value < 0:
- value += (1 << 64)
- self.AppendVarUInt64(value)
-
- def AppendVarUInt64(self, unsigned_value):
- """Appends an unsigned 64-bit integer to the internal buffer,
- encoded as a varint.
- """
- if not 0 <= unsigned_value <= wire_format.UINT64_MAX:
- raise message.EncodeError('Value out of range: %d' % unsigned_value)
- while True:
- bits = unsigned_value & 0x7f
- unsigned_value >>= 7
- if not unsigned_value:
- self._buffer.append(bits)
- break
- self._buffer.append(0x80|bits)
-
- def ToString(self):
- """Returns a string containing the bytes in our internal buffer."""
- return self._buffer.tostring()
diff --git a/python/google/protobuf/internal/output_stream_test.py b/python/google/protobuf/internal/output_stream_test.py
deleted file mode 100755
index df92eecd..00000000
--- a/python/google/protobuf/internal/output_stream_test.py
+++ /dev/null
@@ -1,178 +0,0 @@
-#! /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.
-
-"""Test for google.protobuf.internal.output_stream."""
-
-__author__ = 'robinson@google.com (Will Robinson)'
-
-import unittest
-from google.protobuf import message
-from google.protobuf.internal import output_stream
-from google.protobuf.internal import wire_format
-
-
-class OutputStreamTest(unittest.TestCase):
-
- def setUp(self):
- self.stream = output_stream.OutputStream()
-
- def testAppendRawBytes(self):
- # Empty string.
- self.stream.AppendRawBytes('')
- self.assertEqual('', self.stream.ToString())
-
- # Nonempty string.
- self.stream.AppendRawBytes('abc')
- self.assertEqual('abc', self.stream.ToString())
-
- # Ensure that we're actually appending.
- self.stream.AppendRawBytes('def')
- self.assertEqual('abcdef', self.stream.ToString())
-
- def AppendNumericTestHelper(self, append_fn, values_and_strings):
- """For each (value, expected_string) pair in values_and_strings,
- calls an OutputStream.Append*(value) method on an OutputStream and ensures
- that the string written to that stream matches expected_string.
-
- Args:
- append_fn: Unbound OutputStream method that takes an integer or
- long value as input.
- values_and_strings: Iterable of (value, expected_string) pairs.
- """
- for conversion in (int, long):
- for value, string in values_and_strings:
- stream = output_stream.OutputStream()
- expected_string = ''
- append_fn(stream, conversion(value))
- expected_string += string
- self.assertEqual(expected_string, stream.ToString())
-
- def AppendOverflowTestHelper(self, append_fn, value):
- """Calls an OutputStream.Append*(value) method and asserts
- that the method raises message.EncodeError.
-
- Args:
- append_fn: Unbound OutputStream method that takes an integer or
- long value as input.
- value: Value to pass to append_fn which should cause an
- message.EncodeError.
- """
- stream = output_stream.OutputStream()
- self.assertRaises(message.EncodeError, append_fn, stream, value)
-
- def testAppendLittleEndian32(self):
- append_fn = output_stream.OutputStream.AppendLittleEndian32
- values_and_expected_strings = [
- (0, '\x00\x00\x00\x00'),
- (1, '\x01\x00\x00\x00'),
- ((1 << 32) - 1, '\xff\xff\xff\xff'),
- ]
- self.AppendNumericTestHelper(append_fn, values_and_expected_strings)
-
- self.AppendOverflowTestHelper(append_fn, 1 << 32)
- self.AppendOverflowTestHelper(append_fn, -1)
-
- def testAppendLittleEndian64(self):
- append_fn = output_stream.OutputStream.AppendLittleEndian64
- values_and_expected_strings = [
- (0, '\x00\x00\x00\x00\x00\x00\x00\x00'),
- (1, '\x01\x00\x00\x00\x00\x00\x00\x00'),
- ((1 << 64) - 1, '\xff\xff\xff\xff\xff\xff\xff\xff'),
- ]
- self.AppendNumericTestHelper(append_fn, values_and_expected_strings)
-
- self.AppendOverflowTestHelper(append_fn, 1 << 64)
- self.AppendOverflowTestHelper(append_fn, -1)
-
- def testAppendVarint32(self):
- append_fn = output_stream.OutputStream.AppendVarint32
- values_and_expected_strings = [
- (0, '\x00'),
- (1, '\x01'),
- (127, '\x7f'),
- (128, '\x80\x01'),
- (-1, '\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01'),
- (wire_format.INT32_MAX, '\xff\xff\xff\xff\x07'),
- (wire_format.INT32_MIN, '\x80\x80\x80\x80\xf8\xff\xff\xff\xff\x01'),
- ]
- self.AppendNumericTestHelper(append_fn, values_and_expected_strings)
-
- self.AppendOverflowTestHelper(append_fn, wire_format.INT32_MAX + 1)
- self.AppendOverflowTestHelper(append_fn, wire_format.INT32_MIN - 1)
-
- def testAppendVarUInt32(self):
- append_fn = output_stream.OutputStream.AppendVarUInt32
- values_and_expected_strings = [
- (0, '\x00'),
- (1, '\x01'),
- (127, '\x7f'),
- (128, '\x80\x01'),
- (wire_format.UINT32_MAX, '\xff\xff\xff\xff\x0f'),
- ]
- self.AppendNumericTestHelper(append_fn, values_and_expected_strings)
-
- self.AppendOverflowTestHelper(append_fn, -1)
- self.AppendOverflowTestHelper(append_fn, wire_format.UINT32_MAX + 1)
-
- def testAppendVarint64(self):
- append_fn = output_stream.OutputStream.AppendVarint64
- values_and_expected_strings = [
- (0, '\x00'),
- (1, '\x01'),
- (127, '\x7f'),
- (128, '\x80\x01'),
- (-1, '\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01'),
- (wire_format.INT64_MAX, '\xff\xff\xff\xff\xff\xff\xff\xff\x7f'),
- (wire_format.INT64_MIN, '\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01'),
- ]
- self.AppendNumericTestHelper(append_fn, values_and_expected_strings)
-
- self.AppendOverflowTestHelper(append_fn, wire_format.INT64_MAX + 1)
- self.AppendOverflowTestHelper(append_fn, wire_format.INT64_MIN - 1)
-
- def testAppendVarUInt64(self):
- append_fn = output_stream.OutputStream.AppendVarUInt64
- values_and_expected_strings = [
- (0, '\x00'),
- (1, '\x01'),
- (127, '\x7f'),
- (128, '\x80\x01'),
- (wire_format.UINT64_MAX, '\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01'),
- ]
- self.AppendNumericTestHelper(append_fn, values_and_expected_strings)
-
- self.AppendOverflowTestHelper(append_fn, -1)
- self.AppendOverflowTestHelper(append_fn, wire_format.UINT64_MAX + 1)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index 86101774..2c9fa30b 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -38,6 +38,7 @@ pure-Python protocol compiler.
__author__ = 'robinson@google.com (Will Robinson)'
import operator
+import struct
import unittest
# TODO(robinson): When we split this test in two, only some of these imports
@@ -56,6 +57,51 @@ from google.protobuf.internal import test_util
from google.protobuf.internal import decoder
+class _MiniDecoder(object):
+ """Decodes a stream of values from a string.
+
+ Once upon a time we actually had a class called decoder.Decoder. Then we
+ got rid of it during a redesign that made decoding much, much faster overall.
+ But a couple tests in this file used it to check that the serialized form of
+ a message was correct. So, this class implements just the methods that were
+ used by said tests, so that we don't have to rewrite the tests.
+ """
+
+ def __init__(self, bytes):
+ self._bytes = bytes
+ self._pos = 0
+
+ def ReadVarint(self):
+ result, self._pos = decoder._DecodeVarint(self._bytes, self._pos)
+ return result
+
+ ReadInt32 = ReadVarint
+ ReadInt64 = ReadVarint
+ ReadUInt32 = ReadVarint
+ ReadUInt64 = ReadVarint
+
+ def ReadSInt64(self):
+ return wire_format.ZigZagDecode(self.ReadVarint())
+
+ ReadSInt32 = ReadSInt64
+
+ def ReadFieldNumberAndWireType(self):
+ return wire_format.UnpackTag(self.ReadVarint())
+
+ def ReadFloat(self):
+ result = struct.unpack("<f", self._bytes[self._pos:self._pos+4])[0]
+ self._pos += 4
+ return result
+
+ def ReadDouble(self):
+ result = struct.unpack("<d", self._bytes[self._pos:self._pos+8])[0]
+ self._pos += 8
+ return result
+
+ def EndOfStream(self):
+ return self._pos == len(self._bytes)
+
+
class ReflectionTest(unittest.TestCase):
def assertIs(self, values, others):
@@ -63,6 +109,97 @@ class ReflectionTest(unittest.TestCase):
for i in range(len(values)):
self.assertTrue(values[i] is others[i])
+ def testScalarConstructor(self):
+ # Constructor with only scalar types should succeed.
+ proto = unittest_pb2.TestAllTypes(
+ optional_int32=24,
+ optional_double=54.321,
+ optional_string='optional_string')
+
+ self.assertEqual(24, proto.optional_int32)
+ self.assertEqual(54.321, proto.optional_double)
+ self.assertEqual('optional_string', proto.optional_string)
+
+ def testRepeatedScalarConstructor(self):
+ # Constructor with only repeated scalar types should succeed.
+ proto = unittest_pb2.TestAllTypes(
+ repeated_int32=[1, 2, 3, 4],
+ repeated_double=[1.23, 54.321],
+ repeated_bool=[True, False, False],
+ repeated_string=["optional_string"])
+
+ self.assertEquals([1, 2, 3, 4], list(proto.repeated_int32))
+ self.assertEquals([1.23, 54.321], list(proto.repeated_double))
+ self.assertEquals([True, False, False], list(proto.repeated_bool))
+ self.assertEquals(["optional_string"], list(proto.repeated_string))
+
+ def testRepeatedCompositeConstructor(self):
+ # Constructor with only repeated composite types should succeed.
+ proto = unittest_pb2.TestAllTypes(
+ repeated_nested_message=[
+ unittest_pb2.TestAllTypes.NestedMessage(
+ bb=unittest_pb2.TestAllTypes.FOO),
+ unittest_pb2.TestAllTypes.NestedMessage(
+ bb=unittest_pb2.TestAllTypes.BAR)],
+ repeated_foreign_message=[
+ unittest_pb2.ForeignMessage(c=-43),
+ unittest_pb2.ForeignMessage(c=45324),
+ unittest_pb2.ForeignMessage(c=12)],
+ repeatedgroup=[
+ unittest_pb2.TestAllTypes.RepeatedGroup(),
+ unittest_pb2.TestAllTypes.RepeatedGroup(a=1),
+ unittest_pb2.TestAllTypes.RepeatedGroup(a=2)])
+
+ self.assertEquals(
+ [unittest_pb2.TestAllTypes.NestedMessage(
+ bb=unittest_pb2.TestAllTypes.FOO),
+ unittest_pb2.TestAllTypes.NestedMessage(
+ bb=unittest_pb2.TestAllTypes.BAR)],
+ list(proto.repeated_nested_message))
+ self.assertEquals(
+ [unittest_pb2.ForeignMessage(c=-43),
+ unittest_pb2.ForeignMessage(c=45324),
+ unittest_pb2.ForeignMessage(c=12)],
+ list(proto.repeated_foreign_message))
+ self.assertEquals(
+ [unittest_pb2.TestAllTypes.RepeatedGroup(),
+ unittest_pb2.TestAllTypes.RepeatedGroup(a=1),
+ unittest_pb2.TestAllTypes.RepeatedGroup(a=2)],
+ list(proto.repeatedgroup))
+
+ def testMixedConstructor(self):
+ # Constructor with only mixed types should succeed.
+ proto = unittest_pb2.TestAllTypes(
+ optional_int32=24,
+ optional_string='optional_string',
+ repeated_double=[1.23, 54.321],
+ repeated_bool=[True, False, False],
+ repeated_nested_message=[
+ unittest_pb2.TestAllTypes.NestedMessage(
+ bb=unittest_pb2.TestAllTypes.FOO),
+ unittest_pb2.TestAllTypes.NestedMessage(
+ bb=unittest_pb2.TestAllTypes.BAR)],
+ repeated_foreign_message=[
+ unittest_pb2.ForeignMessage(c=-43),
+ unittest_pb2.ForeignMessage(c=45324),
+ unittest_pb2.ForeignMessage(c=12)])
+
+ self.assertEqual(24, proto.optional_int32)
+ self.assertEqual('optional_string', proto.optional_string)
+ self.assertEquals([1.23, 54.321], list(proto.repeated_double))
+ self.assertEquals([True, False, False], list(proto.repeated_bool))
+ self.assertEquals(
+ [unittest_pb2.TestAllTypes.NestedMessage(
+ bb=unittest_pb2.TestAllTypes.FOO),
+ unittest_pb2.TestAllTypes.NestedMessage(
+ bb=unittest_pb2.TestAllTypes.BAR)],
+ list(proto.repeated_nested_message))
+ self.assertEquals(
+ [unittest_pb2.ForeignMessage(c=-43),
+ unittest_pb2.ForeignMessage(c=45324),
+ unittest_pb2.ForeignMessage(c=12)],
+ list(proto.repeated_foreign_message))
+
def testSimpleHasBits(self):
# Test a scalar.
proto = unittest_pb2.TestAllTypes()
@@ -218,12 +355,23 @@ class ReflectionTest(unittest.TestCase):
proto.optional_fixed32 = 1
proto.optional_int32 = 5
proto.optional_string = 'foo'
+ # Access sub-message but don't set it yet.
+ nested_message = proto.optional_nested_message
self.assertEqual(
[ (proto.DESCRIPTOR.fields_by_name['optional_int32' ], 5),
(proto.DESCRIPTOR.fields_by_name['optional_fixed32'], 1),
(proto.DESCRIPTOR.fields_by_name['optional_string' ], 'foo') ],
proto.ListFields())
+ proto.optional_nested_message.bb = 123
+ self.assertEqual(
+ [ (proto.DESCRIPTOR.fields_by_name['optional_int32' ], 5),
+ (proto.DESCRIPTOR.fields_by_name['optional_fixed32'], 1),
+ (proto.DESCRIPTOR.fields_by_name['optional_string' ], 'foo'),
+ (proto.DESCRIPTOR.fields_by_name['optional_nested_message' ],
+ nested_message) ],
+ proto.ListFields())
+
def testRepeatedListFields(self):
proto = unittest_pb2.TestAllTypes()
proto.repeated_fixed32.append(1)
@@ -234,6 +382,7 @@ class ReflectionTest(unittest.TestCase):
proto.repeated_string.append('baz')
proto.repeated_string.extend(str(x) for x in xrange(2))
proto.optional_int32 = 21
+ proto.repeated_bool # Access but don't set anything; should not be listed.
self.assertEqual(
[ (proto.DESCRIPTOR.fields_by_name['optional_int32' ], 21),
(proto.DESCRIPTOR.fields_by_name['repeated_int32' ], [5, 11]),
@@ -731,7 +880,6 @@ class ReflectionTest(unittest.TestCase):
extendee_proto.ClearExtension(extension)
extension_proto.foreign_message_int = 23
- self.assertTrue(not toplevel.HasField('submessage'))
self.assertTrue(extension_proto is not extendee_proto.Extensions[extension])
def testExtensionFailureModes(self):
@@ -957,57 +1105,75 @@ class ReflectionTest(unittest.TestCase):
empty_proto = unittest_pb2.TestAllExtensions()
self.assertEquals(proto, empty_proto)
+ def assertInitialized(self, proto):
+ self.assertTrue(proto.IsInitialized())
+ # Neither method should raise an exception.
+ proto.SerializeToString()
+ proto.SerializePartialToString()
+
+ def assertNotInitialized(self, proto):
+ self.assertFalse(proto.IsInitialized())
+ self.assertRaises(message.EncodeError, proto.SerializeToString)
+ # "Partial" serialization doesn't care if message is uninitialized.
+ proto.SerializePartialToString()
+
def testIsInitialized(self):
# Trivial cases - all optional fields and extensions.
proto = unittest_pb2.TestAllTypes()
- self.assertTrue(proto.IsInitialized())
+ self.assertInitialized(proto)
proto = unittest_pb2.TestAllExtensions()
- self.assertTrue(proto.IsInitialized())
+ self.assertInitialized(proto)
# The case of uninitialized required fields.
proto = unittest_pb2.TestRequired()
- self.assertFalse(proto.IsInitialized())
+ self.assertNotInitialized(proto)
proto.a = proto.b = proto.c = 2
- self.assertTrue(proto.IsInitialized())
+ self.assertInitialized(proto)
# The case of uninitialized submessage.
proto = unittest_pb2.TestRequiredForeign()
- self.assertTrue(proto.IsInitialized())
+ self.assertInitialized(proto)
proto.optional_message.a = 1
- self.assertFalse(proto.IsInitialized())
+ self.assertNotInitialized(proto)
proto.optional_message.b = 0
proto.optional_message.c = 0
- self.assertTrue(proto.IsInitialized())
+ self.assertInitialized(proto)
# Uninitialized repeated submessage.
message1 = proto.repeated_message.add()
- self.assertFalse(proto.IsInitialized())
+ self.assertNotInitialized(proto)
message1.a = message1.b = message1.c = 0
- self.assertTrue(proto.IsInitialized())
+ self.assertInitialized(proto)
# Uninitialized repeated group in an extension.
proto = unittest_pb2.TestAllExtensions()
extension = unittest_pb2.TestRequired.multi
message1 = proto.Extensions[extension].add()
message2 = proto.Extensions[extension].add()
- self.assertFalse(proto.IsInitialized())
+ self.assertNotInitialized(proto)
message1.a = 1
message1.b = 1
message1.c = 1
- self.assertFalse(proto.IsInitialized())
+ self.assertNotInitialized(proto)
message2.a = 2
message2.b = 2
message2.c = 2
- self.assertTrue(proto.IsInitialized())
+ self.assertInitialized(proto)
# Uninitialized nonrepeated message in an extension.
proto = unittest_pb2.TestAllExtensions()
extension = unittest_pb2.TestRequired.single
proto.Extensions[extension].a = 1
- self.assertFalse(proto.IsInitialized())
+ self.assertNotInitialized(proto)
proto.Extensions[extension].b = 2
proto.Extensions[extension].c = 3
- self.assertTrue(proto.IsInitialized())
+ self.assertInitialized(proto)
+
+ # Try passing an errors list.
+ errors = []
+ proto = unittest_pb2.TestRequired()
+ self.assertFalse(proto.IsInitialized(errors))
+ self.assertEqual(errors, ['a', 'b', 'c'])
def testStringUTF8Encoding(self):
proto = unittest_pb2.TestAllTypes()
@@ -1079,6 +1245,36 @@ class ReflectionTest(unittest.TestCase):
test_utf8_bytes, len(test_utf8_bytes) * '\xff')
self.assertRaises(UnicodeDecodeError, message2.MergeFromString, bytes)
+ def testEmptyNestedMessage(self):
+ proto = unittest_pb2.TestAllTypes()
+ proto.optional_nested_message.MergeFrom(
+ unittest_pb2.TestAllTypes.NestedMessage())
+ self.assertTrue(proto.HasField('optional_nested_message'))
+
+ proto = unittest_pb2.TestAllTypes()
+ proto.optional_nested_message.CopyFrom(
+ unittest_pb2.TestAllTypes.NestedMessage())
+ self.assertTrue(proto.HasField('optional_nested_message'))
+
+ proto = unittest_pb2.TestAllTypes()
+ proto.optional_nested_message.MergeFromString('')
+ self.assertTrue(proto.HasField('optional_nested_message'))
+
+ proto = unittest_pb2.TestAllTypes()
+ proto.optional_nested_message.ParseFromString('')
+ self.assertTrue(proto.HasField('optional_nested_message'))
+
+ serialized = proto.SerializeToString()
+ proto2 = unittest_pb2.TestAllTypes()
+ proto2.MergeFromString(serialized)
+ self.assertTrue(proto2.HasField('optional_nested_message'))
+
+ def testSetInParent(self):
+ proto = unittest_pb2.TestAllTypes()
+ self.assertFalse(proto.HasField('optionalgroup'))
+ proto.optionalgroup.SetInParent()
+ self.assertTrue(proto.HasField('optionalgroup'))
+
# Since we had so many tests for protocol buffer equality, we broke these out
# into separate TestCase classes.
@@ -1541,6 +1737,47 @@ class SerializationTest(unittest.TestCase):
second_proto.MergeFromString(serialized)
self.assertEqual(first_proto, second_proto)
+ def testSerializeNegativeValues(self):
+ first_proto = unittest_pb2.TestAllTypes()
+
+ first_proto.optional_int32 = -1
+ first_proto.optional_int64 = -(2 << 40)
+ first_proto.optional_sint32 = -3
+ first_proto.optional_sint64 = -(4 << 40)
+ first_proto.optional_sfixed32 = -5
+ first_proto.optional_sfixed64 = -(6 << 40)
+
+ second_proto = unittest_pb2.TestAllTypes.FromString(
+ first_proto.SerializeToString())
+
+ self.assertEqual(first_proto, second_proto)
+
+ def testParseTruncated(self):
+ first_proto = unittest_pb2.TestAllTypes()
+ test_util.SetAllFields(first_proto)
+ serialized = first_proto.SerializeToString()
+
+ for truncation_point in xrange(len(serialized) + 1):
+ try:
+ second_proto = unittest_pb2.TestAllTypes()
+ unknown_fields = unittest_pb2.TestEmptyMessage()
+ pos = second_proto._InternalParse(serialized, 0, truncation_point)
+ # If we didn't raise an error then we read exactly the amount expected.
+ self.assertEqual(truncation_point, pos)
+
+ # Parsing to unknown fields should not throw if parsing to known fields
+ # did not.
+ try:
+ pos2 = unknown_fields._InternalParse(serialized, 0, truncation_point)
+ self.assertEqual(truncation_point, pos2)
+ except message.DecodeError:
+ self.fail('Parsing unknown fields failed when parsing known fields '
+ 'did not.')
+ except message.DecodeError:
+ # Parsing unknown fields should also fail.
+ self.assertRaises(message.DecodeError, unknown_fields._InternalParse,
+ serialized, 0, truncation_point)
+
def testCanonicalSerializationOrder(self):
proto = more_messages_pb2.OutOfOrderFields()
# These are also their tag numbers. Even though we're setting these in
@@ -1553,7 +1790,7 @@ class SerializationTest(unittest.TestCase):
proto.optional_int32 = 1
serialized = proto.SerializeToString()
self.assertEqual(proto.ByteSize(), len(serialized))
- d = decoder.Decoder(serialized)
+ d = _MiniDecoder(serialized)
ReadTag = d.ReadFieldNumberAndWireType
self.assertEqual((1, wire_format.WIRETYPE_VARINT), ReadTag())
self.assertEqual(1, d.ReadInt32())
@@ -1709,7 +1946,7 @@ class SerializationTest(unittest.TestCase):
self._CheckRaises(
message.EncodeError,
proto.SerializeToString,
- 'Required field protobuf_unittest.TestRequired.a is not set.')
+ 'Message is missing required fields: a,b,c')
# Shouldn't raise exceptions.
partial = proto.SerializePartialToString()
@@ -1717,7 +1954,7 @@ class SerializationTest(unittest.TestCase):
self._CheckRaises(
message.EncodeError,
proto.SerializeToString,
- 'Required field protobuf_unittest.TestRequired.b is not set.')
+ 'Message is missing required fields: b,c')
# Shouldn't raise exceptions.
partial = proto.SerializePartialToString()
@@ -1725,7 +1962,7 @@ class SerializationTest(unittest.TestCase):
self._CheckRaises(
message.EncodeError,
proto.SerializeToString,
- 'Required field protobuf_unittest.TestRequired.c is not set.')
+ 'Message is missing required fields: c')
# Shouldn't raise exceptions.
partial = proto.SerializePartialToString()
@@ -1744,6 +1981,38 @@ class SerializationTest(unittest.TestCase):
self.assertEqual(2, proto2.b)
self.assertEqual(3, proto2.c)
+ def testSerializeUninitializedSubMessage(self):
+ proto = unittest_pb2.TestRequiredForeign()
+
+ # Sub-message doesn't exist yet, so this succeeds.
+ proto.SerializeToString()
+
+ proto.optional_message.a = 1
+ self._CheckRaises(
+ message.EncodeError,
+ proto.SerializeToString,
+ 'Message is missing required fields: '
+ 'optional_message.b,optional_message.c')
+
+ proto.optional_message.b = 2
+ proto.optional_message.c = 3
+ proto.SerializeToString()
+
+ proto.repeated_message.add().a = 1
+ proto.repeated_message.add().b = 2
+ self._CheckRaises(
+ message.EncodeError,
+ proto.SerializeToString,
+ 'Message is missing required fields: '
+ 'repeated_message[0].b,repeated_message[0].c,'
+ 'repeated_message[1].a,repeated_message[1].c')
+
+ proto.repeated_message[0].b = 2
+ proto.repeated_message[0].c = 3
+ proto.repeated_message[1].a = 1
+ proto.repeated_message[1].c = 3
+ proto.SerializeToString()
+
def testSerializeAllPackedFields(self):
first_proto = unittest_pb2.TestPackedTypes()
second_proto = unittest_pb2.TestPackedTypes()
@@ -1786,7 +2055,7 @@ class SerializationTest(unittest.TestCase):
proto.packed_float.append(2.0) # 4 bytes, will be before double
serialized = proto.SerializeToString()
self.assertEqual(proto.ByteSize(), len(serialized))
- d = decoder.Decoder(serialized)
+ d = _MiniDecoder(serialized)
ReadTag = d.ReadFieldNumberAndWireType
self.assertEqual((90, wire_format.WIRETYPE_LENGTH_DELIMITED), ReadTag())
self.assertEqual(1+1+1+2, d.ReadInt32())
@@ -1803,6 +2072,24 @@ class SerializationTest(unittest.TestCase):
self.assertEqual(1000.0, d.ReadDouble())
self.assertTrue(d.EndOfStream())
+ def testParsePackedFromUnpacked(self):
+ unpacked = unittest_pb2.TestUnpackedTypes()
+ test_util.SetAllUnpackedFields(unpacked)
+ packed = unittest_pb2.TestPackedTypes()
+ packed.MergeFromString(unpacked.SerializeToString())
+ expected = unittest_pb2.TestPackedTypes()
+ test_util.SetAllPackedFields(expected)
+ self.assertEqual(expected, packed)
+
+ def testParseUnpackedFromPacked(self):
+ packed = unittest_pb2.TestPackedTypes()
+ test_util.SetAllPackedFields(packed)
+ unpacked = unittest_pb2.TestUnpackedTypes()
+ unpacked.MergeFromString(packed.SerializeToString())
+ expected = unittest_pb2.TestUnpackedTypes()
+ test_util.SetAllUnpackedFields(expected)
+ self.assertEqual(expected, unpacked)
+
def testFieldNumbers(self):
proto = unittest_pb2.TestAllTypes()
self.assertEqual(unittest_pb2.TestAllTypes.NestedMessage.BB_FIELD_NUMBER, 1)
@@ -1944,33 +2231,6 @@ class OptionsTest(unittest.TestCase):
field_descriptor.label)
-class UtilityTest(unittest.TestCase):
-
- def testImergeSorted(self):
- ImergeSorted = reflection._ImergeSorted
- # Various types of emptiness.
- self.assertEqual([], list(ImergeSorted()))
- self.assertEqual([], list(ImergeSorted([])))
- self.assertEqual([], list(ImergeSorted([], [])))
-
- # One nonempty list.
- self.assertEqual([1, 2, 3], list(ImergeSorted([1, 2, 3])))
- self.assertEqual([1, 2, 3], list(ImergeSorted([1, 2, 3], [])))
- self.assertEqual([1, 2, 3], list(ImergeSorted([], [1, 2, 3])))
-
- # Merging some nonempty lists together.
- self.assertEqual([1, 2, 3], list(ImergeSorted([1, 3], [2])))
- self.assertEqual([1, 2, 3], list(ImergeSorted([1], [3], [2])))
- self.assertEqual([1, 2, 3], list(ImergeSorted([1], [3], [2], [])))
-
- # Elements repeated across component iterators.
- self.assertEqual([1, 2, 2, 3, 3],
- list(ImergeSorted([1, 2], [3], [2, 3])))
-
- # Elements repeated within an iterator.
- self.assertEqual([1, 2, 2, 3, 3],
- list(ImergeSorted([1, 2, 2], [3], [3])))
-
if __name__ == '__main__':
unittest.main()
diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py
index 1a0da552..1df16194 100755
--- a/python/google/protobuf/internal/test_util.py
+++ b/python/google/protobuf/internal/test_util.py
@@ -31,14 +31,13 @@
"""Utilities for Python proto2 tests.
This is intentionally modeled on C++ code in
-//net/proto2/internal/test_util.*.
+//google/protobuf/test_util.*.
"""
__author__ = 'robinson@google.com (Will Robinson)'
import os.path
-import unittest
from google.protobuf import unittest_import_pb2
from google.protobuf import unittest_pb2
@@ -353,198 +352,198 @@ def ExpectAllFieldsAndExtensionsInOrder(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 ExpectAllFieldsSet(test_case, message):
+ """Check all fields for correct values have after Set*Fields() is called."""
+ test_case.assertTrue(message.HasField('optional_int32'))
+ test_case.assertTrue(message.HasField('optional_int64'))
+ test_case.assertTrue(message.HasField('optional_uint32'))
+ test_case.assertTrue(message.HasField('optional_uint64'))
+ test_case.assertTrue(message.HasField('optional_sint32'))
+ test_case.assertTrue(message.HasField('optional_sint64'))
+ test_case.assertTrue(message.HasField('optional_fixed32'))
+ test_case.assertTrue(message.HasField('optional_fixed64'))
+ test_case.assertTrue(message.HasField('optional_sfixed32'))
+ test_case.assertTrue(message.HasField('optional_sfixed64'))
+ test_case.assertTrue(message.HasField('optional_float'))
+ test_case.assertTrue(message.HasField('optional_double'))
+ test_case.assertTrue(message.HasField('optional_bool'))
+ test_case.assertTrue(message.HasField('optional_string'))
+ test_case.assertTrue(message.HasField('optional_bytes'))
+
+ test_case.assertTrue(message.HasField('optionalgroup'))
+ test_case.assertTrue(message.HasField('optional_nested_message'))
+ test_case.assertTrue(message.HasField('optional_foreign_message'))
+ test_case.assertTrue(message.HasField('optional_import_message'))
+
+ test_case.assertTrue(message.optionalgroup.HasField('a'))
+ test_case.assertTrue(message.optional_nested_message.HasField('bb'))
+ test_case.assertTrue(message.optional_foreign_message.HasField('c'))
+ test_case.assertTrue(message.optional_import_message.HasField('d'))
+
+ test_case.assertTrue(message.HasField('optional_nested_enum'))
+ test_case.assertTrue(message.HasField('optional_foreign_enum'))
+ test_case.assertTrue(message.HasField('optional_import_enum'))
+
+ test_case.assertTrue(message.HasField('optional_string_piece'))
+ test_case.assertTrue(message.HasField('optional_cord'))
+
+ test_case.assertEqual(101, message.optional_int32)
+ test_case.assertEqual(102, message.optional_int64)
+ test_case.assertEqual(103, message.optional_uint32)
+ test_case.assertEqual(104, message.optional_uint64)
+ test_case.assertEqual(105, message.optional_sint32)
+ test_case.assertEqual(106, message.optional_sint64)
+ test_case.assertEqual(107, message.optional_fixed32)
+ test_case.assertEqual(108, message.optional_fixed64)
+ test_case.assertEqual(109, message.optional_sfixed32)
+ test_case.assertEqual(110, message.optional_sfixed64)
+ test_case.assertEqual(111, message.optional_float)
+ test_case.assertEqual(112, message.optional_double)
+ test_case.assertEqual(True, message.optional_bool)
+ test_case.assertEqual('115', message.optional_string)
+ test_case.assertEqual('116', message.optional_bytes)
+
+ test_case.assertEqual(117, message.optionalgroup.a)
+ test_case.assertEqual(118, message.optional_nested_message.bb)
+ test_case.assertEqual(119, message.optional_foreign_message.c)
+ test_case.assertEqual(120, message.optional_import_message.d)
+
+ test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ,
+ message.optional_nested_enum)
+ test_case.assertEqual(unittest_pb2.FOREIGN_BAZ,
+ message.optional_foreign_enum)
+ test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ,
+ message.optional_import_enum)
+
+ # -----------------------------------------------------------------
+
+ test_case.assertEqual(2, len(message.repeated_int32))
+ test_case.assertEqual(2, len(message.repeated_int64))
+ test_case.assertEqual(2, len(message.repeated_uint32))
+ test_case.assertEqual(2, len(message.repeated_uint64))
+ test_case.assertEqual(2, len(message.repeated_sint32))
+ test_case.assertEqual(2, len(message.repeated_sint64))
+ test_case.assertEqual(2, len(message.repeated_fixed32))
+ test_case.assertEqual(2, len(message.repeated_fixed64))
+ test_case.assertEqual(2, len(message.repeated_sfixed32))
+ test_case.assertEqual(2, len(message.repeated_sfixed64))
+ test_case.assertEqual(2, len(message.repeated_float))
+ test_case.assertEqual(2, len(message.repeated_double))
+ test_case.assertEqual(2, len(message.repeated_bool))
+ test_case.assertEqual(2, len(message.repeated_string))
+ test_case.assertEqual(2, len(message.repeated_bytes))
+
+ test_case.assertEqual(2, len(message.repeatedgroup))
+ test_case.assertEqual(2, len(message.repeated_nested_message))
+ test_case.assertEqual(2, len(message.repeated_foreign_message))
+ test_case.assertEqual(2, len(message.repeated_import_message))
+ test_case.assertEqual(2, len(message.repeated_nested_enum))
+ test_case.assertEqual(2, len(message.repeated_foreign_enum))
+ test_case.assertEqual(2, len(message.repeated_import_enum))
+
+ test_case.assertEqual(2, len(message.repeated_string_piece))
+ test_case.assertEqual(2, len(message.repeated_cord))
+
+ test_case.assertEqual(201, message.repeated_int32[0])
+ test_case.assertEqual(202, message.repeated_int64[0])
+ test_case.assertEqual(203, message.repeated_uint32[0])
+ test_case.assertEqual(204, message.repeated_uint64[0])
+ test_case.assertEqual(205, message.repeated_sint32[0])
+ test_case.assertEqual(206, message.repeated_sint64[0])
+ test_case.assertEqual(207, message.repeated_fixed32[0])
+ test_case.assertEqual(208, message.repeated_fixed64[0])
+ test_case.assertEqual(209, message.repeated_sfixed32[0])
+ test_case.assertEqual(210, message.repeated_sfixed64[0])
+ test_case.assertEqual(211, message.repeated_float[0])
+ test_case.assertEqual(212, message.repeated_double[0])
+ test_case.assertEqual(True, message.repeated_bool[0])
+ test_case.assertEqual('215', message.repeated_string[0])
+ test_case.assertEqual('216', message.repeated_bytes[0])
+
+ test_case.assertEqual(217, message.repeatedgroup[0].a)
+ test_case.assertEqual(218, message.repeated_nested_message[0].bb)
+ test_case.assertEqual(219, message.repeated_foreign_message[0].c)
+ test_case.assertEqual(220, message.repeated_import_message[0].d)
+
+ test_case.assertEqual(unittest_pb2.TestAllTypes.BAR,
+ message.repeated_nested_enum[0])
+ test_case.assertEqual(unittest_pb2.FOREIGN_BAR,
+ message.repeated_foreign_enum[0])
+ test_case.assertEqual(unittest_import_pb2.IMPORT_BAR,
+ message.repeated_import_enum[0])
+
+ test_case.assertEqual(301, message.repeated_int32[1])
+ test_case.assertEqual(302, message.repeated_int64[1])
+ test_case.assertEqual(303, message.repeated_uint32[1])
+ test_case.assertEqual(304, message.repeated_uint64[1])
+ test_case.assertEqual(305, message.repeated_sint32[1])
+ test_case.assertEqual(306, message.repeated_sint64[1])
+ test_case.assertEqual(307, message.repeated_fixed32[1])
+ test_case.assertEqual(308, message.repeated_fixed64[1])
+ test_case.assertEqual(309, message.repeated_sfixed32[1])
+ test_case.assertEqual(310, message.repeated_sfixed64[1])
+ test_case.assertEqual(311, message.repeated_float[1])
+ test_case.assertEqual(312, message.repeated_double[1])
+ test_case.assertEqual(False, message.repeated_bool[1])
+ test_case.assertEqual('315', message.repeated_string[1])
+ test_case.assertEqual('316', message.repeated_bytes[1])
+
+ test_case.assertEqual(317, message.repeatedgroup[1].a)
+ test_case.assertEqual(318, message.repeated_nested_message[1].bb)
+ test_case.assertEqual(319, message.repeated_foreign_message[1].c)
+ test_case.assertEqual(320, message.repeated_import_message[1].d)
+
+ test_case.assertEqual(unittest_pb2.TestAllTypes.BAZ,
+ message.repeated_nested_enum[1])
+ test_case.assertEqual(unittest_pb2.FOREIGN_BAZ,
+ message.repeated_foreign_enum[1])
+ test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ,
+ message.repeated_import_enum[1])
+
+ # -----------------------------------------------------------------
+
+ test_case.assertTrue(message.HasField('default_int32'))
+ test_case.assertTrue(message.HasField('default_int64'))
+ test_case.assertTrue(message.HasField('default_uint32'))
+ test_case.assertTrue(message.HasField('default_uint64'))
+ test_case.assertTrue(message.HasField('default_sint32'))
+ test_case.assertTrue(message.HasField('default_sint64'))
+ test_case.assertTrue(message.HasField('default_fixed32'))
+ test_case.assertTrue(message.HasField('default_fixed64'))
+ test_case.assertTrue(message.HasField('default_sfixed32'))
+ test_case.assertTrue(message.HasField('default_sfixed64'))
+ test_case.assertTrue(message.HasField('default_float'))
+ test_case.assertTrue(message.HasField('default_double'))
+ test_case.assertTrue(message.HasField('default_bool'))
+ test_case.assertTrue(message.HasField('default_string'))
+ test_case.assertTrue(message.HasField('default_bytes'))
+
+ test_case.assertTrue(message.HasField('default_nested_enum'))
+ test_case.assertTrue(message.HasField('default_foreign_enum'))
+ test_case.assertTrue(message.HasField('default_import_enum'))
+
+ test_case.assertEqual(401, message.default_int32)
+ test_case.assertEqual(402, message.default_int64)
+ test_case.assertEqual(403, message.default_uint32)
+ test_case.assertEqual(404, message.default_uint64)
+ test_case.assertEqual(405, message.default_sint32)
+ test_case.assertEqual(406, message.default_sint64)
+ test_case.assertEqual(407, message.default_fixed32)
+ test_case.assertEqual(408, message.default_fixed64)
+ test_case.assertEqual(409, message.default_sfixed32)
+ test_case.assertEqual(410, message.default_sfixed64)
+ test_case.assertEqual(411, message.default_float)
+ test_case.assertEqual(412, message.default_double)
+ test_case.assertEqual(False, message.default_bool)
+ test_case.assertEqual('415', message.default_string)
+ test_case.assertEqual('416', message.default_bytes)
+
+ test_case.assertEqual(unittest_pb2.TestAllTypes.FOO,
+ message.default_nested_enum)
+ test_case.assertEqual(unittest_pb2.FOREIGN_FOO,
+ message.default_foreign_enum)
+ test_case.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."""
@@ -570,21 +569,21 @@ def SetAllPackedFields(message):
Args:
message: A unittest_pb2.TestPackedTypes instance.
"""
- message.packed_int32.extend([101, 102])
- message.packed_int64.extend([103, 104])
- message.packed_uint32.extend([105, 106])
- message.packed_uint64.extend([107, 108])
- message.packed_sint32.extend([109, 110])
- message.packed_sint64.extend([111, 112])
- message.packed_fixed32.extend([113, 114])
- message.packed_fixed64.extend([115, 116])
- message.packed_sfixed32.extend([117, 118])
- message.packed_sfixed64.extend([119, 120])
- message.packed_float.extend([121.0, 122.0])
- message.packed_double.extend([122.0, 123.0])
+ message.packed_int32.extend([601, 701])
+ message.packed_int64.extend([602, 702])
+ message.packed_uint32.extend([603, 703])
+ message.packed_uint64.extend([604, 704])
+ message.packed_sint32.extend([605, 705])
+ message.packed_sint64.extend([606, 706])
+ message.packed_fixed32.extend([607, 707])
+ message.packed_fixed64.extend([608, 708])
+ message.packed_sfixed32.extend([609, 709])
+ message.packed_sfixed64.extend([610, 710])
+ message.packed_float.extend([611.0, 711.0])
+ message.packed_double.extend([612.0, 712.0])
message.packed_bool.extend([True, False])
- message.packed_enum.extend([unittest_pb2.FOREIGN_FOO,
- unittest_pb2.FOREIGN_BAR])
+ message.packed_enum.extend([unittest_pb2.FOREIGN_BAR,
+ unittest_pb2.FOREIGN_BAZ])
def SetAllPackedExtensions(message):
@@ -596,17 +595,41 @@ def SetAllPackedExtensions(message):
extensions = message.Extensions
pb2 = unittest_pb2
- extensions[pb2.packed_int32_extension].append(101)
- extensions[pb2.packed_int64_extension].append(102)
- extensions[pb2.packed_uint32_extension].append(103)
- extensions[pb2.packed_uint64_extension].append(104)
- extensions[pb2.packed_sint32_extension].append(105)
- extensions[pb2.packed_sint64_extension].append(106)
- extensions[pb2.packed_fixed32_extension].append(107)
- extensions[pb2.packed_fixed64_extension].append(108)
- extensions[pb2.packed_sfixed32_extension].append(109)
- extensions[pb2.packed_sfixed64_extension].append(110)
- extensions[pb2.packed_float_extension].append(111.0)
- extensions[pb2.packed_double_extension].append(112.0)
- extensions[pb2.packed_bool_extension].append(True)
- extensions[pb2.packed_enum_extension].append(pb2.FOREIGN_BAZ)
+ extensions[pb2.packed_int32_extension].extend([601, 701])
+ extensions[pb2.packed_int64_extension].extend([602, 702])
+ extensions[pb2.packed_uint32_extension].extend([603, 703])
+ extensions[pb2.packed_uint64_extension].extend([604, 704])
+ extensions[pb2.packed_sint32_extension].extend([605, 705])
+ extensions[pb2.packed_sint64_extension].extend([606, 706])
+ extensions[pb2.packed_fixed32_extension].extend([607, 707])
+ extensions[pb2.packed_fixed64_extension].extend([608, 708])
+ extensions[pb2.packed_sfixed32_extension].extend([609, 709])
+ extensions[pb2.packed_sfixed64_extension].extend([610, 710])
+ extensions[pb2.packed_float_extension].extend([611.0, 711.0])
+ extensions[pb2.packed_double_extension].extend([612.0, 712.0])
+ extensions[pb2.packed_bool_extension].extend([True, False])
+ extensions[pb2.packed_enum_extension].extend([unittest_pb2.FOREIGN_BAR,
+ unittest_pb2.FOREIGN_BAZ])
+
+
+def SetAllUnpackedFields(message):
+ """Sets every field in the message to a unique value.
+
+ Args:
+ message: A unittest_pb2.TestUnpackedTypes instance.
+ """
+ message.unpacked_int32.extend([601, 701])
+ message.unpacked_int64.extend([602, 702])
+ message.unpacked_uint32.extend([603, 703])
+ message.unpacked_uint64.extend([604, 704])
+ message.unpacked_sint32.extend([605, 705])
+ message.unpacked_sint64.extend([606, 706])
+ message.unpacked_fixed32.extend([607, 707])
+ message.unpacked_fixed64.extend([608, 708])
+ message.unpacked_sfixed32.extend([609, 709])
+ message.unpacked_sfixed64.extend([610, 710])
+ message.unpacked_float.extend([611.0, 711.0])
+ message.unpacked_double.extend([612.0, 712.0])
+ message.unpacked_bool.extend([True, False])
+ message.unpacked_enum.extend([unittest_pb2.FOREIGN_BAR,
+ unittest_pb2.FOREIGN_BAZ])
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index 0cf27186..0208139e 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -43,7 +43,7 @@ from google.protobuf import unittest_pb2
from google.protobuf import unittest_mset_pb2
-class TextFormatTest(test_util.GoldenMessageTestCase):
+class TextFormatTest(unittest.TestCase):
def ReadGolden(self, golden_filename):
f = test_util.GoldenFile(golden_filename)
golden_lines = f.readlines()
@@ -149,7 +149,7 @@ class TextFormatTest(test_util.GoldenMessageTestCase):
parsed_message = unittest_pb2.TestAllTypes()
text_format.Merge(ascii_text, parsed_message)
self.assertEqual(message, parsed_message)
- self.ExpectAllFieldsSet(message)
+ test_util.ExpectAllFieldsSet(self, message)
def testMergeAllExtensions(self):
message = unittest_pb2.TestAllExtensions()
@@ -212,12 +212,18 @@ class TextFormatTest(test_util.GoldenMessageTestCase):
text_format.Merge, text, message)
def testMergeBadExtension(self):
- message = unittest_pb2.TestAllTypes()
+ message = unittest_pb2.TestAllExtensions()
text = '[unknown_extension]: 8\n'
self.assertRaisesWithMessage(
text_format.ParseError,
'1:2 : Extension "unknown_extension" not registered.',
text_format.Merge, text, message)
+ message = unittest_pb2.TestAllTypes()
+ self.assertRaisesWithMessage(
+ text_format.ParseError,
+ ('1:2 : Message type "protobuf_unittest.TestAllTypes" does not have '
+ 'extensions.'),
+ text_format.Merge, text, message)
def testMergeGroupNotClosed(self):
message = unittest_pb2.TestAllTypes()
@@ -231,6 +237,19 @@ class TextFormatTest(test_util.GoldenMessageTestCase):
text_format.ParseError, '1:16 : Expected "}".',
text_format.Merge, text, message)
+ def testMergeEmptyGroup(self):
+ message = unittest_pb2.TestAllTypes()
+ text = 'OptionalGroup: {}'
+ text_format.Merge(text, message)
+ self.assertTrue(message.HasField('optionalgroup'))
+
+ message.Clear()
+
+ message = unittest_pb2.TestAllTypes()
+ text = 'OptionalGroup: <>'
+ text_format.Merge(text, message)
+ self.assertTrue(message.HasField('optionalgroup'))
+
def testMergeBadEnumValue(self):
message = unittest_pb2.TestAllTypes()
text = 'optional_nested_enum: BARR'
diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py
index a3bc57ff..2b3cd4de 100755
--- a/python/google/protobuf/internal/type_checkers.py
+++ b/python/google/protobuf/internal/type_checkers.py
@@ -192,47 +192,72 @@ TYPE_TO_BYTE_SIZE_FN = {
}
-# Maps from field type to an unbound Encoder method F, such that
-# F(encoder, field_number, value) will append the serialization
-# of a value of this type to the encoder.
-_Encoder = encoder.Encoder
-TYPE_TO_SERIALIZE_METHOD = {
- _FieldDescriptor.TYPE_DOUBLE: _Encoder.AppendDouble,
- _FieldDescriptor.TYPE_FLOAT: _Encoder.AppendFloat,
- _FieldDescriptor.TYPE_INT64: _Encoder.AppendInt64,
- _FieldDescriptor.TYPE_UINT64: _Encoder.AppendUInt64,
- _FieldDescriptor.TYPE_INT32: _Encoder.AppendInt32,
- _FieldDescriptor.TYPE_FIXED64: _Encoder.AppendFixed64,
- _FieldDescriptor.TYPE_FIXED32: _Encoder.AppendFixed32,
- _FieldDescriptor.TYPE_BOOL: _Encoder.AppendBool,
- _FieldDescriptor.TYPE_STRING: _Encoder.AppendString,
- _FieldDescriptor.TYPE_GROUP: _Encoder.AppendGroup,
- _FieldDescriptor.TYPE_MESSAGE: _Encoder.AppendMessage,
- _FieldDescriptor.TYPE_BYTES: _Encoder.AppendBytes,
- _FieldDescriptor.TYPE_UINT32: _Encoder.AppendUInt32,
- _FieldDescriptor.TYPE_ENUM: _Encoder.AppendEnum,
- _FieldDescriptor.TYPE_SFIXED32: _Encoder.AppendSFixed32,
- _FieldDescriptor.TYPE_SFIXED64: _Encoder.AppendSFixed64,
- _FieldDescriptor.TYPE_SINT32: _Encoder.AppendSInt32,
- _FieldDescriptor.TYPE_SINT64: _Encoder.AppendSInt64,
+# Maps from field types to encoder constructors.
+TYPE_TO_ENCODER = {
+ _FieldDescriptor.TYPE_DOUBLE: encoder.DoubleEncoder,
+ _FieldDescriptor.TYPE_FLOAT: encoder.FloatEncoder,
+ _FieldDescriptor.TYPE_INT64: encoder.Int64Encoder,
+ _FieldDescriptor.TYPE_UINT64: encoder.UInt64Encoder,
+ _FieldDescriptor.TYPE_INT32: encoder.Int32Encoder,
+ _FieldDescriptor.TYPE_FIXED64: encoder.Fixed64Encoder,
+ _FieldDescriptor.TYPE_FIXED32: encoder.Fixed32Encoder,
+ _FieldDescriptor.TYPE_BOOL: encoder.BoolEncoder,
+ _FieldDescriptor.TYPE_STRING: encoder.StringEncoder,
+ _FieldDescriptor.TYPE_GROUP: encoder.GroupEncoder,
+ _FieldDescriptor.TYPE_MESSAGE: encoder.MessageEncoder,
+ _FieldDescriptor.TYPE_BYTES: encoder.BytesEncoder,
+ _FieldDescriptor.TYPE_UINT32: encoder.UInt32Encoder,
+ _FieldDescriptor.TYPE_ENUM: encoder.EnumEncoder,
+ _FieldDescriptor.TYPE_SFIXED32: encoder.SFixed32Encoder,
+ _FieldDescriptor.TYPE_SFIXED64: encoder.SFixed64Encoder,
+ _FieldDescriptor.TYPE_SINT32: encoder.SInt32Encoder,
+ _FieldDescriptor.TYPE_SINT64: encoder.SInt64Encoder,
}
-TYPE_TO_NOTAG_SERIALIZE_METHOD = {
- _FieldDescriptor.TYPE_DOUBLE: _Encoder.AppendDoubleNoTag,
- _FieldDescriptor.TYPE_FLOAT: _Encoder.AppendFloatNoTag,
- _FieldDescriptor.TYPE_INT64: _Encoder.AppendInt64NoTag,
- _FieldDescriptor.TYPE_UINT64: _Encoder.AppendUInt64NoTag,
- _FieldDescriptor.TYPE_INT32: _Encoder.AppendInt32NoTag,
- _FieldDescriptor.TYPE_FIXED64: _Encoder.AppendFixed64NoTag,
- _FieldDescriptor.TYPE_FIXED32: _Encoder.AppendFixed32NoTag,
- _FieldDescriptor.TYPE_BOOL: _Encoder.AppendBoolNoTag,
- _FieldDescriptor.TYPE_UINT32: _Encoder.AppendUInt32NoTag,
- _FieldDescriptor.TYPE_ENUM: _Encoder.AppendEnumNoTag,
- _FieldDescriptor.TYPE_SFIXED32: _Encoder.AppendSFixed32NoTag,
- _FieldDescriptor.TYPE_SFIXED64: _Encoder.AppendSFixed64NoTag,
- _FieldDescriptor.TYPE_SINT32: _Encoder.AppendSInt32NoTag,
- _FieldDescriptor.TYPE_SINT64: _Encoder.AppendSInt64NoTag,
+# Maps from field types to sizer constructors.
+TYPE_TO_SIZER = {
+ _FieldDescriptor.TYPE_DOUBLE: encoder.DoubleSizer,
+ _FieldDescriptor.TYPE_FLOAT: encoder.FloatSizer,
+ _FieldDescriptor.TYPE_INT64: encoder.Int64Sizer,
+ _FieldDescriptor.TYPE_UINT64: encoder.UInt64Sizer,
+ _FieldDescriptor.TYPE_INT32: encoder.Int32Sizer,
+ _FieldDescriptor.TYPE_FIXED64: encoder.Fixed64Sizer,
+ _FieldDescriptor.TYPE_FIXED32: encoder.Fixed32Sizer,
+ _FieldDescriptor.TYPE_BOOL: encoder.BoolSizer,
+ _FieldDescriptor.TYPE_STRING: encoder.StringSizer,
+ _FieldDescriptor.TYPE_GROUP: encoder.GroupSizer,
+ _FieldDescriptor.TYPE_MESSAGE: encoder.MessageSizer,
+ _FieldDescriptor.TYPE_BYTES: encoder.BytesSizer,
+ _FieldDescriptor.TYPE_UINT32: encoder.UInt32Sizer,
+ _FieldDescriptor.TYPE_ENUM: encoder.EnumSizer,
+ _FieldDescriptor.TYPE_SFIXED32: encoder.SFixed32Sizer,
+ _FieldDescriptor.TYPE_SFIXED64: encoder.SFixed64Sizer,
+ _FieldDescriptor.TYPE_SINT32: encoder.SInt32Sizer,
+ _FieldDescriptor.TYPE_SINT64: encoder.SInt64Sizer,
+ }
+
+
+# Maps from field type to a decoder constructor.
+TYPE_TO_DECODER = {
+ _FieldDescriptor.TYPE_DOUBLE: decoder.DoubleDecoder,
+ _FieldDescriptor.TYPE_FLOAT: decoder.FloatDecoder,
+ _FieldDescriptor.TYPE_INT64: decoder.Int64Decoder,
+ _FieldDescriptor.TYPE_UINT64: decoder.UInt64Decoder,
+ _FieldDescriptor.TYPE_INT32: decoder.Int32Decoder,
+ _FieldDescriptor.TYPE_FIXED64: decoder.Fixed64Decoder,
+ _FieldDescriptor.TYPE_FIXED32: decoder.Fixed32Decoder,
+ _FieldDescriptor.TYPE_BOOL: decoder.BoolDecoder,
+ _FieldDescriptor.TYPE_STRING: decoder.StringDecoder,
+ _FieldDescriptor.TYPE_GROUP: decoder.GroupDecoder,
+ _FieldDescriptor.TYPE_MESSAGE: decoder.MessageDecoder,
+ _FieldDescriptor.TYPE_BYTES: decoder.BytesDecoder,
+ _FieldDescriptor.TYPE_UINT32: decoder.UInt32Decoder,
+ _FieldDescriptor.TYPE_ENUM: decoder.EnumDecoder,
+ _FieldDescriptor.TYPE_SFIXED32: decoder.SFixed32Decoder,
+ _FieldDescriptor.TYPE_SFIXED64: decoder.SFixed64Decoder,
+ _FieldDescriptor.TYPE_SINT32: decoder.SInt32Decoder,
+ _FieldDescriptor.TYPE_SINT64: decoder.SInt64Decoder,
}
# Maps from field type to expected wiretype.
@@ -259,29 +284,3 @@ FIELD_TYPE_TO_WIRE_TYPE = {
_FieldDescriptor.TYPE_SINT32: wire_format.WIRETYPE_VARINT,
_FieldDescriptor.TYPE_SINT64: wire_format.WIRETYPE_VARINT,
}
-
-
-# Maps from field type to an unbound Decoder method F,
-# such that F(decoder) will read a field of the requested type.
-#
-# Note that Message and Group are intentionally missing here.
-# They're handled by _RecursivelyMerge().
-_Decoder = decoder.Decoder
-TYPE_TO_DESERIALIZE_METHOD = {
- _FieldDescriptor.TYPE_DOUBLE: _Decoder.ReadDouble,
- _FieldDescriptor.TYPE_FLOAT: _Decoder.ReadFloat,
- _FieldDescriptor.TYPE_INT64: _Decoder.ReadInt64,
- _FieldDescriptor.TYPE_UINT64: _Decoder.ReadUInt64,
- _FieldDescriptor.TYPE_INT32: _Decoder.ReadInt32,
- _FieldDescriptor.TYPE_FIXED64: _Decoder.ReadFixed64,
- _FieldDescriptor.TYPE_FIXED32: _Decoder.ReadFixed32,
- _FieldDescriptor.TYPE_BOOL: _Decoder.ReadBool,
- _FieldDescriptor.TYPE_STRING: _Decoder.ReadString,
- _FieldDescriptor.TYPE_BYTES: _Decoder.ReadBytes,
- _FieldDescriptor.TYPE_UINT32: _Decoder.ReadUInt32,
- _FieldDescriptor.TYPE_ENUM: _Decoder.ReadEnum,
- _FieldDescriptor.TYPE_SFIXED32: _Decoder.ReadSFixed32,
- _FieldDescriptor.TYPE_SFIXED64: _Decoder.ReadSFixed64,
- _FieldDescriptor.TYPE_SINT32: _Decoder.ReadSInt32,
- _FieldDescriptor.TYPE_SINT64: _Decoder.ReadSInt64,
- }
diff --git a/python/google/protobuf/internal/wire_format.py b/python/google/protobuf/internal/wire_format.py
index da6464de..c941fe1a 100755
--- a/python/google/protobuf/internal/wire_format.py
+++ b/python/google/protobuf/internal/wire_format.py
@@ -33,16 +33,17 @@
__author__ = 'robinson@google.com (Will Robinson)'
import struct
+from google.protobuf import descriptor
from google.protobuf import message
TAG_TYPE_BITS = 3 # Number of bits used to hold type info in a proto tag.
-_TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1 # 0x7
+TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1 # 0x7
# These numbers identify the wire type of a protocol buffer value.
# We use the least-significant TAG_TYPE_BITS bits of the varint-encoded
# tag-and-type to store one of these WIRETYPE_* constants.
-# These values must match WireType enum in //net/proto2/public/wire_format.h.
+# These values must match WireType enum in google/protobuf/wire_format.h.
WIRETYPE_VARINT = 0
WIRETYPE_FIXED64 = 1
WIRETYPE_LENGTH_DELIMITED = 2
@@ -93,7 +94,7 @@ def UnpackTag(tag):
"""The inverse of PackTag(). Given an unsigned 32-bit number,
returns a (field_number, wire_type) tuple.
"""
- return (tag >> TAG_TYPE_BITS), (tag & _TAG_TYPE_MASK)
+ return (tag >> TAG_TYPE_BITS), (tag & TAG_TYPE_MASK)
def ZigZagEncode(value):
@@ -245,3 +246,23 @@ def _VarUInt64ByteSizeNoTag(uint64):
if uint64 > UINT64_MAX:
raise message.EncodeError('Value out of range: %d' % uint64)
return 10
+
+
+NON_PACKABLE_TYPES = (
+ descriptor.FieldDescriptor.TYPE_STRING,
+ descriptor.FieldDescriptor.TYPE_GROUP,
+ descriptor.FieldDescriptor.TYPE_MESSAGE,
+ descriptor.FieldDescriptor.TYPE_BYTES
+)
+
+
+def IsTypePackable(field_type):
+ """Return true iff packable = true is valid for fields of this type.
+
+ Args:
+ field_type: a FieldDescriptor::Type value.
+
+ Returns:
+ True iff fields of this type are packable.
+ """
+ return field_type not in NON_PACKABLE_TYPES
diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py
index 9a88bdc8..f8398474 100755
--- a/python/google/protobuf/message.py
+++ b/python/google/protobuf/message.py
@@ -99,7 +99,7 @@ class Message(object):
Args:
other_msg: Message to copy into the current one.
"""
- if self == other_msg:
+ if self is other_msg:
return
self.Clear()
self.MergeFrom(other_msg)
@@ -108,6 +108,15 @@ class Message(object):
"""Clears all data that was set in the message."""
raise NotImplementedError
+ def SetInParent(self):
+ """Mark this as present in the parent.
+
+ This normally happens automatically when you assign a field of a
+ sub-message, but sometimes you want to make the sub-message
+ present while keeping it empty. If you find yourself using this,
+ you may want to reconsider your design."""
+ raise NotImplementedError
+
def IsInitialized(self):
"""Checks if the message is initialized.
diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py
index d65d8b67..5b238031 100755
--- a/python/google/protobuf/reflection.py
+++ b/python/google/protobuf/reflection.py
@@ -50,9 +50,13 @@ this file*.
__author__ = 'robinson@google.com (Will Robinson)'
-import heapq
-import threading
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+import struct
import weakref
+
# We use "as" to avoid name collisions with variables.
from google.protobuf.internal import containers
from google.protobuf.internal import decoder
@@ -139,14 +143,26 @@ class GeneratedProtocolMessageType(type):
type.
"""
descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
+
+ cls._decoders_by_tag = {}
+ cls._extensions_by_name = {}
+ cls._extensions_by_number = {}
+ if (descriptor.has_options and
+ descriptor.GetOptions().message_set_wire_format):
+ cls._decoders_by_tag[decoder.MESSAGE_SET_ITEM_TAG] = (
+ decoder.MessageSetItemDecoder(cls._extensions_by_number))
+
# We act as a "friend" class of the descriptor, setting
# its _concrete_class attribute the first time we use a
# given descriptor to initialize a concrete protocol message
- # class.
+ # class. We also attach stuff to each FieldDescriptor for quick
+ # lookup later on.
concrete_class_attr_name = '_concrete_class'
if not hasattr(descriptor, concrete_class_attr_name):
setattr(descriptor, concrete_class_attr_name, cls)
- cls._known_extensions = []
+ for field in descriptor.fields:
+ _AttachFieldHelpers(cls, field)
+
_AddEnumValues(descriptor, cls)
_AddInitMethod(descriptor, cls)
_AddPropertiesForFields(descriptor, cls)
@@ -184,30 +200,33 @@ def _PropertyName(proto_field_name):
# return proto_field_name + "_"
# return proto_field_name
# """
+ # Kenton says: The above is a BAD IDEA. People rely on being able to use
+ # getattr() and setattr() to reflectively manipulate field values. If we
+ # rename the properties, then every such user has to also make sure to apply
+ # the same transformation. Note that currently if you name a field "yield",
+ # you can still access it just fine using getattr/setattr -- it's not even
+ # that cumbersome to do so.
+ # TODO(kenton): Remove this method entirely if/when everyone agrees with my
+ # position.
return proto_field_name
-def _ValueFieldName(proto_field_name):
- """Returns the name of the (internal) instance attribute which objects
- should use to store the current value for a given protocol message field.
-
- Args:
- proto_field_name: The protocol message field name, exactly
- as it appears (or would appear) in a .proto file.
- """
- return '_value_' + proto_field_name
+def _VerifyExtensionHandle(message, extension_handle):
+ """Verify that the given extension handle is valid."""
+ if not isinstance(extension_handle, _FieldDescriptor):
+ raise KeyError('HasExtension() expects an extension handle, got: %s' %
+ extension_handle)
-def _HasFieldName(proto_field_name):
- """Returns the name of the (internal) instance attribute which
- objects should use to store a boolean telling whether this field
- is explicitly set or not.
+ if not extension_handle.is_extension:
+ raise KeyError('"%s" is not an extension.' % extension_handle.full_name)
- Args:
- proto_field_name: The protocol message field name, exactly
- as it appears (or would appear) in a .proto file.
- """
- return '_has_' + proto_field_name
+ if extension_handle.containing_type is not message.DESCRIPTOR:
+ raise KeyError('Extension "%s" extends message type "%s", but this '
+ 'message is of type "%s".' %
+ (extension_handle.full_name,
+ extension_handle.containing_type.full_name,
+ message.DESCRIPTOR.full_name))
def _AddSlots(message_descriptor, dictionary):
@@ -218,16 +237,57 @@ def _AddSlots(message_descriptor, dictionary):
message_descriptor: A Descriptor instance describing this message type.
dictionary: Class dictionary to which we'll add a '__slots__' entry.
"""
- field_names = [_ValueFieldName(f.name) for f in message_descriptor.fields]
- field_names.extend(_HasFieldName(f.name) for f in message_descriptor.fields
- if f.label != _FieldDescriptor.LABEL_REPEATED)
- field_names.extend(('Extensions',
- '_cached_byte_size',
- '_cached_byte_size_dirty',
- '_called_transition_to_nonempty',
- '_listener',
- '_lock', '__weakref__'))
- dictionary['__slots__'] = field_names
+ dictionary['__slots__'] = ['_cached_byte_size',
+ '_cached_byte_size_dirty',
+ '_fields',
+ '_is_present_in_parent',
+ '_listener',
+ '_listener_for_children',
+ '__weakref__']
+
+
+def _IsMessageSetExtension(field):
+ return (field.is_extension and
+ field.containing_type.has_options and
+ field.containing_type.GetOptions().message_set_wire_format and
+ field.type == _FieldDescriptor.TYPE_MESSAGE and
+ field.message_type == field.extension_scope and
+ field.label == _FieldDescriptor.LABEL_OPTIONAL)
+
+
+def _AttachFieldHelpers(cls, field_descriptor):
+ is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED)
+ is_packed = (field_descriptor.has_options and
+ field_descriptor.GetOptions().packed)
+
+ if _IsMessageSetExtension(field_descriptor):
+ field_encoder = encoder.MessageSetItemEncoder(field_descriptor.number)
+ sizer = encoder.MessageSetItemSizer(field_descriptor.number)
+ else:
+ field_encoder = type_checkers.TYPE_TO_ENCODER[field_descriptor.type](
+ field_descriptor.number, is_repeated, is_packed)
+ sizer = type_checkers.TYPE_TO_SIZER[field_descriptor.type](
+ field_descriptor.number, is_repeated, is_packed)
+
+ field_descriptor._encoder = field_encoder
+ field_descriptor._sizer = sizer
+ field_descriptor._default_constructor = _DefaultValueConstructorForField(
+ field_descriptor)
+
+ def AddDecoder(wiretype, is_packed):
+ tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype)
+ cls._decoders_by_tag[tag_bytes] = (
+ type_checkers.TYPE_TO_DECODER[field_descriptor.type](
+ field_descriptor.number, is_repeated, is_packed,
+ field_descriptor, field_descriptor._default_constructor))
+
+ AddDecoder(type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type],
+ False)
+
+ if is_repeated and wire_format.IsTypePackable(field_descriptor.type):
+ # To support wire compatibility of adding packed = true, add a decoder for
+ # packed values regardless of the field's options.
+ AddDecoder(wire_format.WIRETYPE_LENGTH_DELIMITED, True)
def _AddClassAttributesForNestedExtensions(descriptor, dictionary):
@@ -249,44 +309,51 @@ def _AddEnumValues(descriptor, cls):
setattr(cls, enum_value.name, enum_value.number)
-def _DefaultValueForField(message, field):
- """Returns a default value for a field.
+def _DefaultValueConstructorForField(field):
+ """Returns a function which returns a default value for a field.
Args:
+ field: FieldDescriptor object for this field.
+
+ The returned function has one argument:
message: Message instance containing this field, or a weakref proxy
of same.
- field: FieldDescriptor object for this field.
- Returns: A default value for this field. May refer back to |message|
- via a weak reference.
+ That function in turn returns a default value for this field. The default
+ value may refer back to |message| via a weak reference.
"""
- # TODO(robinson): Only the repeated fields need a reference to 'message' (so
- # that they can set the 'has' bit on the containing Message when someone
- # append()s a value). We could special-case this, and avoid an extra
- # function call on __init__() and Clear() for non-repeated fields.
-
- # TODO(robinson): Find a better place for the default value assertion in this
- # function. No need to repeat them every time the client calls Clear('foo').
- # (We should probably just assert these things once and as early as possible,
- # by tightening checking in the descriptor classes.)
+
if field.label == _FieldDescriptor.LABEL_REPEATED:
if field.default_value != []:
raise ValueError('Repeated field default value not empty list: %s' % (
field.default_value))
- listener = _Listener(message, None)
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
# We can't look at _concrete_class yet since it might not have
# been set. (Depends on order in which we initialize the classes).
- return containers.RepeatedCompositeFieldContainer(
- listener, field.message_type)
+ message_type = field.message_type
+ def MakeRepeatedMessageDefault(message):
+ return containers.RepeatedCompositeFieldContainer(
+ message._listener_for_children, field.message_type)
+ return MakeRepeatedMessageDefault
else:
- return containers.RepeatedScalarFieldContainer(
- listener, type_checkers.GetTypeChecker(field.cpp_type, field.type))
+ type_checker = type_checkers.GetTypeChecker(field.cpp_type, field.type)
+ def MakeRepeatedScalarDefault(message):
+ return containers.RepeatedScalarFieldContainer(
+ message._listener_for_children, type_checker)
+ return MakeRepeatedScalarDefault
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
- assert field.default_value is None
+ # _concrete_class may not yet be initialized.
+ message_type = field.message_type
+ def MakeSubMessageDefault(message):
+ result = message_type._concrete_class()
+ result._SetListener(message._listener_for_children)
+ return result
+ return MakeSubMessageDefault
- return field.default_value
+ def MakeScalarDefault(message):
+ return field.default_value
+ return MakeScalarDefault
def _AddInitMethod(message_descriptor, cls):
@@ -295,21 +362,29 @@ def _AddInitMethod(message_descriptor, cls):
def init(self, **kwargs):
self._cached_byte_size = 0
self._cached_byte_size_dirty = False
+ self._fields = {}
+ self._is_present_in_parent = False
self._listener = message_listener_mod.NullMessageListener()
- self._called_transition_to_nonempty = False
- # TODO(robinson): We should only create a lock if we really need one
- # in this class.
- self._lock = threading.Lock()
- for field in fields:
- default_value = _DefaultValueForField(self, field)
- python_field_name = _ValueFieldName(field.name)
- setattr(self, python_field_name, default_value)
- if field.label != _FieldDescriptor.LABEL_REPEATED:
- setattr(self, _HasFieldName(field.name), False)
- self.Extensions = _ExtensionDict(self, cls._known_extensions)
+ self._listener_for_children = _Listener(self)
for field_name, field_value in kwargs.iteritems():
field = _GetFieldByName(message_descriptor, field_name)
- _MergeFieldOrExtension(self, field, field_value)
+ if field is None:
+ raise TypeError("%s() got an unexpected keyword argument '%s'" %
+ (message_descriptor.name, field_name))
+ if field.label == _FieldDescriptor.LABEL_REPEATED:
+ copy = field._default_constructor(self)
+ if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: # Composite
+ for val in field_value:
+ copy.add().MergeFrom(val)
+ else: # Scalar
+ copy.extend(field_value)
+ self._fields[field] = copy
+ elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+ copy = field._default_constructor(self)
+ copy.MergeFrom(field_value)
+ self._fields[field] = copy
+ else:
+ self._fields[field] = field_value
init.__module__ = None
init.__doc__ = None
@@ -336,6 +411,11 @@ def _AddPropertiesForFields(descriptor, cls):
for field in descriptor.fields:
_AddPropertiesForField(field, cls)
+ if descriptor.is_extendable:
+ # _ExtensionDict is just an adaptor with no state so we allocate a new one
+ # every time it is accessed.
+ cls.Extensions = property(lambda self: _ExtensionDict(self))
+
def _AddPropertiesForField(field, cls):
"""Adds a public property for a protocol message field.
@@ -377,11 +457,22 @@ def _AddPropertiesForRepeatedField(field, cls):
cls: The class we're constructing.
"""
proto_field_name = field.name
- python_field_name = _ValueFieldName(proto_field_name)
property_name = _PropertyName(proto_field_name)
def getter(self):
- return getattr(self, python_field_name)
+ field_value = self._fields.get(field)
+ if field_value is None:
+ # Construct a new object to represent this field.
+ field_value = field._default_constructor(self)
+
+ # Atomically check if another thread has preempted us and, if not, swap
+ # in the new object we just created. If someone has preempted us, we
+ # take that object and discard ours.
+ # WARNING: We are relying on setdefault() being atomic. This is true
+ # in CPython but we haven't investigated others. This warning appears
+ # in several other locations in this file.
+ field_value = self._fields.setdefault(field, field_value)
+ return field_value
getter.__module__ = None
getter.__doc__ = 'Getter for %s.' % proto_field_name
@@ -407,21 +498,21 @@ def _AddPropertiesForNonRepeatedScalarField(field, cls):
cls: The class we're constructing.
"""
proto_field_name = field.name
- python_field_name = _ValueFieldName(proto_field_name)
- has_field_name = _HasFieldName(proto_field_name)
property_name = _PropertyName(proto_field_name)
type_checker = type_checkers.GetTypeChecker(field.cpp_type, field.type)
+ default_value = field.default_value
def getter(self):
- return getattr(self, python_field_name)
+ return self._fields.get(field, default_value)
getter.__module__ = None
getter.__doc__ = 'Getter for %s.' % proto_field_name
def setter(self, new_value):
type_checker.CheckValue(new_value)
- setattr(self, has_field_name, True)
- self._MarkByteSizeDirty()
- self._MaybeCallTransitionToNonemptyCallback()
- setattr(self, python_field_name, new_value)
+ self._fields[field] = new_value
+ # Check _cached_byte_size_dirty inline to improve performance, since scalar
+ # setters are called frequently.
+ if not self._cached_byte_size_dirty:
+ self._Modified()
setter.__module__ = None
setter.__doc__ = 'Setter for %s.' % proto_field_name
@@ -444,25 +535,23 @@ def _AddPropertiesForNonRepeatedCompositeField(field, cls):
# TODO(robinson): Remove duplication with similar method
# for non-repeated scalars.
proto_field_name = field.name
- python_field_name = _ValueFieldName(proto_field_name)
- has_field_name = _HasFieldName(proto_field_name)
property_name = _PropertyName(proto_field_name)
message_type = field.message_type
def getter(self):
- # TODO(robinson): Appropriately scary note about double-checked locking.
- field_value = getattr(self, python_field_name)
+ field_value = self._fields.get(field)
if field_value is None:
- self._lock.acquire()
- try:
- field_value = getattr(self, python_field_name)
- if field_value is None:
- field_class = message_type._concrete_class
- field_value = field_class()
- field_value._SetListener(_Listener(self, has_field_name))
- setattr(self, python_field_name, field_value)
- finally:
- self._lock.release()
+ # Construct a new object to represent this field.
+ field_value = message_type._concrete_class()
+ field_value._SetListener(self._listener_for_children)
+
+ # Atomically check if another thread has preempted us and, if not, swap
+ # in the new object we just created. If someone has preempted us, we
+ # take that object and discard ours.
+ # WARNING: We are relying on setdefault() being atomic. This is true
+ # in CPython but we haven't investigated others. This warning appears
+ # in several other locations in this file.
+ field_value = self._fields.setdefault(field, field_value)
return field_value
getter.__module__ = None
getter.__doc__ = 'Getter for %s.' % proto_field_name
@@ -490,7 +579,27 @@ def _AddStaticMethods(cls):
# TODO(robinson): This probably needs to be thread-safe(?)
def RegisterExtension(extension_handle):
extension_handle.containing_type = cls.DESCRIPTOR
- cls._known_extensions.append(extension_handle)
+ _AttachFieldHelpers(cls, extension_handle)
+
+ # Try to insert our extension, failing if an extension with the same number
+ # already exists.
+ actual_handle = cls._extensions_by_number.setdefault(
+ extension_handle.number, extension_handle)
+ if actual_handle is not extension_handle:
+ raise AssertionError(
+ 'Extensions "%s" and "%s" both try to extend message type "%s" with '
+ 'field number %d.' %
+ (extension_handle.full_name, actual_handle.full_name,
+ cls.DESCRIPTOR.full_name, extension_handle.number))
+
+ cls._extensions_by_name[extension_handle.full_name] = extension_handle
+
+ handle = extension_handle # avoid line wrapping
+ if _IsMessageSetExtension(handle):
+ # MessageSet extension. Also register under type name.
+ cls._extensions_by_name[
+ extension_handle.message_type.full_name] = extension_handle
+
cls.RegisterExtension = staticmethod(RegisterExtension)
def FromString(s):
@@ -500,115 +609,107 @@ def _AddStaticMethods(cls):
cls.FromString = staticmethod(FromString)
+def _IsPresent(item):
+ """Given a (FieldDescriptor, value) tuple from _fields, return true if the
+ value should be included in the list returned by ListFields()."""
+
+ if item[0].label == _FieldDescriptor.LABEL_REPEATED:
+ return bool(item[1])
+ elif item[0].cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+ return item[1]._is_present_in_parent
+ else:
+ return True
+
+
def _AddListFieldsMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
- # Ensure that we always list in ascending field-number order.
- # For non-extension fields, we can do the sort once, here, at import-time.
- # For extensions, we sort on each ListFields() call, though
- # we could do better if we have to.
- fields = sorted(message_descriptor.fields, key=lambda f: f.number)
- has_field_names = (_HasFieldName(f.name) for f in fields)
- value_field_names = (_ValueFieldName(f.name) for f in fields)
- triplets = zip(has_field_names, value_field_names, fields)
-
def ListFields(self):
- # We need to list all extension and non-extension fields
- # together, in sorted order by field number.
-
- # Step 0: Get an iterator over all "set" non-extension fields,
- # sorted by field number.
- # This iterator yields (field_number, field_descriptor, value) tuples.
- def SortedSetFieldsIter():
- # Note that triplets is already sorted by field number.
- for has_field_name, value_field_name, field_descriptor in triplets:
- if field_descriptor.label == _FieldDescriptor.LABEL_REPEATED:
- value = getattr(self, _ValueFieldName(field_descriptor.name))
- if len(value) > 0:
- yield (field_descriptor.number, field_descriptor, value)
- elif getattr(self, _HasFieldName(field_descriptor.name)):
- value = getattr(self, _ValueFieldName(field_descriptor.name))
- yield (field_descriptor.number, field_descriptor, value)
- sorted_fields = SortedSetFieldsIter()
-
- # Step 1: Get an iterator over all "set" extension fields,
- # sorted by field number.
- # This iterator ALSO yields (field_number, field_descriptor, value) tuples.
- # TODO(robinson): It's not necessary to repeat this with each
- # serialization call. We can do better.
- sorted_extension_fields = sorted(
- [(f.number, f, v) for f, v in self.Extensions._ListSetExtensions()])
-
- # Step 2: Create a composite iterator that merges the extension-
- # and non-extension fields, and that still yields fields in
- # sorted order.
- all_set_fields = _ImergeSorted(sorted_fields, sorted_extension_fields)
-
- # Step 3: Strip off the field numbers and return.
- return [field[1:] for field in all_set_fields]
+ all_fields = [item for item in self._fields.iteritems() if _IsPresent(item)]
+ all_fields.sort(key = lambda item: item[0].number)
+ return all_fields
cls.ListFields = ListFields
-def _AddHasFieldMethod(cls):
+
+def _AddHasFieldMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
+
+ singular_fields = {}
+ for field in message_descriptor.fields:
+ if field.label != _FieldDescriptor.LABEL_REPEATED:
+ singular_fields[field.name] = field
+
def HasField(self, field_name):
try:
- return getattr(self, _HasFieldName(field_name))
- except AttributeError:
- raise ValueError('Protocol message has no "%s" field.' % field_name)
+ field = singular_fields[field_name]
+ except KeyError:
+ raise ValueError(
+ 'Protocol message has no singular "%s" field.' % field_name)
+
+ if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+ value = self._fields.get(field)
+ return value is not None and value._is_present_in_parent
+ else:
+ return field in self._fields
cls.HasField = HasField
-def _AddClearFieldMethod(cls):
+def _AddClearFieldMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
def ClearField(self, field_name):
- field = _GetFieldByName(self.DESCRIPTOR, field_name)
- proto_field_name = field.name
- python_field_name = _ValueFieldName(proto_field_name)
- has_field_name = _HasFieldName(proto_field_name)
- default_value = _DefaultValueForField(self, field)
- if field.label == _FieldDescriptor.LABEL_REPEATED:
- self._MarkByteSizeDirty()
- else:
- if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
- old_field_value = getattr(self, python_field_name)
- if old_field_value is not None:
- # Snip the old object out of the object tree.
- old_field_value._SetListener(None)
- if getattr(self, has_field_name):
- setattr(self, has_field_name, False)
- # Set dirty bit on ourself and parents only if
- # we're actually changing state.
- self._MarkByteSizeDirty()
- setattr(self, python_field_name, default_value)
+ try:
+ field = message_descriptor.fields_by_name[field_name]
+ except KeyError:
+ raise ValueError('Protocol message has no "%s" field.' % field_name)
+
+ if field in self._fields:
+ # Note: If the field is a sub-message, its listener will still point
+ # at us. That's fine, because the worst than can happen is that it
+ # will call _Modified() and invalidate our byte size. Big deal.
+ del self._fields[field]
+
+ # Always call _Modified() -- even if nothing was changed, this is
+ # a mutating method, and thus calling it should cause the field to become
+ # present in the parent message.
+ self._Modified()
+
cls.ClearField = ClearField
def _AddClearExtensionMethod(cls):
"""Helper for _AddMessageMethods()."""
def ClearExtension(self, extension_handle):
- self.Extensions._ClearExtension(extension_handle)
+ _VerifyExtensionHandle(self, extension_handle)
+
+ # Similar to ClearField(), above.
+ if extension_handle in self._fields:
+ del self._fields[extension_handle]
+ self._Modified()
cls.ClearExtension = ClearExtension
-def _AddClearMethod(cls):
+def _AddClearMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
def Clear(self):
# Clear fields.
- fields = self.DESCRIPTOR.fields
- for field in fields:
- self.ClearField(field.name)
- # Clear extensions.
- extensions = self.Extensions._ListSetExtensions()
- for extension in extensions:
- self.ClearExtension(extension[0])
+ self._fields = {}
+ self._Modified()
cls.Clear = Clear
def _AddHasExtensionMethod(cls):
"""Helper for _AddMessageMethods()."""
def HasExtension(self, extension_handle):
- return self.Extensions._HasExtension(extension_handle)
+ _VerifyExtensionHandle(self, extension_handle)
+ if extension_handle.label == _FieldDescriptor.LABEL_REPEATED:
+ raise KeyError('"%s" is repeated.' % extension_handle.full_name)
+
+ if extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+ value = self._fields.get(extension_handle)
+ return value is not None and value._is_present_in_parent
+ else:
+ return extension_handle in self._fields
cls.HasExtension = HasExtension
@@ -622,26 +723,8 @@ def _AddEqualsMethod(message_descriptor, cls):
if self is other:
return True
- # Compare all fields contained directly in this message.
- for field_descriptor in message_descriptor.fields:
- label = field_descriptor.label
- property_name = _PropertyName(field_descriptor.name)
- # Non-repeated field equality requires matching "has" bits as well
- # as having an equal value.
- if label != _FieldDescriptor.LABEL_REPEATED:
- self_has = self.HasField(property_name)
- other_has = other.HasField(property_name)
- if self_has != other_has:
- return False
- if not self_has:
- # If the "has" bit for this field is False, we must stop here.
- # Otherwise we will recurse forever on recursively-defined protos.
- continue
- if getattr(self, property_name) != getattr(other, property_name):
- return False
+ return self.ListFields() == other.ListFields()
- # Compare the extensions present in both messages.
- return self.Extensions == other.Extensions
cls.__eq__ = __eq__
@@ -685,618 +768,202 @@ def _BytesForNonRepeatedElement(value, field_number, field_type):
def _AddByteSizeMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
- def BytesForField(message, field, value):
- """Returns the number of bytes required to serialize a single field
- in message. The field may be repeated or not, composite or not.
-
- Args:
- message: The Message instance containing a field of the given type.
- field: A FieldDescriptor describing the field of interest.
- value: The value whose byte size we're interested in.
-
- Returns: The number of bytes required to serialize the current value
- of "field" in "message", including space for tags and any other
- necessary information.
- """
-
- if _MessageSetField(field):
- return wire_format.MessageSetItemByteSize(field.number, value)
-
- field_number, field_type = field.number, field.type
-
- # Repeated fields.
- if field.label == _FieldDescriptor.LABEL_REPEATED:
- elements = value
- else:
- elements = [value]
-
- if field.GetOptions().packed:
- content_size = _ContentBytesForPackedField(message, field, elements)
- if content_size:
- tag_size = wire_format.TagByteSize(field_number)
- length_size = wire_format.Int32ByteSizeNoTag(content_size)
- return tag_size + length_size + content_size
- else:
- return 0
- else:
- return sum(_BytesForNonRepeatedElement(element, field_number, field_type)
- for element in elements)
-
- def _ContentBytesForPackedField(self, field, value):
- """Returns the number of bytes required to serialize the actual
- content of a packed field (not including the tag or the encoding
- of the length.
-
- Args:
- self: The Message instance containing a field of the given type.
- field: A FieldDescriptor describing the field of interest.
- value: The value whose byte size we're interested in.
-
- Returns: The number of bytes required to serialize the current value
- of the packed "field" in "message", excluding space for tags and the
- length encoding.
- """
- size = sum(_BytesForNonRepeatedElement(element, field.number, field.type)
- for element in value)
- # In the packed case, there are no per element tags.
- return size - wire_format.TagByteSize(field.number) * len(value)
-
- fields = message_descriptor.fields
- has_field_names = (_HasFieldName(f.name) for f in fields)
- zipped = zip(has_field_names, fields)
-
def ByteSize(self):
if not self._cached_byte_size_dirty:
return self._cached_byte_size
size = 0
- # Hardcoded fields first.
- for has_field_name, field in zipped:
- if (field.label == _FieldDescriptor.LABEL_REPEATED
- or getattr(self, has_field_name)):
- value = getattr(self, _ValueFieldName(field.name))
- size += BytesForField(self, field, value)
- # Extensions next.
- for field, value in self.Extensions._ListSetExtensions():
- size += BytesForField(self, field, value)
+ for field_descriptor, field_value in self.ListFields():
+ size += field_descriptor._sizer(field_value)
self._cached_byte_size = size
self._cached_byte_size_dirty = False
+ self._listener_for_children.dirty = False
return size
- cls._ContentBytesForPackedField = _ContentBytesForPackedField
cls.ByteSize = ByteSize
-def _MessageSetField(field_descriptor):
- """Checks if a field should be serialized using the message set wire format.
-
- Args:
- field_descriptor: Descriptor of the field.
-
- Returns:
- True if the field should be serialized using the message set wire format,
- false otherwise.
- """
- return (field_descriptor.is_extension and
- field_descriptor.label != _FieldDescriptor.LABEL_REPEATED and
- field_descriptor.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
- field_descriptor.containing_type.GetOptions().message_set_wire_format)
-
-
-def _SerializeValueToEncoder(value, field_number, field_descriptor, encoder):
- """Appends the serialization of a single value to encoder.
-
- Args:
- value: Value to serialize.
- field_number: Field number of this value.
- field_descriptor: Descriptor of the field to serialize.
- encoder: encoder.Encoder object to which we should serialize this value.
- """
- if _MessageSetField(field_descriptor):
- encoder.AppendMessageSetItem(field_number, value)
- return
-
- try:
- method = type_checkers.TYPE_TO_SERIALIZE_METHOD[field_descriptor.type]
- method(encoder, field_number, value)
- except KeyError:
- raise message_mod.EncodeError('Unrecognized field type: %d' %
- field_descriptor.type)
-
-
-def _ImergeSorted(*streams):
- """Merges N sorted iterators into a single sorted iterator.
- Each element in streams must be an iterable that yields
- its elements in sorted order, and the elements contained
- in each stream must all be comparable.
-
- There may be repeated elements in the component streams or
- across the streams; the repeated elements will all be repeated
- in the merged iterator as well.
-
- I believe that the heapq module at HEAD in the Python
- sources has a method like this, but for now we roll our own.
- """
- iters = [iter(stream) for stream in streams]
- heap = []
- for index, it in enumerate(iters):
- try:
- heap.append((it.next(), index))
- except StopIteration:
- pass
- heapq.heapify(heap)
-
- while heap:
- smallest_value, idx = heap[0]
- yield smallest_value
- try:
- next_element = iters[idx].next()
- heapq.heapreplace(heap, (next_element, idx))
- except StopIteration:
- heapq.heappop(heap)
-
-
def _AddSerializeToStringMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
def SerializeToString(self):
# Check if the message has all of its required fields set.
errors = []
- if not _InternalIsInitialized(self, errors):
- raise message_mod.EncodeError('\n'.join(errors))
+ if not self.IsInitialized():
+ raise message_mod.EncodeError(
+ 'Message is missing required fields: ' +
+ ','.join(self.FindInitializationErrors()))
return self.SerializePartialToString()
cls.SerializeToString = SerializeToString
def _AddSerializePartialToStringMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
- Encoder = encoder.Encoder
def SerializePartialToString(self):
- encoder = Encoder()
- # We need to serialize all extension and non-extension fields
- # together, in sorted order by field number.
- for field_descriptor, field_value in self.ListFields():
- if field_descriptor.label == _FieldDescriptor.LABEL_REPEATED:
- repeated_value = field_value
- else:
- repeated_value = [field_value]
- if field_descriptor.GetOptions().packed:
- # First, write the field number and WIRETYPE_LENGTH_DELIMITED.
- field_number = field_descriptor.number
- encoder.AppendTag(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
- # Next, write the number of bytes.
- content_bytes = self._ContentBytesForPackedField(
- field_descriptor, field_value)
- encoder.AppendInt32NoTag(content_bytes)
- # Finally, write the actual values.
- try:
- method = type_checkers.TYPE_TO_NOTAG_SERIALIZE_METHOD[
- field_descriptor.type]
- for value in repeated_value:
- method(encoder, value)
- except KeyError:
- raise message_mod.EncodeError('Unrecognized field type: %d' %
- field_descriptor.type)
- else:
- for element in repeated_value:
- _SerializeValueToEncoder(element, field_descriptor.number,
- field_descriptor, encoder)
- return encoder.ToString()
-
+ out = StringIO()
+ self._InternalSerialize(out.write)
+ return out.getvalue()
cls.SerializePartialToString = SerializePartialToString
+ def InternalSerialize(self, write_bytes):
+ for field_descriptor, field_value in self.ListFields():
+ field_descriptor._encoder(write_bytes, field_value)
+ cls._InternalSerialize = InternalSerialize
-def _WireTypeForFieldType(field_type):
- """Given a field type, returns the expected wire type."""
- try:
- return type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_type]
- except KeyError:
- raise message_mod.DecodeError('Unknown field type: %d' % field_type)
-
-
-def _WireTypeForField(field_descriptor):
- """Given a field descriptor, returns the expected wire type."""
- if field_descriptor.GetOptions().packed:
- return wire_format.WIRETYPE_LENGTH_DELIMITED
- else:
- return _WireTypeForFieldType(field_descriptor.type)
-
-
-def _RecursivelyMerge(field_number, field_type, decoder, message):
- """Decodes a message from decoder into message.
- message is either a group or a nested message within some containing
- protocol message. If it's a group, we use the group protocol to
- deserialize, and if it's a nested message, we use the nested-message
- protocol.
-
- Args:
- field_number: The field number of message in its enclosing protocol buffer.
- field_type: The field type of message. Must be either TYPE_MESSAGE
- or TYPE_GROUP.
- decoder: Decoder to read from.
- message: Message to deserialize into.
- """
- if field_type == _FieldDescriptor.TYPE_MESSAGE:
- decoder.ReadMessageInto(message)
- elif field_type == _FieldDescriptor.TYPE_GROUP:
- decoder.ReadGroupInto(field_number, message)
- else:
- raise message_mod.DecodeError('Unexpected field type: %d' % field_type)
-
-
-def _DeserializeScalarFromDecoder(field_type, decoder):
- """Deserializes a scalar of the requested type from decoder. field_type must
- be a scalar (non-group, non-message) FieldDescriptor.FIELD_* constant.
- """
- try:
- method = type_checkers.TYPE_TO_DESERIALIZE_METHOD[field_type]
- return method(decoder)
- except KeyError:
- raise message_mod.DecodeError('Unrecognized field type: %d' % field_type)
-
-
-def _SkipField(field_number, wire_type, decoder):
- """Skips a field with the specified wire type.
-
- Args:
- field_number: Tag number of the field to skip.
- wire_type: Wire type of the field to skip.
- decoder: Decoder used to deserialize the messsage. It must be positioned
- just after reading the the tag and wire type of the field.
- """
- if wire_type == wire_format.WIRETYPE_VARINT:
- decoder.ReadUInt64()
- elif wire_type == wire_format.WIRETYPE_FIXED64:
- decoder.ReadFixed64()
- elif wire_type == wire_format.WIRETYPE_LENGTH_DELIMITED:
- decoder.SkipBytes(decoder.ReadInt32())
- elif wire_type == wire_format.WIRETYPE_START_GROUP:
- _SkipGroup(field_number, decoder)
- elif wire_type == wire_format.WIRETYPE_END_GROUP:
- pass
- elif wire_type == wire_format.WIRETYPE_FIXED32:
- decoder.ReadFixed32()
- else:
- raise message_mod.DecodeError('Unexpected wire type: %d' % wire_type)
-
-
-def _SkipGroup(group_number, decoder):
- """Skips a nested group from the decoder.
-
- Args:
- group_number: Tag number of the group to skip.
- decoder: Decoder used to deserialize the message. It must be positioned
- exactly at the beginning of the message that should be skipped.
- """
- while True:
- field_number, wire_type = decoder.ReadFieldNumberAndWireType()
- if (wire_type == wire_format.WIRETYPE_END_GROUP and
- field_number == group_number):
- return
- _SkipField(field_number, wire_type, decoder)
-
-
-def _DeserializeMessageSetItem(message, decoder):
- """Deserializes a message using the message set wire format.
-
- Args:
- message: Message to be parsed to.
- decoder: The decoder to be used to deserialize encoded data. Note that the
- decoder should be positioned just after reading the START_GROUP tag that
- began the messageset item.
- """
- field_number, wire_type = decoder.ReadFieldNumberAndWireType()
- if wire_type != wire_format.WIRETYPE_VARINT or field_number != 2:
- raise message_mod.DecodeError(
- 'Incorrect message set wire format. '
- 'wire_type: %d, field_number: %d' % (wire_type, field_number))
-
- type_id = decoder.ReadInt32()
- field_number, wire_type = decoder.ReadFieldNumberAndWireType()
- if wire_type != wire_format.WIRETYPE_LENGTH_DELIMITED or field_number != 3:
- raise message_mod.DecodeError(
- 'Incorrect message set wire format. '
- 'wire_type: %d, field_number: %d' % (wire_type, field_number))
-
- extension_dict = message.Extensions
- extensions_by_number = extension_dict._AllExtensionsByNumber()
- if type_id not in extensions_by_number:
- _SkipField(field_number, wire_type, decoder)
- return
-
- field_descriptor = extensions_by_number[type_id]
- value = extension_dict[field_descriptor]
- decoder.ReadMessageInto(value)
- # Read the END_GROUP tag.
- field_number, wire_type = decoder.ReadFieldNumberAndWireType()
- if wire_type != wire_format.WIRETYPE_END_GROUP or field_number != 1:
- raise message_mod.DecodeError(
- 'Incorrect message set wire format. '
- 'wire_type: %d, field_number: %d' % (wire_type, field_number))
-
-
-def _DeserializeOneEntity(message_descriptor, message, decoder):
- """Deserializes the next wire entity from decoder into message.
-
- The next wire entity is either a scalar or a nested message, an
- element in a repeated field (the wire encoding in this case is the
- same), or a packed repeated field (in this case, the entire repeated
- field is read by a single call to _DeserializeOneEntity).
-
- Args:
- message_descriptor: A Descriptor instance describing all fields
- in message.
- message: The Message instance into which we're decoding our fields.
- decoder: The Decoder we're using to deserialize encoded data.
-
- Returns: The number of bytes read from decoder during this method.
- """
- initial_position = decoder.Position()
- field_number, wire_type = decoder.ReadFieldNumberAndWireType()
- extension_dict = message.Extensions
- extensions_by_number = extension_dict._AllExtensionsByNumber()
- if field_number in message_descriptor.fields_by_number:
- # Non-extension field.
- field_descriptor = message_descriptor.fields_by_number[field_number]
- value = getattr(message, _PropertyName(field_descriptor.name))
- def nonextension_setter_fn(scalar):
- setattr(message, _PropertyName(field_descriptor.name), scalar)
- scalar_setter_fn = nonextension_setter_fn
- elif field_number in extensions_by_number:
- # Extension field.
- field_descriptor = extensions_by_number[field_number]
- value = extension_dict[field_descriptor]
- def extension_setter_fn(scalar):
- extension_dict[field_descriptor] = scalar
- scalar_setter_fn = extension_setter_fn
- elif wire_type == wire_format.WIRETYPE_END_GROUP:
- # We assume we're being parsed as the group that's ended.
- return 0
- elif (wire_type == wire_format.WIRETYPE_START_GROUP and
- field_number == 1 and
- message_descriptor.GetOptions().message_set_wire_format):
- # A Message Set item.
- _DeserializeMessageSetItem(message, decoder)
- return decoder.Position() - initial_position
- else:
- _SkipField(field_number, wire_type, decoder)
- return decoder.Position() - initial_position
-
- # If we reach this point, we've identified the field as either
- # hardcoded or extension, and set |field_descriptor|, |scalar_setter_fn|,
- # and |value| appropriately. Now actually deserialize the thing.
- #
- # field_descriptor: Describes the field we're deserializing.
- # value: The value currently stored in the field to deserialize.
- # Used only if the field is composite and/or repeated.
- # scalar_setter_fn: A function F such that F(scalar) will
- # set a nonrepeated scalar value for this field. Used only
- # if this field is a nonrepeated scalar.
-
- field_number = field_descriptor.number
- expected_wire_type = _WireTypeForField(field_descriptor)
- if wire_type != expected_wire_type:
- # Need to fill in uninterpreted_bytes. Work for the next CL.
- raise RuntimeError('TODO(robinson): Wiretype mismatches not handled.')
-
- property_name = _PropertyName(field_descriptor.name)
- label = field_descriptor.label
- field_type = field_descriptor.type
- cpp_type = field_descriptor.cpp_type
-
- # Nonrepeated scalar. Just set the field directly.
- if (label != _FieldDescriptor.LABEL_REPEATED
- and cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE):
- scalar_setter_fn(_DeserializeScalarFromDecoder(field_type, decoder))
- return decoder.Position() - initial_position
-
- # Nonrepeated composite. Recursively deserialize.
- if label != _FieldDescriptor.LABEL_REPEATED:
- composite = value
- _RecursivelyMerge(field_number, field_type, decoder, composite)
- return decoder.Position() - initial_position
-
- # Now we know we're dealing with a repeated field of some kind.
- element_list = value
-
- if cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE:
- # Repeated scalar.
- if not field_descriptor.GetOptions().packed:
- element_list.append(_DeserializeScalarFromDecoder(field_type, decoder))
- return decoder.Position() - initial_position
- else:
- # Packed repeated field.
- length = _DeserializeScalarFromDecoder(
- _FieldDescriptor.TYPE_INT32, decoder)
- content_start = decoder.Position()
- while decoder.Position() - content_start < length:
- element_list.append(_DeserializeScalarFromDecoder(field_type, decoder))
- return decoder.Position() - initial_position
- else:
- # Repeated composite.
- composite = element_list.add()
- _RecursivelyMerge(field_number, field_type, decoder, composite)
- return decoder.Position() - initial_position
-
-
-def _FieldOrExtensionValues(message, field_or_extension):
- """Retrieves the list of values for the specified field or extension.
-
- The target field or extension can be optional, required or repeated, but it
- must have value(s) set. The assumption is that the target field or extension
- is set (e.g. _HasFieldOrExtension holds true).
- Args:
- message: Message which contains the target field or extension.
- field_or_extension: Field or extension for which the list of values is
- required. Must be an instance of FieldDescriptor.
+def _AddMergeFromStringMethod(message_descriptor, cls):
+ """Helper for _AddMessageMethods()."""
+ def MergeFromString(self, serialized):
+ length = len(serialized)
+ try:
+ if self._InternalParse(serialized, 0, length) != length:
+ # The only reason _InternalParse would return early is if it
+ # encountered an end-group tag.
+ raise message_mod.DecodeError('Unexpected end-group tag.')
+ except IndexError:
+ raise message_mod.DecodeError('Truncated message.')
+ except struct.error, e:
+ raise message_mod.DecodeError(e)
+ return length # Return this for legacy reasons.
+ cls.MergeFromString = MergeFromString
- Returns:
- A list of values for the specified field or extension. This list will only
- contain a single element if the field is non-repeated.
- """
- if field_or_extension.is_extension:
- value = message.Extensions[field_or_extension]
- else:
- value = getattr(message, _ValueFieldName(field_or_extension.name))
- if field_or_extension.label != _FieldDescriptor.LABEL_REPEATED:
- return [value]
- else:
- # In this case value is a list or repeated values.
- return value
+ local_ReadTag = decoder.ReadTag
+ local_SkipField = decoder.SkipField
+ decoders_by_tag = cls._decoders_by_tag
+
+ def InternalParse(self, buffer, pos, end):
+ self._Modified()
+ field_dict = self._fields
+ while pos != end:
+ (tag_bytes, new_pos) = local_ReadTag(buffer, pos)
+ field_decoder = decoders_by_tag.get(tag_bytes)
+ if field_decoder is None:
+ new_pos = local_SkipField(buffer, new_pos, end, tag_bytes)
+ if new_pos == -1:
+ return pos
+ pos = new_pos
+ else:
+ pos = field_decoder(buffer, new_pos, end, self, field_dict)
+ return pos
+ cls._InternalParse = InternalParse
-def _HasFieldOrExtension(message, field_or_extension):
- """Checks if a message has the specified field or extension set.
+def _AddIsInitializedMethod(message_descriptor, cls):
+ """Adds the IsInitialized and FindInitializationError methods to the
+ protocol message class."""
- The field or extension specified can be optional, required or repeated. If
- it is repeated, this function returns True. Otherwise it checks the has bit
- of the field or extension.
+ required_fields = [field for field in message_descriptor.fields
+ if field.label == _FieldDescriptor.LABEL_REQUIRED]
- Args:
- message: Message which contains the target field or extension.
- field_or_extension: Field or extension to check. This must be a
- FieldDescriptor instance.
+ def IsInitialized(self, errors=None):
+ """Checks if all required fields of a message are set.
- Returns:
- True if the message has a value set for the specified field or extension,
- or if the field or extension is repeated.
- """
- if field_or_extension.label == _FieldDescriptor.LABEL_REPEATED:
- return True
- if field_or_extension.is_extension:
- return message.HasExtension(field_or_extension)
- else:
- return message.HasField(field_or_extension.name)
+ Args:
+ errors: A list which, if provided, will be populated with the field
+ paths of all missing required fields.
+ Returns:
+ True iff the specified message has all required fields set.
+ """
-def _IsFieldOrExtensionInitialized(message, field, errors=None):
- """Checks if a message field or extension is initialized.
+ # Performance is critical so we avoid HasField() and ListFields().
- Args:
- message: The message which contains the field or extension.
- field: Field or extension to check. This must be a FieldDescriptor instance.
- errors: Errors will be appended to it, if set to a meaningful value.
+ for field in required_fields:
+ if (field not in self._fields or
+ (field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
+ not self._fields[field]._is_present_in_parent)):
+ if errors is not None:
+ errors.extend(self.FindInitializationErrors())
+ return False
- Returns:
- True if the field/extension can be considered initialized.
- """
- # If the field is required and is not set, it isn't initialized.
- if field.label == _FieldDescriptor.LABEL_REQUIRED:
- if not _HasFieldOrExtension(message, field):
- if errors is not None:
- errors.append('Required field %s is not set.' % field.full_name)
- return False
+ for field, value in self._fields.iteritems():
+ if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+ if field.label == _FieldDescriptor.LABEL_REPEATED:
+ for element in value:
+ if not element.IsInitialized():
+ if errors is not None:
+ errors.extend(self.FindInitializationErrors())
+ return False
+ elif value._is_present_in_parent and not value.IsInitialized():
+ if errors is not None:
+ errors.extend(self.FindInitializationErrors())
+ return False
- # If the field is optional and is not set, or if it
- # isn't a submessage then the field is initialized.
- if field.label == _FieldDescriptor.LABEL_OPTIONAL:
- if not _HasFieldOrExtension(message, field):
- return True
- if field.cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE:
return True
- # The field is set and is either a single or a repeated submessage.
- messages = _FieldOrExtensionValues(message, field)
- # If all submessages in this field are initialized, the field is
- # considered initialized.
- for message in messages:
- if not _InternalIsInitialized(message, errors):
- return False
- return True
-
+ cls.IsInitialized = IsInitialized
-def _InternalIsInitialized(message, errors=None):
- """Checks if all required fields of a message are set.
-
- Args:
- message: The message to check.
- errors: If set, initialization errors will be appended to it.
+ def FindInitializationErrors(self):
+ """Finds required fields which are not initialized.
- Returns:
- True iff the specified message has all required fields set.
- """
- fields_and_extensions = []
- fields_and_extensions.extend(message.DESCRIPTOR.fields)
- fields_and_extensions.extend(
- [extension[0] for extension in message.Extensions._ListSetExtensions()])
- for field_or_extension in fields_and_extensions:
- if not _IsFieldOrExtensionInitialized(message, field_or_extension, errors):
- return False
- return True
-
-
-def _AddMergeFromStringMethod(message_descriptor, cls):
- """Helper for _AddMessageMethods()."""
- Decoder = decoder.Decoder
- def MergeFromString(self, serialized):
- decoder = Decoder(serialized)
- byte_count = 0
- while not decoder.EndOfStream():
- bytes_read = _DeserializeOneEntity(message_descriptor, self, decoder)
- if not bytes_read:
- break
- byte_count += bytes_read
- return byte_count
- cls.MergeFromString = MergeFromString
-
-
-def _AddIsInitializedMethod(cls):
- """Adds the IsInitialized method to the protocol message class."""
- cls.IsInitialized = _InternalIsInitialized
+ Returns:
+ A list of strings. Each string is a path to an uninitialized field from
+ the top-level message, e.g. "foo.bar[5].baz".
+ """
+ errors = [] # simplify things
-def _MergeFieldOrExtension(destination_msg, field, value):
- """Merges a specified message field into another message."""
- property_name = _PropertyName(field.name)
- is_extension = field.is_extension
+ for field in required_fields:
+ if not self.HasField(field.name):
+ errors.append(field.name)
- if not is_extension:
- destination = getattr(destination_msg, property_name)
- elif (field.label == _FieldDescriptor.LABEL_REPEATED or
- field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE):
- destination = destination_msg.Extensions[field]
+ for field, value in self.ListFields():
+ if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+ if field.is_extension:
+ name = "(%s)" % field.full_name
+ else:
+ name = field.name
- # Case 1 - a composite field.
- if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
- if field.label == _FieldDescriptor.LABEL_REPEATED:
- for v in value:
- destination.add().MergeFrom(v)
- else:
- destination.MergeFrom(value)
- return
+ if field.label == _FieldDescriptor.LABEL_REPEATED:
+ for i in xrange(len(value)):
+ element = value[i]
+ prefix = "%s[%d]." % (name, i)
+ sub_errors = element.FindInitializationErrors()
+ errors += [ prefix + error for error in sub_errors ]
+ else:
+ prefix = name + "."
+ sub_errors = value.FindInitializationErrors()
+ errors += [ prefix + error for error in sub_errors ]
- # Case 2 - a repeated field.
- if field.label == _FieldDescriptor.LABEL_REPEATED:
- for v in value:
- destination.append(v)
- return
+ return errors
- # Case 3 - a singular field.
- if is_extension:
- destination_msg.Extensions[field] = value
- else:
- setattr(destination_msg, property_name, value)
+ cls.FindInitializationErrors = FindInitializationErrors
def _AddMergeFromMethod(cls):
+ LABEL_REPEATED = _FieldDescriptor.LABEL_REPEATED
+ CPPTYPE_MESSAGE = _FieldDescriptor.CPPTYPE_MESSAGE
+
def MergeFrom(self, msg):
assert msg is not self
- for field in msg.ListFields():
- _MergeFieldOrExtension(self, field[0], field[1])
+ self._Modified()
+
+ fields = self._fields
+
+ for field, value in msg._fields.iteritems():
+ if field.label == LABEL_REPEATED or field.cpp_type == CPPTYPE_MESSAGE:
+ field_value = fields.get(field)
+ if field_value is None:
+ # Construct a new object to represent this field.
+ field_value = field._default_constructor(self)
+ fields[field] = field_value
+ field_value.MergeFrom(value)
+ else:
+ self._fields[field] = value
cls.MergeFrom = MergeFrom
def _AddMessageMethods(message_descriptor, cls):
"""Adds implementations of all Message methods to cls."""
_AddListFieldsMethod(message_descriptor, cls)
- _AddHasFieldMethod(cls)
- _AddClearFieldMethod(cls)
- _AddClearExtensionMethod(cls)
- _AddClearMethod(cls)
- _AddHasExtensionMethod(cls)
+ _AddHasFieldMethod(message_descriptor, cls)
+ _AddClearFieldMethod(message_descriptor, cls)
+ if message_descriptor.is_extendable:
+ _AddClearExtensionMethod(cls)
+ _AddHasExtensionMethod(cls)
+ _AddClearMethod(message_descriptor, cls)
_AddEqualsMethod(message_descriptor, cls)
_AddStrMethod(message_descriptor, cls)
_AddSetListenerMethod(cls)
@@ -1304,31 +971,30 @@ def _AddMessageMethods(message_descriptor, cls):
_AddSerializeToStringMethod(message_descriptor, cls)
_AddSerializePartialToStringMethod(message_descriptor, cls)
_AddMergeFromStringMethod(message_descriptor, cls)
- _AddIsInitializedMethod(cls)
+ _AddIsInitializedMethod(message_descriptor, cls)
_AddMergeFromMethod(cls)
def _AddPrivateHelperMethods(cls):
"""Adds implementation of private helper methods to cls."""
- def MaybeCallTransitionToNonemptyCallback(self):
- """Calls self._listener.TransitionToNonempty() the first time this
- method is called. On all subsequent calls, this is a no-op.
- """
- if not self._called_transition_to_nonempty:
- self._listener.TransitionToNonempty()
- self._called_transition_to_nonempty = True
- cls._MaybeCallTransitionToNonemptyCallback = (
- MaybeCallTransitionToNonemptyCallback)
-
- def MarkByteSizeDirty(self):
+ def Modified(self):
"""Sets the _cached_byte_size_dirty bit to true,
and propagates this to our listener iff this was a state change.
"""
+
+ # Note: Some callers check _cached_byte_size_dirty before calling
+ # _Modified() as an extra optimization. So, if this method is ever
+ # changed such that it does stuff even when _cached_byte_size_dirty is
+ # already true, the callers need to be updated.
if not self._cached_byte_size_dirty:
self._cached_byte_size_dirty = True
- self._listener.ByteSizeDirty()
- cls._MarkByteSizeDirty = MarkByteSizeDirty
+ self._listener_for_children.dirty = True
+ self._is_present_in_parent = True
+ self._listener.Modified()
+
+ cls._Modified = Modified
+ cls.SetInParent = Modified
class _Listener(object):
@@ -1338,22 +1004,17 @@ class _Listener(object):
In order to support semantics like:
- foo.bar.baz = 23
+ foo.bar.baz.qux = 23
assert foo.HasField('bar')
...child objects must have back references to their parents.
This helper class is at the heart of this support.
"""
- def __init__(self, parent_message, has_field_name):
+ def __init__(self, parent_message):
"""Args:
- parent_message: The message whose _MaybeCallTransitionToNonemptyCallback()
- and _MarkByteSizeDirty() methods we should call when we receive
- TransitionToNonempty() and ByteSizeDirty() messages.
- has_field_name: The name of the "has" field that we should set in
- the parent message when we receive a TransitionToNonempty message,
- or None if there's no "has" field to set. (This will be the case
- for child objects in "repeated" fields).
+ parent_message: The message whose _Modified() method we should call when
+ we receive Modified() messages.
"""
# This listener establishes a back reference from a child (contained) object
# to its parent (containing) object. We make this a weak reference to avoid
@@ -1363,36 +1024,27 @@ class _Listener(object):
self._parent_message_weakref = parent_message
else:
self._parent_message_weakref = weakref.proxy(parent_message)
- self._has_field_name = has_field_name
- def TransitionToNonempty(self):
+ # As an optimization, we also indicate directly on the listener whether
+ # or not the parent message is dirty. This way we can avoid traversing
+ # up the tree in the common case.
+ self.dirty = False
+
+ def Modified(self):
+ if self.dirty:
+ return
try:
- if self._has_field_name is not None:
- setattr(self._parent_message_weakref, self._has_field_name, True)
# Propagate the signal to our parents iff this is the first field set.
- self._parent_message_weakref._MaybeCallTransitionToNonemptyCallback()
+ self._parent_message_weakref._Modified()
except ReferenceError:
# We can get here if a client has kept a reference to a child object,
# and is now setting a field on it, but the child's parent has been
# garbage-collected. This is not an error.
pass
- def ByteSizeDirty(self):
- try:
- self._parent_message_weakref._MarkByteSizeDirty()
- except ReferenceError:
- # Same as above.
- pass
-
# TODO(robinson): Move elsewhere? This file is getting pretty ridiculous...
# TODO(robinson): Unify error handling of "unknown extension" crap.
-# TODO(robinson): There's so much similarity between the way that
-# extensions behave and the way that normal fields behave that it would
-# be really nice to unify more code. It's not immediately obvious
-# how to do this, though, and I'd rather get the full functionality
-# implemented (and, crucially, get all the tests and specs fleshed out
-# and passing), and then come back to this thorny unification problem.
# TODO(robinson): Support iteritems()-style iteration over all
# extensions with the "has" bits turned on?
class _ExtensionDict(object):
@@ -1404,250 +1056,85 @@ class _ExtensionDict(object):
FieldDescriptors.
"""
- class _ExtensionListener(object):
+ def __init__(self, extended_message):
+ """extended_message: Message instance for which we are the Extensions dict.
+ """
- """Adapts an _ExtensionDict to behave as a MessageListener."""
+ self._extended_message = extended_message
- def __init__(self, extension_dict, handle_id):
- self._extension_dict = extension_dict
- self._handle_id = handle_id
+ def __getitem__(self, extension_handle):
+ """Returns the current value of the given extension handle."""
- def TransitionToNonempty(self):
- self._extension_dict._SubmessageTransitionedToNonempty(self._handle_id)
+ _VerifyExtensionHandle(self._extended_message, extension_handle)
- def ByteSizeDirty(self):
- self._extension_dict._SubmessageByteSizeBecameDirty()
+ result = self._extended_message._fields.get(extension_handle)
+ if result is not None:
+ return result
- # TODO(robinson): Somewhere, we need to blow up if people
- # try to register two extensions with the same field number.
- # (And we need a test for this of course).
+ if extension_handle.label == _FieldDescriptor.LABEL_REPEATED:
+ result = extension_handle._default_constructor(self._extended_message)
+ elif extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
+ result = extension_handle.message_type._concrete_class()
+ try:
+ result._SetListener(self._extended_message._listener_for_children)
+ except ReferenceError:
+ pass
+ else:
+ # Singular scalar -- just return the default without inserting into the
+ # dict.
+ return extension_handle.default_value
- def __init__(self, extended_message, known_extensions):
- """extended_message: Message instance for which we are the Extensions dict.
- known_extensions: Iterable of known extension handles.
- These must be FieldDescriptors.
- """
- # We keep a weak reference to extended_message, since
- # it has a reference to this instance in turn.
- self._extended_message = weakref.proxy(extended_message)
- # We make a deep copy of known_extensions to avoid any
- # thread-safety concerns, since the argument passed in
- # is the global (class-level) dict of known extensions for
- # this type of message, which could be modified at any time
- # via a RegisterExtension() call.
- #
- # This dict maps from handle id to handle (a FieldDescriptor).
- #
- # XXX
- # TODO(robinson): This isn't good enough. The client could
- # instantiate an object in module A, then afterward import
- # module B and pass the instance to B.Foo(). If B imports
- # an extender of this proto and then tries to use it, B
- # will get a KeyError, even though the extension *is* registered
- # at the time of use.
- # XXX
- self._known_extensions = dict((id(e), e) for e in known_extensions)
- # Read lock around self._values, which may be modified by multiple
- # concurrent readers in the conceptually "const" __getitem__ method.
- # So, we grab this lock in every "read-only" method to ensure
- # that concurrent read access is safe without external locking.
- self._lock = threading.Lock()
- # Maps from extension handle ID to current value of that extension.
- self._values = {}
- # Maps from extension handle ID to a boolean "has" bit, but only
- # for non-repeated extension fields.
- keys = (id for id, extension in self._known_extensions.iteritems()
- if extension.label != _FieldDescriptor.LABEL_REPEATED)
- self._has_bits = dict.fromkeys(keys, False)
-
- self._extensions_by_number = dict(
- (f.number, f) for f in self._known_extensions.itervalues())
-
- self._extensions_by_name = {}
- for extension in self._known_extensions.itervalues():
- if (extension.containing_type.GetOptions().message_set_wire_format and
- extension.type == descriptor_mod.FieldDescriptor.TYPE_MESSAGE and
- extension.message_type == extension.extension_scope and
- extension.label == descriptor_mod.FieldDescriptor.LABEL_OPTIONAL):
- extension_name = extension.message_type.full_name
- else:
- extension_name = extension.full_name
- self._extensions_by_name[extension_name] = extension
+ # Atomically check if another thread has preempted us and, if not, swap
+ # in the new object we just created. If someone has preempted us, we
+ # take that object and discard ours.
+ # WARNING: We are relying on setdefault() being atomic. This is true
+ # in CPython but we haven't investigated others. This warning appears
+ # in several other locations in this file.
+ result = self._extended_message._fields.setdefault(
+ extension_handle, result)
- def __getitem__(self, extension_handle):
- """Returns the current value of the given extension handle."""
- # We don't care as much about keeping critical sections short in the
- # extension support, since it's presumably much less of a common case.
- self._lock.acquire()
- try:
- handle_id = id(extension_handle)
- if handle_id not in self._known_extensions:
- raise KeyError('Extension not known to this class')
- if handle_id not in self._values:
- self._AddMissingHandle(extension_handle, handle_id)
- return self._values[handle_id]
- finally:
- self._lock.release()
+ return result
def __eq__(self, other):
- # We have to grab read locks since we're accessing _values
- # in a "const" method. See the comment in the constructor.
- if self is other:
- return True
- self._lock.acquire()
- try:
- other._lock.acquire()
- try:
- if self._has_bits != other._has_bits:
- return False
- # If there's a "has" bit, then only compare values where it is true.
- for k, v in self._values.iteritems():
- if self._has_bits.get(k, False) and v != other._values[k]:
- return False
- return True
- finally:
- other._lock.release()
- finally:
- self._lock.release()
+ if not isinstance(other, self.__class__):
+ return False
+
+ my_fields = self._extended_message.ListFields()
+ other_fields = other._extended_message.ListFields()
+
+ # Get rid of non-extension fields.
+ my_fields = [ field for field in my_fields if field.is_extension ]
+ other_fields = [ field for field in other_fields if field.is_extension ]
+
+ return my_fields == other_fields
def __ne__(self, other):
return not self == other
# Note that this is only meaningful for non-repeated, scalar extension
- # fields. Note also that we may have to call
- # MaybeCallTransitionToNonemptyCallback() when we do successfully set a field
- # this way, to set any necssary "has" bits in the ancestors of the extended
- # message.
+ # fields. Note also that we may have to call _Modified() when we do
+ # successfully set a field this way, to set any necssary "has" bits in the
+ # ancestors of the extended message.
def __setitem__(self, extension_handle, value):
"""If extension_handle specifies a non-repeated, scalar extension
field, sets the value of that field.
"""
- handle_id = id(extension_handle)
- if handle_id not in self._known_extensions:
- raise KeyError('Extension not known to this class')
- field = extension_handle # Just shorten the name.
- if (field.label == _FieldDescriptor.LABEL_OPTIONAL
- and field.cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE):
- # It's slightly wasteful to lookup the type checker each time,
- # but we expect this to be a vanishingly uncommon case anyway.
- type_checker = type_checkers.GetTypeChecker(field.cpp_type, field.type)
- type_checker.CheckValue(value)
- self._values[handle_id] = value
- self._has_bits[handle_id] = True
- self._extended_message._MarkByteSizeDirty()
- self._extended_message._MaybeCallTransitionToNonemptyCallback()
- else:
- raise TypeError('Extension is repeated and/or a composite type.')
-
- def _AddMissingHandle(self, extension_handle, handle_id):
- """Helper internal to ExtensionDict."""
- # Special handling for non-repeated message extensions, which (like
- # normal fields of this kind) are initialized lazily.
- # REQUIRES: _lock already held.
- cpp_type = extension_handle.cpp_type
- label = extension_handle.label
- if (cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE
- and label != _FieldDescriptor.LABEL_REPEATED):
- self._AddMissingNonRepeatedCompositeHandle(extension_handle, handle_id)
- else:
- self._values[handle_id] = _DefaultValueForField(
- self._extended_message, extension_handle)
-
- def _AddMissingNonRepeatedCompositeHandle(self, extension_handle, handle_id):
- """Helper internal to ExtensionDict."""
- # REQUIRES: _lock already held.
- value = extension_handle.message_type._concrete_class()
- value._SetListener(_ExtensionDict._ExtensionListener(self, handle_id))
- self._values[handle_id] = value
-
- def _SubmessageTransitionedToNonempty(self, handle_id):
- """Called when a submessage with a given handle id first transitions to
- being nonempty. Called by _ExtensionListener.
- """
- assert handle_id in self._has_bits
- self._has_bits[handle_id] = True
- self._extended_message._MaybeCallTransitionToNonemptyCallback()
- def _SubmessageByteSizeBecameDirty(self):
- """Called whenever a submessage's cached byte size becomes invalid
- (goes from being "clean" to being "dirty"). Called by _ExtensionListener.
- """
- self._extended_message._MarkByteSizeDirty()
-
- # We may wish to widen the public interface of Message.Extensions
- # to expose some of this private functionality in the future.
- # For now, we make all this functionality module-private and just
- # implement what we need for serialization/deserialization,
- # HasField()/ClearField(), etc.
-
- def _HasExtension(self, extension_handle):
- """Method for internal use by this module.
- Returns true iff we "have" this extension in the sense of the
- "has" bit being set.
- """
- handle_id = id(extension_handle)
- # Note that this is different from the other checks.
- if handle_id not in self._has_bits:
- raise KeyError('Extension not known to this class, or is repeated field.')
- return self._has_bits[handle_id]
-
- # Intentionally pretty similar to ClearField() above.
- def _ClearExtension(self, extension_handle):
- """Method for internal use by this module.
- Clears the specified extension, unsetting its "has" bit.
- """
- handle_id = id(extension_handle)
- if handle_id not in self._known_extensions:
- raise KeyError('Extension not known to this class')
- default_value = _DefaultValueForField(self._extended_message,
- extension_handle)
- if extension_handle.label == _FieldDescriptor.LABEL_REPEATED:
- self._extended_message._MarkByteSizeDirty()
- else:
- cpp_type = extension_handle.cpp_type
- if cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
- if handle_id in self._values:
- # Future modifications to this object shouldn't set any
- # "has" bits here.
- self._values[handle_id]._SetListener(None)
- if self._has_bits[handle_id]:
- self._has_bits[handle_id] = False
- self._extended_message._MarkByteSizeDirty()
- if handle_id in self._values:
- del self._values[handle_id]
-
- def _ListSetExtensions(self):
- """Method for internal use by this module.
-
- Returns an sequence of all extensions that are currently "set"
- in this extension dict. A "set" extension is a repeated extension,
- or a non-repeated extension with its "has" bit set.
-
- The returned sequence contains (field_descriptor, value) pairs,
- where value is the current value of the extension with the given
- field descriptor.
-
- The sequence values are in arbitrary order.
- """
- self._lock.acquire() # Read-only methods must lock around self._values.
- try:
- set_extensions = []
- for handle_id, value in self._values.iteritems():
- handle = self._known_extensions[handle_id]
- if (handle.label == _FieldDescriptor.LABEL_REPEATED
- or self._has_bits[handle_id]):
- set_extensions.append((handle, value))
- return set_extensions
- finally:
- self._lock.release()
-
- def _AllExtensionsByNumber(self):
- """Method for internal use by this module.
-
- Returns: A dict mapping field_number to (handle, field_descriptor),
- for *all* registered extensions for this dict.
- """
- return self._extensions_by_number
+ _VerifyExtensionHandle(self._extended_message, extension_handle)
+
+ if (extension_handle.label == _FieldDescriptor.LABEL_REPEATED or
+ extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE):
+ raise TypeError(
+ 'Cannot assign to extension "%s" because it is a repeated or '
+ 'composite type.' % extension_handle.full_name)
+
+ # It's slightly wasteful to lookup the type checker each time,
+ # but we expect this to be a vanishingly uncommon case anyway.
+ type_checker = type_checkers.GetTypeChecker(
+ extension_handle.cpp_type, extension_handle.type)
+ type_checker.CheckValue(value)
+ self._extended_message._fields[extension_handle] = value
+ self._extended_message._Modified()
def _FindExtensionByName(self, name):
"""Tries to find a known extension with the specified name.
@@ -1658,4 +1145,4 @@ class _ExtensionDict(object):
Returns:
Extension field descriptor.
"""
- return self._extensions_by_name.get(name, None)
+ return self._extended_message._extensions_by_name.get(name, None)
diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py
index 1cddce6c..889aa836 100755
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -149,6 +149,10 @@ def _MergeField(tokenizer, message):
name.append(tokenizer.ConsumeIdentifier())
name = '.'.join(name)
+ if not message_descriptor.is_extendable:
+ raise tokenizer.ParseErrorPreviousToken(
+ 'Message type "%s" does not have extensions.' %
+ message_descriptor.full_name)
field = message.Extensions._FindExtensionByName(name)
if not field:
raise tokenizer.ParseErrorPreviousToken(
@@ -198,6 +202,7 @@ def _MergeField(tokenizer, message):
sub_message = message.Extensions[field]
else:
sub_message = getattr(message, field.name)
+ sub_message.SetInParent()
while not tokenizer.TryConsume(end_token):
if tokenizer.AtEnd():
diff --git a/python/setup.py b/python/setup.py
index 118ccd41..4051c533 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -58,16 +58,13 @@ def MakeTestSuite():
generate_proto("../src/google/protobuf/unittest.proto")
generate_proto("../src/google/protobuf/unittest_import.proto")
generate_proto("../src/google/protobuf/unittest_mset.proto")
+ generate_proto("../src/google/protobuf/unittest_no_generic_services.proto")
generate_proto("google/protobuf/internal/more_extensions.proto")
generate_proto("google/protobuf/internal/more_messages.proto")
import unittest
import google.protobuf.internal.generator_test as generator_test
- import google.protobuf.internal.decoder_test as decoder_test
import google.protobuf.internal.descriptor_test as descriptor_test
- import google.protobuf.internal.encoder_test as encoder_test
- import google.protobuf.internal.input_stream_test as input_stream_test
- import google.protobuf.internal.output_stream_test as output_stream_test
import google.protobuf.internal.reflection_test as reflection_test
import google.protobuf.internal.service_reflection_test \
as service_reflection_test
@@ -77,11 +74,7 @@ def MakeTestSuite():
loader = unittest.defaultTestLoader
suite = unittest.TestSuite()
for test in [ generator_test,
- decoder_test,
descriptor_test,
- encoder_test,
- input_stream_test,
- output_stream_test,
reflection_test,
service_reflection_test,
text_format_test,
@@ -114,9 +107,7 @@ if __name__ == '__main__':
'google.protobuf.internal.containers',
'google.protobuf.internal.decoder',
'google.protobuf.internal.encoder',
- 'google.protobuf.internal.input_stream',
'google.protobuf.internal.message_listener',
- 'google.protobuf.internal.output_stream',
'google.protobuf.internal.type_checkers',
'google.protobuf.internal.wire_format',
'google.protobuf.descriptor',
diff --git a/src/Makefile.am b/src/Makefile.am
index 53da6f1e..510613ce 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,7 +24,8 @@ AM_LDFLAGS = $(PTHREAD_CFLAGS)
# If I say "dist_include_DATA", automake complains that $(includedir) is not
# a "legitimate" directory for DATA. Screw you, automake.
protodir = $(includedir)
-nobase_dist_proto_DATA = google/protobuf/descriptor.proto
+nobase_dist_proto_DATA = google/protobuf/descriptor.proto \
+ google/protobuf/compiler/plugin.proto
# Not sure why these don't get cleaned automatically.
clean-local:
@@ -66,6 +67,8 @@ nobase_include_HEADERS = \
google/protobuf/compiler/command_line_interface.h \
google/protobuf/compiler/importer.h \
google/protobuf/compiler/parser.h \
+ google/protobuf/compiler/plugin.h \
+ google/protobuf/compiler/plugin.pb.h \
google/protobuf/compiler/cpp/cpp_generator.h \
google/protobuf/compiler/java/java_generator.h \
google/protobuf/compiler/python/python_generator.h
@@ -87,6 +90,7 @@ libprotobuf_lite_la_SOURCES = \
google/protobuf/repeated_field.cc \
google/protobuf/wire_format_lite.cc \
google/protobuf/io/coded_stream.cc \
+ google/protobuf/io/coded_stream_inl.h \
google/protobuf/io/zero_copy_stream.cc \
google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -123,6 +127,10 @@ libprotoc_la_LDFLAGS = -version-info 5:0:0
libprotoc_la_SOURCES = \
google/protobuf/compiler/code_generator.cc \
google/protobuf/compiler/command_line_interface.cc \
+ google/protobuf/compiler/plugin.cc \
+ google/protobuf/compiler/plugin.pb.cc \
+ google/protobuf/compiler/subprocess.cc \
+ google/protobuf/compiler/subprocess.h \
google/protobuf/compiler/cpp/cpp_enum.cc \
google/protobuf/compiler/cpp/cpp_enum.h \
google/protobuf/compiler/cpp/cpp_enum_field.cc \
@@ -186,6 +194,7 @@ protoc_inputs = \
google/protobuf/unittest_lite.proto \
google/protobuf/unittest_import_lite.proto \
google/protobuf/unittest_lite_imports_nonlite.proto \
+ google/protobuf/unittest_no_generic_services.proto \
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
EXTRA_DIST = \
@@ -226,6 +235,8 @@ protoc_outputs = \
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/unittest_no_generic_services.pb.cc \
+ google/protobuf/unittest_no_generic_services.pb.h \
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h
@@ -265,7 +276,7 @@ COMMON_TEST_SOURCES = \
google/protobuf/testing/file.cc \
google/protobuf/testing/file.h
-check_PROGRAMS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test $(GZCHECKPROGRAMS)
+check_PROGRAMS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test test_plugin $(GZCHECKPROGRAMS)
protobuf_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
$(top_builddir)/gtest/lib/libgtest.la \
$(top_builddir)/gtest/lib/libgtest_main.la
@@ -297,9 +308,14 @@ protobuf_test_SOURCES = \
google/protobuf/io/zero_copy_stream_unittest.cc \
google/protobuf/compiler/command_line_interface_unittest.cc \
google/protobuf/compiler/importer_unittest.cc \
+ google/protobuf/compiler/mock_code_generator.cc \
+ google/protobuf/compiler/mock_code_generator.h \
google/protobuf/compiler/parser_unittest.cc \
google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc \
google/protobuf/compiler/cpp/cpp_unittest.cc \
+ google/protobuf/compiler/cpp/cpp_plugin_unittest.cc \
+ google/protobuf/compiler/java/java_plugin_unittest.cc \
+ google/protobuf/compiler/python/python_plugin_unittest.cc \
$(COMMON_TEST_SOURCES)
nodist_protobuf_test_SOURCES = $(protoc_outputs)
@@ -325,6 +341,15 @@ protobuf_lite_test_SOURCES = \
google/protobuf/test_util_lite.h
nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs)
+# Test plugin binary.
+test_plugin_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
+ $(top_builddir)/gtest/lib/libgtest.la
+test_plugin_SOURCES = \
+ google/protobuf/compiler/mock_code_generator.cc \
+ google/protobuf/testing/file.cc \
+ google/protobuf/testing/file.h \
+ google/protobuf/compiler/test_plugin.cc
+
if HAVE_ZLIB
zcgzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
zcgzip_SOURCES = google/protobuf/testing/zcgzip.cc
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc
index 0def84d8..3413a36a 100644
--- a/src/google/protobuf/compiler/code_generator.cc
+++ b/src/google/protobuf/compiler/code_generator.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
@@ -43,9 +44,15 @@ namespace compiler {
CodeGenerator::~CodeGenerator() {}
OutputDirectory::~OutputDirectory() {}
+io::ZeroCopyOutputStream* OutputDirectory::OpenForInsert(
+ const string& filename, const string& insertion_point) {
+ GOOGLE_LOG(FATAL) << "This OutputDirectory does not support insertion.";
+ return NULL; // make compiler happy
+}
+
// Parses a set of comma-delimited name/value pairs.
void ParseGeneratorParameter(const string& text,
- vector<pair<string, string> >* output) {
+ vector<pair<string, string> >* output) {
vector<string> parts;
SplitStringUsing(text, ",", &parts);
diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h
index 8a7081f7..47ebb4d2 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -103,6 +103,13 @@ class LIBPROTOC_EXPORT OutputDirectory {
// contain "." or ".." components.
virtual io::ZeroCopyOutputStream* Open(const string& filename) = 0;
+ // Creates a ZeroCopyOutputStream which will insert code into the given file
+ // at the given insertion point. See plugin.proto for more information on
+ // insertion points. The default implementation assert-fails -- it exists
+ // only for backwards-compatibility.
+ virtual io::ZeroCopyOutputStream* OpenForInsert(
+ const string& filename, const string& insertion_point);
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OutputDirectory);
};
@@ -114,7 +121,7 @@ class LIBPROTOC_EXPORT OutputDirectory {
// parses to the pairs:
// ("foo", "bar"), ("baz", ""), ("qux", "corge")
extern void ParseGeneratorParameter(const string&,
- vector<pair<string, string> >*);
+ vector<pair<string, string> >*);
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 3eba3486..39bd370e 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -32,6 +32,8 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <google/protobuf/compiler/command_line_interface.h>
+
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -46,15 +48,19 @@
#include <iostream>
#include <ctype.h>
-#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/plugin.pb.h>
+#include <google/protobuf/compiler/subprocess.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/map-util.h>
namespace google {
@@ -182,6 +188,8 @@ class CommandLineInterface::DiskOutputDirectory : public OutputDirectory {
// implements OutputDirectory --------------------------------------
io::ZeroCopyOutputStream* Open(const string& filename);
+ io::ZeroCopyOutputStream* OpenForInsert(
+ const string& filename, const string& insertion_point);
private:
string root_;
@@ -209,11 +217,45 @@ class CommandLineInterface::ErrorReportingFileOutput
private:
scoped_ptr<io::FileOutputStream> file_stream_;
- int file_descriptor_;
string filename_;
DiskOutputDirectory* directory_;
};
+// Kind of like ErrorReportingFileOutput, but used when inserting
+// (OutputDirectory::OpenForInsert()). In this case, we are writing to a
+// temporary file, since we must copy data from the original. We copy the
+// data up to the insertion point in the constructor, and the remainder in the
+// destructor. We then replace the original file with the temporary, also in
+// the destructor.
+class CommandLineInterface::InsertionOutputStream
+ : public io::ZeroCopyOutputStream {
+ public:
+ InsertionOutputStream(
+ const string& filename,
+ const string& temp_filename,
+ const string& insertion_point,
+ int original_file_descriptor, // Takes ownership.
+ int temp_file_descriptor, // Takes ownership.
+ DiskOutputDirectory* directory); // Does not take ownership.
+ ~InsertionOutputStream();
+
+ // implements ZeroCopyOutputStream ---------------------------------
+ bool Next(void** data, int* size) { return temp_file_->Next(data, size); }
+ void BackUp(int count) { temp_file_->BackUp(count); }
+ int64 ByteCount() const { return temp_file_->ByteCount(); }
+
+ private:
+ scoped_ptr<io::FileInputStream> original_file_;
+ scoped_ptr<io::FileOutputStream> temp_file_;
+
+ string filename_;
+ string temp_filename_;
+ DiskOutputDirectory* directory_;
+
+ // The contents of the line containing the insertion point.
+ string magic_line_;
+};
+
// -------------------------------------------------------------------
CommandLineInterface::DiskOutputDirectory::DiskOutputDirectory(
@@ -242,6 +284,8 @@ bool CommandLineInterface::DiskOutputDirectory::VerifyExistence() {
return true;
}
+// -------------------------------------------------------------------
+
io::ZeroCopyOutputStream* CommandLineInterface::DiskOutputDirectory::Open(
const string& filename) {
// Recursively create parent directories to the output file.
@@ -286,7 +330,6 @@ CommandLineInterface::ErrorReportingFileOutput::ErrorReportingFileOutput(
const string& filename,
DiskOutputDirectory* directory)
: file_stream_(new io::FileOutputStream(file_descriptor)),
- file_descriptor_(file_descriptor),
filename_(filename),
directory_(directory) {}
@@ -304,6 +347,201 @@ CommandLineInterface::ErrorReportingFileOutput::~ErrorReportingFileOutput() {
}
}
+// -------------------------------------------------------------------
+
+io::ZeroCopyOutputStream*
+CommandLineInterface::DiskOutputDirectory::OpenForInsert(
+ const string& filename, const string& insertion_point) {
+ string path = root_ + filename;
+
+ // Put the temp file in the same directory so that we can simply rename() it
+ // into place later.
+ string temp_path = path + ".protoc_temp";
+
+ // Open the original file.
+ int original_file;
+ do {
+ original_file = open(path.c_str(), O_RDONLY | O_BINARY);
+ } while (original_file < 0 && errno == EINTR);
+
+ if (original_file < 0) {
+ // Failed to open.
+ cerr << path << ": " << strerror(errno) << endl;
+ had_error_ = true;
+ // Return a dummy stream.
+ return new io::ArrayOutputStream(NULL, 0);
+ }
+
+ // Create the temp file.
+ int temp_file;
+ do {
+ temp_file =
+ open(temp_path.c_str(),
+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ } while (temp_file < 0 && errno == EINTR);
+
+ if (temp_file < 0) {
+ // Failed to open.
+ cerr << temp_path << ": " << strerror(errno) << endl;
+ had_error_ = true;
+ close(original_file);
+ // Return a dummy stream.
+ return new io::ArrayOutputStream(NULL, 0);
+ }
+
+ return new InsertionOutputStream(
+ path, temp_path, insertion_point, original_file, temp_file, this);
+}
+
+namespace {
+
+// Helper for reading lines from a ZeroCopyInputStream.
+// TODO(kenton): Put somewhere reusable?
+class LineReader {
+ public:
+ LineReader(io::ZeroCopyInputStream* input)
+ : input_(input), buffer_(NULL), size_(0) {}
+
+ ~LineReader() {
+ if (size_ > 0) {
+ input_->BackUp(size_);
+ }
+ }
+
+ bool ReadLine(string* line) {
+ line->clear();
+
+ while (true) {
+ for (int i = 0; i < size_; i++) {
+ if (buffer_[i] == '\n') {
+ line->append(buffer_, i + 1);
+ buffer_ += i + 1;
+ size_ -= i + 1;
+ return true;
+ }
+ }
+
+ line->append(buffer_, size_);
+
+ const void* void_buffer;
+ if (!input_->Next(&void_buffer, &size_)) {
+ buffer_ = NULL;
+ size_ = 0;
+ return false;
+ }
+
+ buffer_ = reinterpret_cast<const char*>(void_buffer);
+ }
+ }
+
+ private:
+ io::ZeroCopyInputStream* input_;
+ const char* buffer_;
+ int size_;
+};
+
+} // namespace
+
+CommandLineInterface::InsertionOutputStream::InsertionOutputStream(
+ const string& filename,
+ const string& temp_filename,
+ const string& insertion_point,
+ int original_file_descriptor,
+ int temp_file_descriptor,
+ DiskOutputDirectory* directory)
+ : original_file_(new io::FileInputStream(original_file_descriptor)),
+ temp_file_(new io::FileOutputStream(temp_file_descriptor)),
+ filename_(filename),
+ temp_filename_(temp_filename),
+ directory_(directory) {
+ string magic_string = strings::Substitute(
+ "@@protoc_insertion_point($0)", insertion_point);
+
+ LineReader reader(original_file_.get());
+ io::Printer writer(temp_file_.get(), '$');
+ string line;
+
+ while (true) {
+ if (!reader.ReadLine(&line)) {
+ int error = temp_file_->GetErrno();
+ if (error == 0) {
+ cerr << filename << ": Insertion point not found: "
+ << insertion_point << endl;
+ } else {
+ cerr << filename << ": " << strerror(error) << endl;
+ }
+ original_file_->Close();
+ original_file_.reset();
+ // Will finish handling error in the destructor.
+ break;
+ }
+
+ if (line.find(magic_string) != string::npos) {
+ // Found the magic line. Since we want to insert before it, save it for
+ // later.
+ magic_line_ = line;
+ break;
+ }
+
+ writer.PrintRaw(line);
+ }
+}
+
+CommandLineInterface::InsertionOutputStream::~InsertionOutputStream() {
+ // C-style error handling is teh best.
+ bool had_error = false;
+
+ if (original_file_ == NULL) {
+ // We had an error in the constructor.
+ had_error = true;
+ } else {
+ // Use CodedOutputStream for convenience, so we don't have to deal with
+ // copying buffers ourselves.
+ io::CodedOutputStream out(temp_file_.get());
+ out.WriteRaw(magic_line_.data(), magic_line_.size());
+
+ // Write the rest of the original file.
+ const void* buffer;
+ int size;
+ while (original_file_->Next(&buffer, &size)) {
+ out.WriteRaw(buffer, size);
+ }
+
+ // Close the original file.
+ if (!original_file_->Close()) {
+ cerr << filename_ << ": " << strerror(original_file_->GetErrno()) << endl;
+ had_error = true;
+ }
+ }
+
+ // Check if we had any errors while writing.
+ if (temp_file_->GetErrno() != 0) {
+ cerr << filename_ << ": " << strerror(temp_file_->GetErrno()) << endl;
+ had_error = true;
+ }
+
+ // Close the temp file.
+ if (!temp_file_->Close()) {
+ cerr << filename_ << ": " << strerror(temp_file_->GetErrno()) << endl;
+ had_error = true;
+ }
+
+ // If everything was successful, overwrite the original file with the temp
+ // file.
+ if (!had_error) {
+ if (rename(temp_filename_.c_str(), filename_.c_str()) < 0) {
+ cerr << filename_ << ": rename: " << strerror(errno) << endl;
+ had_error = true;
+ }
+ }
+
+ if (had_error) {
+ // We had some sort of error so let's try to delete the temp file.
+ remove(temp_filename_.c_str());
+ directory_->set_had_error(true);
+ }
+}
+
// ===================================================================
CommandLineInterface::CommandLineInterface()
@@ -323,6 +561,10 @@ void CommandLineInterface::RegisterGenerator(const string& flag_name,
generators_[flag_name] = info;
}
+void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) {
+ plugin_prefix_ = exe_name_prefix;
+}
+
int CommandLineInterface::Run(int argc, const char* const argv[]) {
Clear();
if (!ParseArguments(argc, argv)) return 1;
@@ -346,7 +588,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
vector<const FileDescriptor*> parsed_files;
- // Parse each file and generate output.
+ // Parse each file.
for (int i = 0; i < input_files_.size(); i++) {
// Import the file.
const FileDescriptor* parsed_file = importer.Import(input_files_[i]);
@@ -359,13 +601,13 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
"--disallow_services was used." << endl;
return 1;
}
+ }
- if (mode_ == MODE_COMPILE) {
- // Generate output files.
- for (int i = 0; i < output_directives_.size(); i++) {
- if (!GenerateOutput(parsed_file, output_directives_[i])) {
- return 1;
- }
+ // Generate output.
+ if (mode_ == MODE_COMPILE) {
+ for (int i = 0; i < output_directives_.size(); i++) {
+ if (!GenerateOutput(parsed_files, output_directives_[i])) {
+ return 1;
}
}
}
@@ -686,10 +928,37 @@ bool CommandLineInterface::InterpretArgument(const string& name,
return false;
}
+ } else if (name == "--plugin") {
+ if (plugin_prefix_.empty()) {
+ cerr << "This compiler does not support plugins." << endl;
+ return false;
+ }
+
+ string name;
+ string path;
+
+ string::size_type equals_pos = value.find_first_of('=');
+ if (equals_pos == string::npos) {
+ // Use the basename of the file.
+ string::size_type slash_pos = value.find_last_of('/');
+ if (slash_pos == string::npos) {
+ name = value;
+ } else {
+ name = value.substr(slash_pos + 1);
+ }
+ path = value;
+ } else {
+ name = value.substr(0, equals_pos);
+ path = value.substr(equals_pos + 1);
+ }
+
+ plugins_[name] = path;
+
} else {
// Some other flag. Look it up in the generators list.
- GeneratorMap::const_iterator iter = generators_.find(name);
- if (iter == generators_.end()) {
+ const GeneratorInfo* generator_info = FindOrNull(generators_, name);
+ if (generator_info == NULL &&
+ (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) {
cerr << "Unknown flag: " << name << endl;
return false;
}
@@ -703,7 +972,11 @@ bool CommandLineInterface::InterpretArgument(const string& name,
OutputDirective directive;
directive.name = name;
- directive.generator = iter->second.generator;
+ if (generator_info == NULL) {
+ directive.generator = NULL;
+ } else {
+ directive.generator = generator_info->generator;
+ }
// Split value at ':' to separate the generator parameter from the
// filename. However, avoid doing this if the colon is part of a valid
@@ -755,6 +1028,17 @@ void CommandLineInterface::PrintHelpText() {
" --error_format=FORMAT Set the format in which to print errors.\n"
" FORMAT may be 'gcc' (the default) or 'msvs'\n"
" (Microsoft Visual Studio format)." << endl;
+ if (!plugin_prefix_.empty()) {
+ cerr <<
+" --plugin=EXECUTABLE Specifies a plugin executable to use.\n"
+" Normally, protoc searches the PATH for\n"
+" plugins, but you may specify additional\n"
+" executables not in the path using this flag.\n"
+" Additionally, EXECUTABLE may be of the form\n"
+" NAME=PATH, in which case the given plugin name\n"
+" is mapped to the given executable even if\n"
+" the executable's own name differs." << endl;
+ }
for (GeneratorMap::iterator iter = generators_.begin();
iter != generators_.end(); ++iter) {
@@ -768,7 +1052,7 @@ void CommandLineInterface::PrintHelpText() {
}
bool CommandLineInterface::GenerateOutput(
- const FileDescriptor* parsed_file,
+ const vector<const FileDescriptor*>& parsed_files,
const OutputDirective& output_directive) {
// Create the output directory.
DiskOutputDirectory output_directory(output_directive.output_location);
@@ -780,12 +1064,34 @@ bool CommandLineInterface::GenerateOutput(
// Call the generator.
string error;
- if (!output_directive.generator->Generate(
- parsed_file, output_directive.parameter, &output_directory, &error)) {
- // Generator returned an error.
- cerr << parsed_file->name() << ": " << output_directive.name << ": "
- << error << endl;
- return false;
+ if (output_directive.generator == NULL) {
+ // This is a plugin.
+ GOOGLE_CHECK(HasPrefixString(output_directive.name, "--") &&
+ HasSuffixString(output_directive.name, "_out"))
+ << "Bad name for plugin generator: " << output_directive.name;
+
+ // Strip the "--" and "_out" and add the plugin prefix.
+ string plugin_name = plugin_prefix_ + "gen-" +
+ output_directive.name.substr(2, output_directive.name.size() - 6);
+
+ if (!GeneratePluginOutput(parsed_files, plugin_name,
+ output_directive.parameter,
+ &output_directory, &error)) {
+ cerr << output_directive.name << ": " << error << endl;
+ return false;
+ }
+ } else {
+ // Regular generator.
+ for (int i = 0; i < parsed_files.size(); i++) {
+ if (!output_directive.generator->Generate(
+ parsed_files[i], output_directive.parameter,
+ &output_directory, &error)) {
+ // Generator returned an error.
+ cerr << output_directive.name << ": " << parsed_files[i]->name() << ": "
+ << error << endl;
+ return false;
+ }
+ }
}
// Check for write errors.
@@ -796,6 +1102,84 @@ bool CommandLineInterface::GenerateOutput(
return true;
}
+bool CommandLineInterface::GeneratePluginOutput(
+ const vector<const FileDescriptor*>& parsed_files,
+ const string& plugin_name,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error) {
+ CodeGeneratorRequest request;
+ CodeGeneratorResponse response;
+
+ // Build the request.
+ if (!parameter.empty()) {
+ request.set_parameter(parameter);
+ }
+
+ set<const FileDescriptor*> already_seen;
+ for (int i = 0; i < parsed_files.size(); i++) {
+ request.add_file_to_generate(parsed_files[i]->name());
+ GetTransitiveDependencies(parsed_files[i], &already_seen,
+ request.mutable_proto_file());
+ }
+
+ // Invoke the plugin.
+ Subprocess subprocess;
+
+ if (plugins_.count(plugin_name) > 0) {
+ subprocess.Start(plugins_[plugin_name], Subprocess::EXACT_NAME);
+ } else {
+ subprocess.Start(plugin_name, Subprocess::SEARCH_PATH);
+ }
+
+ string communicate_error;
+ if (!subprocess.Communicate(request, &response, &communicate_error)) {
+ *error = strings::Substitute("$0: $1", plugin_name, communicate_error);
+ return false;
+ }
+
+ // Write the files. We do this even if there was a generator error in order
+ // to match the behavior of a compiled-in generator.
+ scoped_ptr<io::ZeroCopyOutputStream> current_output;
+ for (int i = 0; i < response.file_size(); i++) {
+ const CodeGeneratorResponse::File& output_file = response.file(i);
+
+ if (!output_file.insertion_point().empty()) {
+ // Open a file for insert.
+ // We reset current_output to NULL first so that the old file is closed
+ // before the new one is opened.
+ current_output.reset();
+ current_output.reset(output_directory->OpenForInsert(
+ output_file.name(), output_file.insertion_point()));
+ } else if (!output_file.name().empty()) {
+ // Starting a new file. Open it.
+ // We reset current_output to NULL first so that the old file is closed
+ // before the new one is opened.
+ current_output.reset();
+ current_output.reset(output_directory->Open(output_file.name()));
+ } else if (current_output == NULL) {
+ *error = strings::Substitute(
+ "$0: First file chunk returned by plugin did not specify a file name.",
+ plugin_name);
+ return false;
+ }
+
+ // Use CodedOutputStream for convenience; otherwise we'd need to provide
+ // our own buffer-copying loop.
+ io::CodedOutputStream writer(current_output.get());
+ writer.WriteString(output_file.content());
+ }
+
+ // Check for errors.
+ if (!response.error().empty()) {
+ // Generator returned an error.
+ *error = response.error();
+ return false;
+ }
+
+ return true;
+}
+
bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
// Look up the type.
const Descriptor* type = pool->FindMessageTypeByName(codec_type_);
@@ -862,22 +1246,16 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
bool CommandLineInterface::WriteDescriptorSet(
const vector<const FileDescriptor*> parsed_files) {
FileDescriptorSet file_set;
- set<const FileDescriptor*> already_added;
- vector<const FileDescriptor*> to_add(parsed_files);
-
- while (!to_add.empty()) {
- const FileDescriptor* file = to_add.back();
- to_add.pop_back();
- if (already_added.insert(file).second) {
- // This file was not already in the set.
- file->CopyTo(file_set.add_file());
-
- if (imports_in_descriptor_set_) {
- // Add all of this file's dependencies.
- for (int i = 0; i < file->dependency_count(); i++) {
- to_add.push_back(file->dependency(i));
- }
- }
+
+ if (imports_in_descriptor_set_) {
+ set<const FileDescriptor*> already_seen;
+ for (int i = 0; i < parsed_files.size(); i++) {
+ GetTransitiveDependencies(
+ parsed_files[i], &already_seen, file_set.mutable_file());
+ }
+ } else {
+ for (int i = 0; i < parsed_files.size(); i++) {
+ parsed_files[i]->CopyTo(file_set.add_file());
}
}
@@ -906,6 +1284,24 @@ bool CommandLineInterface::WriteDescriptorSet(
return true;
}
+void CommandLineInterface::GetTransitiveDependencies(
+ const FileDescriptor* file,
+ set<const FileDescriptor*>* already_seen,
+ RepeatedPtrField<FileDescriptorProto>* output) {
+ if (!already_seen->insert(file).second) {
+ // Already saw this file. Skip.
+ return;
+ }
+
+ // Add all dependencies.
+ for (int i = 0; i < file->dependency_count(); i++) {
+ GetTransitiveDependencies(file->dependency(i), already_seen, output);
+ }
+
+ // Add this file.
+ file->CopyTo(output->Add());
+}
+
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index ec658636..1070a83b 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -50,10 +50,13 @@ namespace protobuf {
class FileDescriptor; // descriptor.h
class DescriptorPool; // descriptor.h
+class FileDescriptorProto; // descriptor.pb.h
+template<typename T> class RepeatedPtrField; // repeated_field.h
namespace compiler {
class CodeGenerator; // code_generator.h
+class OutputDirectory; // code_generator.h
class DiskSourceTree; // importer.h
// This class implements the command-line interface to the protocol compiler.
@@ -109,6 +112,37 @@ class LIBPROTOC_EXPORT CommandLineInterface {
CodeGenerator* generator,
const string& help_text);
+ // Enables "plugins". In this mode, if a command-line flag ends with "_out"
+ // but does not match any registered generator, the compiler will attempt to
+ // find a "plugin" to implement the generator. Plugins are just executables.
+ // They should live somewhere in the PATH.
+ //
+ // The compiler determines the executable name to search for by concatenating
+ // exe_name_prefix with the unrecognized flag name, removing "_out". So, for
+ // example, if exe_name_prefix is "protoc-" and you pass the flag --foo_out,
+ // the compiler will try to run the program "protoc-foo".
+ //
+ // The plugin program should implement the following usage:
+ // plugin [--out=OUTDIR] [--parameter=PARAMETER] PROTO_FILES < DESCRIPTORS
+ // --out indicates the output directory (as passed to the --foo_out
+ // parameter); if omitted, the current directory should be used. --parameter
+ // gives the generator parameter, if any was provided. The PROTO_FILES list
+ // the .proto files which were given on the compiler command-line; these are
+ // the files for which the plugin is expected to generate output code.
+ // Finally, DESCRIPTORS is an encoded FileDescriptorSet (as defined in
+ // descriptor.proto). This is piped to the plugin's stdin. The set will
+ // include descriptors for all the files listed in PROTO_FILES as well as
+ // all files that they import. The plugin MUST NOT attempt to read the
+ // PROTO_FILES directly -- it must use the FileDescriptorSet.
+ //
+ // The plugin should generate whatever files are necessary, as code generators
+ // normally do. It should write the names of all files it generates to
+ // stdout. The names should be relative to the output directory, NOT absolute
+ // names or relative to the current directory. If any errors occur, error
+ // messages should be written to stderr. If an error is fatal, the plugin
+ // should exit with a non-zero exit code.
+ void AllowPlugins(const string& exe_name_prefix);
+
// Run the Protocol Compiler with the given command-line parameters.
// Returns the error code which should be returned by main().
//
@@ -142,6 +176,7 @@ class LIBPROTOC_EXPORT CommandLineInterface {
class ErrorPrinter;
class DiskOutputDirectory;
class ErrorReportingFileOutput;
+ class InsertionOutputStream;
// Clear state from previous Run().
void Clear();
@@ -176,8 +211,13 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// Generate the given output file from the given input.
struct OutputDirective; // see below
- bool GenerateOutput(const FileDescriptor* proto_file,
+ bool GenerateOutput(const vector<const FileDescriptor*>& parsed_files,
const OutputDirective& output_directive);
+ bool GeneratePluginOutput(const vector<const FileDescriptor*>& parsed_files,
+ const string& plugin_name,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error);
// Implements --encode and --decode.
bool EncodeOrDecode(const DescriptorPool* pool);
@@ -185,6 +225,17 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// Implements the --descriptor_set_out option.
bool WriteDescriptorSet(const vector<const FileDescriptor*> parsed_files);
+ // Get all transitive dependencies of the given file (including the file
+ // itself), adding them to the given list of FileDescriptorProtos. The
+ // protos will be ordered such that every file is listed before any file that
+ // depends on it, so that you can call DescriptorPool::BuildFile() on them
+ // in order. Any files in *already_seen will not be added, and each file
+ // added will be inserted into *already_seen.
+ static void GetTransitiveDependencies(
+ const FileDescriptor* file,
+ set<const FileDescriptor*>* already_seen,
+ RepeatedPtrField<FileDescriptorProto>* output);
+
// -----------------------------------------------------------------
// The name of the executable as invoked (i.e. argv[0]).
@@ -201,6 +252,14 @@ class LIBPROTOC_EXPORT CommandLineInterface {
typedef map<string, GeneratorInfo> GeneratorMap;
GeneratorMap generators_;
+ // See AllowPlugins(). If this is empty, plugins aren't allowed.
+ string plugin_prefix_;
+
+ // Maps specific plugin names to files. When executing a plugin, this map
+ // is searched first to find the plugin executable. If not found here, the
+ // PATH (or other OS-specific search strategy) is searched.
+ map<string, string> plugins_;
+
// Stuff parsed from command line.
enum Mode {
MODE_COMPILE, // Normal mode: parse .proto files and compile them.
@@ -223,8 +282,8 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// output_directives_ lists all the files we are supposed to output and what
// generator to use for each.
struct OutputDirective {
- string name;
- CodeGenerator* generator;
+ string name; // E.g. "--foo_out"
+ CodeGenerator* generator; // NULL for plugins
string parameter;
string output_location;
};
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 9da41c02..83850cf9 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -47,10 +47,12 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/mock_code_generator.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
@@ -83,28 +85,19 @@ class CommandLineInterfaceTest : public testing::Test {
// -----------------------------------------------------------------
// Methods to set up the test (called before Run()).
- class MockCodeGenerator;
class NullCodeGenerator;
- // Registers a MockCodeGenerator with the given name.
- MockCodeGenerator* RegisterGenerator(const string& generator_name,
- const string& flag_name,
- const string& filename,
- const string& help_text);
- MockCodeGenerator* RegisterErrorGenerator(const string& generator_name,
- const string& error_text,
- const string& flag_name,
- const string& filename,
- const string& help_text);
-
- // Registers a CodeGenerator which will not actually generate anything,
- // but records the parameter passed to the generator.
- NullCodeGenerator* RegisterNullGenerator(const string& flag_name);
+ // Normally plugins are allowed for all tests. Call this to explicitly
+ // disable them.
+ void DisallowPlugins() { disallow_plugins_ = true; }
// Create a temp file within temp_directory_ with the given name.
// The containing directory is also created if necessary.
void CreateTempFile(const string& name, const string& contents);
+ // Create a subdirectory within temp_directory_.
+ void CreateTempDir(const string& name);
+
void SetInputsAreProtoPathRelative(bool enable) {
cli_.SetInputsAreProtoPathRelative(enable);
}
@@ -130,7 +123,8 @@ class CommandLineInterfaceTest : public testing::Test {
bool HasAlternateErrorSubstring(const string& expected_substring);
// Checks that MockCodeGenerator::Generate() was called in the given
- // context. That is, this tests if the generator with the given name
+ // context (or the generator in test_plugin.cc, which produces the same
+ // output). That is, this tests if the generator with the given name
// was called with the given parameter and proto file and produced the
// given output file. This is checked by reading the output file and
// checking that it contains the content that MockCodeGenerator would
@@ -140,8 +134,17 @@ class CommandLineInterfaceTest : public testing::Test {
void ExpectGenerated(const string& generator_name,
const string& parameter,
const string& proto_name,
+ const string& message_name);
+ void ExpectGenerated(const string& generator_name,
+ const string& parameter,
+ const string& proto_name,
const string& message_name,
- const string& output_file);
+ const string& output_directory);
+ void ExpectGeneratedWithInsertions(const string& generator_name,
+ const string& parameter,
+ const string& insertions,
+ const string& proto_name,
+ const string& message_name);
void ReadDescriptorSet(const string& filename,
FileDescriptorSet* descriptor_set);
@@ -150,6 +153,9 @@ class CommandLineInterfaceTest : public testing::Test {
// The object we are testing.
CommandLineInterface cli_;
+ // Was DisallowPlugins() called?
+ bool disallow_plugins_;
+
// We create a directory within TestTempDir() in order to add extra
// protection against accidentally deleting user files (since we recursively
// delete this directory during the test). This is the full path of that
@@ -166,40 +172,6 @@ class CommandLineInterfaceTest : public testing::Test {
vector<CodeGenerator*> mock_generators_to_delete_;
};
-// A mock CodeGenerator which outputs information about the context in which
-// it was called, which can then be checked. Output is written to a filename
-// constructed by concatenating the filename_prefix (given to the constructor)
-// with the proto file name, separated by a '.'.
-class CommandLineInterfaceTest::MockCodeGenerator : public CodeGenerator {
- public:
- // Create a MockCodeGenerator whose Generate() method returns true.
- MockCodeGenerator(const string& name, const string& filename_prefix);
-
- // Create a MockCodeGenerator whose Generate() method returns false
- // and sets the error string to the given string.
- MockCodeGenerator(const string& name, const string& filename_prefix,
- const string& error);
-
- ~MockCodeGenerator();
-
- void set_expect_write_error(bool value) {
- expect_write_error_ = value;
- }
-
- // implements CodeGenerator ----------------------------------------
- bool Generate(const FileDescriptor* file,
- const string& parameter,
- OutputDirectory* output_directory,
- string* error) const;
-
- private:
- string name_;
- string filename_prefix_;
- bool return_error_;
- string error_;
- bool expect_write_error_;
-};
-
class CommandLineInterfaceTest::NullCodeGenerator : public CodeGenerator {
public:
NullCodeGenerator() : called_(false) {}
@@ -237,6 +209,22 @@ void CommandLineInterfaceTest::SetUp() {
// Create the temp directory.
GOOGLE_CHECK(File::CreateDir(temp_directory_.c_str(), DEFAULT_FILE_MODE));
+
+ // Register generators.
+ CodeGenerator* generator = new MockCodeGenerator("test_generator");
+ mock_generators_to_delete_.push_back(generator);
+ cli_.RegisterGenerator("--test_out", generator, "Test output.");
+ cli_.RegisterGenerator("-t", generator, "Test output.");
+
+ generator = new MockCodeGenerator("alt_generator");
+ mock_generators_to_delete_.push_back(generator);
+ cli_.RegisterGenerator("--alt_out", generator, "Alt output.");
+
+ generator = new NullCodeGenerator();
+ mock_generators_to_delete_.push_back(generator);
+ cli_.RegisterGenerator("--null_out", generator, "Null output.");
+
+ disallow_plugins_ = false;
}
void CommandLineInterfaceTest::TearDown() {
@@ -254,6 +242,11 @@ void CommandLineInterfaceTest::Run(const string& command) {
vector<string> args;
SplitStringUsing(command, " ", &args);
+ if (!disallow_plugins_) {
+ cli_.AllowPlugins("prefix-");
+ args.push_back("--plugin=prefix-gen-plug=test_plugin");
+ }
+
scoped_array<const char*> argv(new const char*[args.size()]);
for (int i = 0; i < args.size(); i++) {
@@ -270,44 +263,6 @@ void CommandLineInterfaceTest::Run(const string& command) {
// -------------------------------------------------------------------
-CommandLineInterfaceTest::MockCodeGenerator*
-CommandLineInterfaceTest::RegisterGenerator(
- const string& generator_name,
- const string& flag_name,
- const string& filename,
- const string& help_text) {
- MockCodeGenerator* generator =
- new MockCodeGenerator(generator_name, filename);
- mock_generators_to_delete_.push_back(generator);
-
- cli_.RegisterGenerator(flag_name, generator, help_text);
- return generator;
-}
-
-CommandLineInterfaceTest::MockCodeGenerator*
-CommandLineInterfaceTest::RegisterErrorGenerator(
- const string& generator_name,
- const string& error_text,
- const string& flag_name,
- const string& filename_prefix,
- const string& help_text) {
- MockCodeGenerator* generator =
- new MockCodeGenerator(generator_name, filename_prefix, error_text);
- mock_generators_to_delete_.push_back(generator);
-
- cli_.RegisterGenerator(flag_name, generator, help_text);
- return generator;
-}
-
-CommandLineInterfaceTest::NullCodeGenerator*
-CommandLineInterfaceTest::RegisterNullGenerator(
- const string& flag_name) {
- NullCodeGenerator* generator = new NullCodeGenerator;
- mock_generators_to_delete_.push_back(generator);
- cli_.RegisterGenerator(flag_name, generator, "");
- return generator;
-}
-
void CommandLineInterfaceTest::CreateTempFile(
const string& name,
const string& contents) {
@@ -323,6 +278,10 @@ void CommandLineInterfaceTest::CreateTempFile(
File::WriteStringToFileOrDie(contents, full_name);
}
+void CommandLineInterfaceTest::CreateTempDir(const string& name) {
+ File::RecursivelyCreateDir(temp_directory_ + "/" + name, 0777);
+}
+
// -------------------------------------------------------------------
void CommandLineInterfaceTest::ExpectNoErrors() {
@@ -352,21 +311,31 @@ void CommandLineInterfaceTest::ExpectGenerated(
const string& generator_name,
const string& parameter,
const string& proto_name,
+ const string& message_name) {
+ MockCodeGenerator::ExpectGenerated(
+ generator_name, parameter, "", proto_name, message_name, temp_directory_);
+}
+
+void CommandLineInterfaceTest::ExpectGenerated(
+ const string& generator_name,
+ const string& parameter,
+ const string& proto_name,
const string& message_name,
- const string& output_file_prefix) {
- // Open and read the file.
- string output_file = output_file_prefix + "." + proto_name;
- string file_contents;
- ASSERT_TRUE(File::ReadFileToString(temp_directory_ + "/" + output_file,
- &file_contents))
- << "Failed to open file: " + output_file;
+ const string& output_directory) {
+ MockCodeGenerator::ExpectGenerated(
+ generator_name, parameter, "", proto_name, message_name,
+ temp_directory_ + "/" + output_directory);
+}
- // Check that the contents are as we expect.
- string expected_contents =
- generator_name + ": " + parameter + ", " + proto_name + ", " +
- message_name + "\n";
- EXPECT_EQ(expected_contents, file_contents)
- << "Output file did not have expected contents: " + output_file;
+void CommandLineInterfaceTest::ExpectGeneratedWithInsertions(
+ const string& generator_name,
+ const string& parameter,
+ const string& insertions,
+ const string& proto_name,
+ const string& message_name) {
+ MockCodeGenerator::ExpectGenerated(
+ generator_name, parameter, insertions, proto_name, message_name,
+ temp_directory_);
}
void CommandLineInterfaceTest::ReadDescriptorSet(
@@ -383,77 +352,52 @@ void CommandLineInterfaceTest::ReadDescriptorSet(
// ===================================================================
-CommandLineInterfaceTest::MockCodeGenerator::MockCodeGenerator(
- const string& name, const string& filename_prefix)
- : name_(name),
- filename_prefix_(filename_prefix),
- return_error_(false),
- expect_write_error_(false) {
-}
-
-CommandLineInterfaceTest::MockCodeGenerator::MockCodeGenerator(
- const string& name, const string& filename_prefix, const string& error)
- : name_(name),
- filename_prefix_(filename_prefix),
- return_error_(true),
- error_(error),
- expect_write_error_(false) {
-}
+TEST_F(CommandLineInterfaceTest, BasicOutput) {
+ // Test that the common case works.
-CommandLineInterfaceTest::MockCodeGenerator::~MockCodeGenerator() {}
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
-bool CommandLineInterfaceTest::MockCodeGenerator::Generate(
- const FileDescriptor* file,
- const string& parameter,
- OutputDirectory* output_directory,
- string* error) const {
- scoped_ptr<io::ZeroCopyOutputStream> output(
- output_directory->Open(filename_prefix_ + "." + file->name()));
- io::Printer printer(output.get(), '$');
- map<string, string> vars;
- vars["name"] = name_;
- vars["parameter"] = parameter;
- vars["proto_name"] = file->name();
- vars["message_name"] = file->message_type_count() > 0 ?
- file->message_type(0)->full_name().c_str() : "(none)";
-
- printer.Print(vars, "$name$: $parameter$, $proto_name$, $message_name$\n");
-
- if (expect_write_error_) {
- EXPECT_TRUE(printer.failed());
- } else {
- EXPECT_FALSE(printer.failed());
- }
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
- *error = error_;
- return !return_error_;
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
-// ===================================================================
+TEST_F(CommandLineInterfaceTest, BasicPlugin) {
+ // Test that basic plugins work.
-TEST_F(CommandLineInterfaceTest, BasicOutput) {
- // Test that the common case works.
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
+ Run("protocol_compiler --plug_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorAndPlugin) {
+ // Invoke a generator and a plugin at the same time.
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
- Run("protocol_compiler --test_out=$tmpdir "
+ Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+ ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, MultipleInputs) {
// Test parsing multiple input files.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -461,48 +405,68 @@ TEST_F(CommandLineInterfaceTest, MultipleInputs) {
"syntax = \"proto2\";\n"
"message Bar {}\n");
- Run("protocol_compiler --test_out=$tmpdir "
+ Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
"--proto_path=$tmpdir foo.proto bar.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
- ExpectGenerated("test_generator", "", "bar.proto", "Bar", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+ ExpectGenerated("test_generator", "", "bar.proto", "Bar");
}
TEST_F(CommandLineInterfaceTest, CreateDirectory) {
// Test that when we output to a sub-directory, it is created.
- RegisterGenerator("test_generator", "--test_out",
- "bar/baz/output.test", "Test output.");
-
- CreateTempFile("foo.proto",
+ CreateTempFile("bar/baz/foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
+ CreateTempDir("out");
+ CreateTempDir("plugout");
- Run("protocol_compiler --test_out=$tmpdir "
- "--proto_path=$tmpdir foo.proto");
+ Run("protocol_compiler --test_out=$tmpdir/out --plug_out=$tmpdir/plugout "
+ "--proto_path=$tmpdir bar/baz/foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "",
- "foo.proto", "Foo", "bar/baz/output.test");
+ ExpectGenerated("test_generator", "", "bar/baz/foo.proto", "Foo", "out");
+ ExpectGenerated("test_plugin", "", "bar/baz/foo.proto", "Foo", "plugout");
}
TEST_F(CommandLineInterfaceTest, GeneratorParameters) {
// Test that generator parameters are correctly parsed from the command line.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
Run("protocol_compiler --test_out=TestParameter:$tmpdir "
+ "--plug_out=TestPluginParameter:$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectNoErrors();
+ ExpectGenerated("test_generator", "TestParameter", "foo.proto", "Foo");
+ ExpectGenerated("test_plugin", "TestPluginParameter", "foo.proto", "Foo");
+}
+
+TEST_F(CommandLineInterfaceTest, Insert) {
+ // Test running a generator that inserts code into another's output.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler "
+ "--test_out=TestParameter:$tmpdir "
+ "--plug_out=TestPluginParameter:$tmpdir "
+ "--test_out=insert=test_generator,test_plugin:$tmpdir "
+ "--plug_out=insert=test_generator,test_plugin:$tmpdir "
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "TestParameter",
- "foo.proto", "Foo", "output.test");
+ ExpectGeneratedWithInsertions(
+ "test_generator", "TestParameter", "test_generator,test_plugin",
+ "foo.proto", "Foo");
+ ExpectGeneratedWithInsertions(
+ "test_plugin", "TestPluginParameter", "test_generator,test_plugin",
+ "foo.proto", "Foo");
}
#if defined(_WIN32) || defined(__CYGWIN__)
@@ -510,12 +474,10 @@ TEST_F(CommandLineInterfaceTest, GeneratorParameters) {
TEST_F(CommandLineInterfaceTest, WindowsOutputPath) {
// Test that the output path can be a Windows-style path.
- NullCodeGenerator* generator = RegisterNullGenerator("--test_out");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n");
- Run("protocol_compiler --test_out=C:\\ "
+ Run("protocol_compiler --null_out=C:\\ "
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
@@ -526,12 +488,10 @@ TEST_F(CommandLineInterfaceTest, WindowsOutputPath) {
TEST_F(CommandLineInterfaceTest, WindowsOutputPathAndParameter) {
// Test that we can have a windows-style output path and a parameter.
- NullCodeGenerator* generator = RegisterNullGenerator("--test_out");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n");
- Run("protocol_compiler --test_out=bar:C:\\ "
+ Run("protocol_compiler --null_out=bar:C:\\ "
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
@@ -543,9 +503,6 @@ TEST_F(CommandLineInterfaceTest, TrailingBackslash) {
// Test that the directories can end in backslashes. Some users claim this
// doesn't work on their system.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -554,7 +511,7 @@ TEST_F(CommandLineInterfaceTest, TrailingBackslash) {
"--proto_path=$tmpdir\\ foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
#endif // defined(_WIN32) || defined(__CYGWIN__)
@@ -562,9 +519,6 @@ TEST_F(CommandLineInterfaceTest, TrailingBackslash) {
TEST_F(CommandLineInterfaceTest, PathLookup) {
// Test that specifying multiple directories in the proto search path works.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("b/bar.proto",
"syntax = \"proto2\";\n"
"message Bar {}\n");
@@ -580,15 +534,12 @@ TEST_F(CommandLineInterfaceTest, PathLookup) {
"--proto_path=$tmpdir/a --proto_path=$tmpdir/b foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, ColonDelimitedPath) {
// Same as PathLookup, but we provide the proto_path in a single flag.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("b/bar.proto",
"syntax = \"proto2\";\n"
"message Bar {}\n");
@@ -613,15 +564,12 @@ TEST_F(CommandLineInterfaceTest, ColonDelimitedPath) {
#undef PATH_SEPARATOR
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, NonRootMapping) {
// Test setting up a search path mapping a directory to a non-root location.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -630,42 +578,34 @@ TEST_F(CommandLineInterfaceTest, NonRootMapping) {
"--proto_path=bar=$tmpdir bar/foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "bar/foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "bar/foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, MultipleGenerators) {
// Test that we can have multiple generators and use both in one invocation,
// each with a different output directory.
- RegisterGenerator("test_generator_1", "--test1_out",
- "output1.test", "Test output 1.");
- RegisterGenerator("test_generator_2", "--test2_out",
- "output2.test", "Test output 2.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
// Create the "a" and "b" sub-directories.
- CreateTempFile("a/dummy", "");
- CreateTempFile("b/dummy", "");
+ CreateTempDir("a");
+ CreateTempDir("b");
Run("protocol_compiler "
- "--test1_out=$tmpdir/a "
- "--test2_out=$tmpdir/b "
+ "--test_out=$tmpdir/a "
+ "--alt_out=$tmpdir/b "
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator_1", "", "foo.proto", "Foo", "a/output1.test");
- ExpectGenerated("test_generator_2", "", "foo.proto", "Foo", "b/output2.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo", "a");
+ ExpectGenerated("alt_generator", "", "foo.proto", "Foo", "b");
}
TEST_F(CommandLineInterfaceTest, DisallowServicesNoServices) {
// Test that --disallow_services doesn't cause a problem when there are no
// services.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -674,15 +614,12 @@ TEST_F(CommandLineInterfaceTest, DisallowServicesNoServices) {
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, DisallowServicesHasService) {
// Test that --disallow_services produces an error when there are services.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n"
@@ -697,9 +634,6 @@ TEST_F(CommandLineInterfaceTest, DisallowServicesHasService) {
TEST_F(CommandLineInterfaceTest, AllowServicesHasService) {
// Test that services work fine as long as --disallow_services is not used.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n"
@@ -709,7 +643,7 @@ TEST_F(CommandLineInterfaceTest, AllowServicesHasService) {
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) {
@@ -717,9 +651,6 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) {
SetInputsAreProtoPathRelative(false);
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -728,7 +659,7 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) {
"--proto_path=$tmpdir $tmpdir/foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) {
@@ -787,9 +718,6 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) {
TEST_F(CommandLineInterfaceTest, ParseErrors) {
// Test that parse errors are reported.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"badsyntax\n");
@@ -804,9 +732,6 @@ TEST_F(CommandLineInterfaceTest, ParseErrors) {
TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) {
// Test that parse errors are reported from multiple files.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
// We set up files such that foo.proto actually depends on bar.proto in
// two ways: Directly and through baz.proto. bar.proto's errors should
// only be reported once.
@@ -834,9 +759,6 @@ TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) {
TEST_F(CommandLineInterfaceTest, InputNotFoundError) {
// Test what happens if the input file is not found.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
Run("protocol_compiler --test_out=$tmpdir "
"--proto_path=$tmpdir foo.proto");
@@ -850,9 +772,6 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundError) {
SetInputsAreProtoPathRelative(false);
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
Run("protocol_compiler --test_out=$tmpdir "
"--proto_path=$tmpdir $tmpdir/foo.proto");
@@ -866,9 +785,6 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotMappedError) {
SetInputsAreProtoPathRelative(false);
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -895,9 +811,6 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundAndNotMappedError) {
SetInputsAreProtoPathRelative(false);
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
// Create a directory called "bar" so that we can point --proto_path at it.
CreateTempFile("bar/dummy", "");
@@ -914,9 +827,6 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputShadowedError) {
SetInputsAreProtoPathRelative(false);
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo/foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -938,9 +848,6 @@ TEST_F(CommandLineInterfaceTest, CwdRelativeInputShadowedError) {
TEST_F(CommandLineInterfaceTest, ProtoPathNotFoundError) {
// Test what happens if the input file is not found.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
Run("protocol_compiler --test_out=$tmpdir "
"--proto_path=$tmpdir/foo foo.proto");
@@ -952,9 +859,6 @@ TEST_F(CommandLineInterfaceTest, ProtoPathNotFoundError) {
TEST_F(CommandLineInterfaceTest, MissingInputError) {
// Test that we get an error if no inputs are given.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
Run("protocol_compiler --test_out=$tmpdir "
"--proto_path=$tmpdir");
@@ -962,9 +866,6 @@ TEST_F(CommandLineInterfaceTest, MissingInputError) {
}
TEST_F(CommandLineInterfaceTest, MissingOutputError) {
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -975,35 +876,56 @@ TEST_F(CommandLineInterfaceTest, MissingOutputError) {
}
TEST_F(CommandLineInterfaceTest, OutputWriteError) {
- MockCodeGenerator* generator =
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
- generator->set_expect_write_error(true);
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
+ string output_file =
+ MockCodeGenerator::GetOutputFileName("test_generator", "foo.proto");
+
// Create a directory blocking our output location.
- CreateTempFile("output.test.foo.proto/foo", "");
+ CreateTempDir(output_file);
Run("protocol_compiler --test_out=$tmpdir "
"--proto_path=$tmpdir foo.proto");
+ ExpectErrorSubstring("MockCodeGenerator detected write error.");
+
#if defined(_WIN32) && !defined(__CYGWIN__)
// Windows with MSVCRT.dll produces EPERM instead of EISDIR.
- if (HasAlternateErrorSubstring("output.test.foo.proto: Permission denied")) {
+ if (HasAlternateErrorSubstring(output_file + ": Permission denied")) {
return;
}
#endif
- ExpectErrorSubstring("output.test.foo.proto: Is a directory");
+ ExpectErrorSubstring(output_file + ": Is a directory");
}
-TEST_F(CommandLineInterfaceTest, OutputDirectoryNotFoundError) {
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
+TEST_F(CommandLineInterfaceTest, PluginOutputWriteError) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ string output_file =
+ MockCodeGenerator::GetOutputFileName("test_plugin", "foo.proto");
+
+ // Create a directory blocking our output location.
+ CreateTempDir(output_file);
+
+ Run("protocol_compiler --plug_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ // Windows with MSVCRT.dll produces EPERM instead of EISDIR.
+ if (HasAlternateErrorSubstring(output_file + ": Permission denied")) {
+ return;
+ }
+#endif
+
+ ExpectErrorSubstring(output_file + ": Is a directory");
+}
+TEST_F(CommandLineInterfaceTest, OutputDirectoryNotFoundError) {
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -1011,14 +933,21 @@ TEST_F(CommandLineInterfaceTest, OutputDirectoryNotFoundError) {
Run("protocol_compiler --test_out=$tmpdir/nosuchdir "
"--proto_path=$tmpdir foo.proto");
- ExpectErrorSubstring("nosuchdir/: "
- "No such file or directory");
+ ExpectErrorSubstring("nosuchdir/: No such file or directory");
}
-TEST_F(CommandLineInterfaceTest, OutputDirectoryIsFileError) {
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
+TEST_F(CommandLineInterfaceTest, PluginOutputDirectoryNotFoundError) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ Run("protocol_compiler --plug_out=$tmpdir/nosuchdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring("nosuchdir/: No such file or directory");
+}
+
+TEST_F(CommandLineInterfaceTest, OutputDirectoryIsFileError) {
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -1037,45 +966,109 @@ TEST_F(CommandLineInterfaceTest, OutputDirectoryIsFileError) {
}
TEST_F(CommandLineInterfaceTest, GeneratorError) {
- RegisterErrorGenerator("error_generator", "Test error message.",
- "--error_out", "output.test", "Test error output.");
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message MockCodeGenerator_Error {}\n");
+
+ Run("protocol_compiler --test_out=$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring(
+ "--test_out: foo.proto: Saw message type MockCodeGenerator_Error.");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginError) {
+ // Test a generator plugin that returns an error.
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
- "message Foo {}\n");
+ "message MockCodeGenerator_Error {}\n");
- Run("protocol_compiler --error_out=$tmpdir "
+ Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
"--proto_path=$tmpdir foo.proto");
- ExpectErrorSubstring("--error_out: Test error message.");
+ ExpectErrorSubstring(
+ "--plug_out: foo.proto: Saw message type MockCodeGenerator_Error.");
}
-TEST_F(CommandLineInterfaceTest, HelpText) {
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
- RegisterErrorGenerator("error_generator", "Test error message.",
- "--error_out", "output.test", "Test error output.");
+TEST_F(CommandLineInterfaceTest, GeneratorPluginFail) {
+ // Test a generator plugin that exits with an error code.
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
+ "message MockCodeGenerator_Exit {}\n");
+
+ Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring("Saw message type MockCodeGenerator_Exit.");
+ ExpectErrorSubstring(
+ "--plug_out: prefix-gen-plug: Plugin failed with status code 123.");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginCrash) {
+ // Test a generator plugin that crashes.
+
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message MockCodeGenerator_Abort {}\n");
+
+ Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+ "--proto_path=$tmpdir foo.proto");
+
+ ExpectErrorSubstring("Saw message type MockCodeGenerator_Abort.");
+
+ // Don't depend on the exact signal number.
+ ExpectErrorSubstring(
+ "--plug_out: prefix-gen-plug: Plugin killed by signal");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) {
+ // Test what happens if the plugin isn't found.
+
+ CreateTempFile("error.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+
+ Run("protocol_compiler --badplug_out=TestParameter:$tmpdir "
+ "--plugin=prefix-gen-badplug=no_such_file "
+ "--proto_path=$tmpdir error.proto");
+
+ ExpectErrorSubstring(
+ "no_such_file: program not found or is not executable");
+
+ ExpectErrorSubstring(
+ "--badplug_out: prefix-gen-badplug: Plugin failed with status code 1.");
+}
+
+TEST_F(CommandLineInterfaceTest, GeneratorPluginNotAllowed) {
+ // Test what happens if plugins aren't allowed.
+
+ CreateTempFile("error.proto",
+ "syntax = \"proto2\";\n"
"message Foo {}\n");
+ DisallowPlugins();
+ Run("protocol_compiler --plug_out=TestParameter:$tmpdir "
+ "--proto_path=$tmpdir error.proto");
+
+ ExpectErrorSubstring("Unknown flag: --plug_out");
+}
+
+TEST_F(CommandLineInterfaceTest, HelpText) {
Run("test_exec_name --help");
ExpectErrorSubstring("Usage: test_exec_name ");
ExpectErrorSubstring("--test_out=OUT_DIR");
ExpectErrorSubstring("Test output.");
- ExpectErrorSubstring("--error_out=OUT_DIR");
- ExpectErrorSubstring("Test error output.");
+ ExpectErrorSubstring("--alt_out=OUT_DIR");
+ ExpectErrorSubstring("Alt output.");
}
TEST_F(CommandLineInterfaceTest, GccFormatErrors) {
// Test --error_format=gcc (which is the default, but we want to verify
// that it can be set explicitly).
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"badsyntax\n");
@@ -1090,9 +1083,6 @@ TEST_F(CommandLineInterfaceTest, GccFormatErrors) {
TEST_F(CommandLineInterfaceTest, MsvsFormatErrors) {
// Test --error_format=msvs
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"badsyntax\n");
@@ -1108,9 +1098,6 @@ TEST_F(CommandLineInterfaceTest, MsvsFormatErrors) {
TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) {
// Test --error_format=msvs
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"badsyntax\n");
@@ -1128,9 +1115,6 @@ TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) {
TEST_F(CommandLineInterfaceTest, ParseSingleCharacterFlag) {
// Test that a single-character flag works.
- RegisterGenerator("test_generator", "-t",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -1139,15 +1123,12 @@ TEST_F(CommandLineInterfaceTest, ParseSingleCharacterFlag) {
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, ParseSpaceDelimitedValue) {
// Test that separating the flag value with a space works.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -1156,16 +1137,13 @@ TEST_F(CommandLineInterfaceTest, ParseSpaceDelimitedValue) {
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, ParseSingleCharacterSpaceDelimitedValue) {
// Test that separating the flag value with a space works for
// single-character flags.
- RegisterGenerator("test_generator", "-t",
- "output.test", "Test output.");
-
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
"message Foo {}\n");
@@ -1174,15 +1152,12 @@ TEST_F(CommandLineInterfaceTest, ParseSingleCharacterSpaceDelimitedValue) {
"--proto_path=$tmpdir foo.proto");
ExpectNoErrors();
- ExpectGenerated("test_generator", "", "foo.proto", "Foo", "output.test");
+ ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
TEST_F(CommandLineInterfaceTest, MissingValueError) {
// Test that we get an error if a flag is missing its value.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
Run("protocol_compiler --test_out --proto_path=$tmpdir foo.proto");
ExpectErrorText("Missing value for flag: --test_out\n");
@@ -1192,9 +1167,6 @@ TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) {
// Test that we get an error if the last argument is a flag requiring a
// value.
- RegisterGenerator("test_generator", "--test_out",
- "output.test", "Test output.");
-
Run("protocol_compiler --test_out");
ExpectErrorText("Missing value for flag: --test_out\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index a7bc35bd..30b1d2bf 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -123,8 +123,11 @@ TEST(BootstrapTest, GeneratedDescriptorMatches) {
Importer importer(&source_tree, &error_collector);
const FileDescriptor* proto_file =
importer.Import("google/protobuf/descriptor.proto");
+ const FileDescriptor* plugin_proto_file =
+ importer.Import("google/protobuf/compiler/plugin.proto");
EXPECT_EQ("", error_collector.text_);
ASSERT_TRUE(proto_file != NULL);
+ ASSERT_TRUE(plugin_proto_file != NULL);
CppGenerator generator;
MockOutputDirectory output_directory;
@@ -133,11 +136,18 @@ TEST(BootstrapTest, GeneratedDescriptorMatches) {
parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
ASSERT_TRUE(generator.Generate(proto_file, parameter,
&output_directory, &error));
+ parameter = "dllexport_decl=LIBPROTOC_EXPORT";
+ ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter,
+ &output_directory, &error));
output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.h",
"google/protobuf/descriptor.pb.h");
output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.cc",
"google/protobuf/descriptor.pb.cc");
+ output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h",
+ "google/protobuf/compiler/plugin.pb.h");
+ output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc",
+ "google/protobuf/compiler/plugin.pb.cc");
}
} // namespace
@@ -145,5 +155,4 @@ TEST(BootstrapTest, GeneratedDescriptorMatches) {
} // namespace cpp
} // namespace compiler
} // namespace protobuf
-
} // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 90e9172a..76d2b798 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -98,6 +98,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
"$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"
+ "const int $prefix$$short_name$_ARRAYSIZE = $prefix$$short_name$_MAX + 1;\n"
"\n");
if (HasDescriptorMethods(descriptor_->file())) {
@@ -149,17 +150,21 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
"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");
+ " $classname$_$nested_name$_MAX;\n"
+ "static const int $nested_name$_ARRAYSIZE =\n"
+ " $classname$_$nested_name$_ARRAYSIZE;\n");
if (HasDescriptorMethods(descriptor_->file())) {
printer->Print(vars,
"static inline const ::google::protobuf::EnumDescriptor*\n"
"$nested_name$_descriptor() {\n"
" return $classname$_descriptor();\n"
- "}\n"
+ "}\n");
+ printer->Print(vars,
"static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
" return $classname$_Name(value);\n"
- "}\n"
+ "}\n");
+ printer->Print(vars,
"static inline bool $nested_name$_Parse(const ::std::string& name,\n"
" $nested_name$* value) {\n"
" return $classname$_Parse(name, value);\n"
@@ -240,7 +245,8 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) {
}
printer->Print(vars,
"const $classname$ $parent$::$nested_name$_MIN;\n"
- "const $classname$ $parent$::$nested_name$_MAX;\n");
+ "const $classname$ $parent$::$nested_name$_MAX;\n"
+ "const int $parent$::$nested_name$_ARRAYSIZE;\n");
printer->Print("#endif // _MSC_VER\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 7ca11c8c..91ce493a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -114,7 +114,9 @@ void EnumFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"int value;\n"
- "DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n"
+ "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
+ " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
+ " input, &value)));\n"
"if ($type$_IsValid(value)) {\n"
" set_$name$(static_cast< $type$ >(value));\n");
if (HasUnknownFields(descriptor_->file())) {
@@ -170,24 +172,17 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
- "inline ::google::protobuf::RepeatedField<int>* 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");
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
+ "inline ::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n");
}
void RepeatedEnumFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField<int>&\n"
- "$classname$::$name$() const {\n"
- " return $name$_;\n"
- "}\n"
- "inline ::google::protobuf::RepeatedField<int>*\n"
- "$classname$::mutable_$name$() {\n"
- " return &$name$_;\n"
- "}\n"
"inline $type$ $classname$::$name$(int index) const {\n"
" return static_cast< $type$ >($name$_.Get(index));\n"
"}\n"
@@ -199,6 +194,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" GOOGLE_DCHECK($type$_IsValid(value));\n"
" $name$_.Add(value);\n"
"}\n");
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedField<int>&\n"
+ "$classname$::$name$() const {\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline ::google::protobuf::RepeatedField<int>*\n"
+ "$classname$::mutable_$name$() {\n"
+ " return &$name$_;\n"
+ "}\n");
}
void RepeatedEnumFieldGenerator::
@@ -223,7 +227,33 @@ GenerateConstructorCode(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
+ // Don't use ReadRepeatedPrimitive here so that the enum can be validated.
+ printer->Print(variables_,
+ "int value;\n"
+ "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
+ " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
+ " input, &value)));\n"
+ "if ($type$_IsValid(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("}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
+ if (!descriptor_->options().packed()) {
+ // We use a non-inlined implementation in this case, since this path will
+ // rarely be executed.
+ printer->Print(variables_,
+ "DO_((::google::protobuf::internal::WireFormatLite::ReadPackedEnumNoInline(\n"
+ " input,\n"
+ " &$type$_IsValid,\n"
+ " this->mutable_$name$())));\n");
+ } else {
printer->Print(variables_,
"::google::protobuf::uint32 length;\n"
"DO_(input->ReadVarint32(&length));\n"
@@ -231,25 +261,14 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"input->PushLimit(length);\n"
"while (input->BytesUntilLimit() > 0) {\n"
" int value;\n"
- " DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n"
+ " DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
+ " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
+ " input, &value)));\n"
" if ($type$_IsValid(value)) {\n"
" add_$name$(static_cast< $type$ >(value));\n"
" }\n"
"}\n"
"input->PopLimit(limit);\n");
- } else {
- printer->Print(variables_,
- "int value;\n"
- "DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n"
- "if ($type$_IsValid(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");
}
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index 20dd57bb..0793430c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -83,6 +83,7 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
+ void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc
index 7208ed3a..658a7077 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc
@@ -33,6 +33,7 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/cpp/cpp_extension.h>
+#include <map>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/printer.h>
@@ -43,6 +44,18 @@ namespace protobuf {
namespace compiler {
namespace cpp {
+namespace {
+
+// Returns the fully-qualified class name of the message that this field
+// extends. This function is used in the Google-internal code to handle some
+// legacy cases.
+string ExtendeeClassName(const FieldDescriptor* descriptor) {
+ const Descriptor* extendee = descriptor->containing_type();
+ return ClassName(extendee, true);
+}
+
+} // anonymous namespace
+
ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
const string& dllexport_decl)
: descriptor_(descriptor),
@@ -80,7 +93,7 @@ ExtensionGenerator::~ExtensionGenerator() {}
void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
map<string, string> vars;
- vars["extendee" ] = ClassName(descriptor_->containing_type(), true);
+ vars["extendee" ] = ExtendeeClassName(descriptor_);
vars["number" ] = SimpleItoa(descriptor_->number());
vars["type_traits" ] = type_traits_;
vars["name" ] = descriptor_->name();
@@ -106,6 +119,7 @@ void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
" ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
" $name$;\n"
);
+
}
void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
@@ -115,7 +129,7 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
string name = scope + descriptor_->name();
map<string, string> vars;
- vars["extendee" ] = ClassName(descriptor_->containing_type(), true);
+ vars["extendee" ] = ExtendeeClassName(descriptor_);
vars["type_traits" ] = type_traits_;
vars["name" ] = name;
vars["constant_name"] = FieldConstantName(descriptor_);
@@ -154,7 +168,7 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
map<string, string> vars;
- vars["extendee" ] = ClassName(descriptor_->containing_type(), true);
+ vars["extendee" ] = ExtendeeClassName(descriptor_);
vars["number" ] = SimpleItoa(descriptor_->number());
vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
vars["is_repeated"] = descriptor_->is_repeated() ? "true" : "false";
@@ -193,5 +207,4 @@ void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
} // namespace cpp
} // namespace compiler
} // namespace protobuf
-
} // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index c546e964..103cac4a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -40,6 +40,7 @@
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/wire_format.h>
+#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
@@ -61,11 +62,24 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
(*variables)["tag_size"] = SimpleItoa(
WireFormat::TagSize(descriptor->number(), descriptor->type()));
(*variables)["deprecation"] = descriptor->options().deprecated()
- ? " DEPRECATED_PROTOBUF_FIELD" : "";
+ ? " PROTOBUF_DEPRECATED" : "";
+
}
FieldGenerator::~FieldGenerator() {}
+void FieldGenerator::
+GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
+ // Reaching here indicates a bug. Cases are:
+ // - This FieldGenerator should support packing, but this method should be
+ // overridden.
+ // - This FieldGenerator doesn't support packing, and this method should
+ // never have been called.
+ GOOGLE_LOG(FATAL) << "GenerateMergeFromCodedStreamWithPacking() "
+ << "called on field generator that does not support packing.";
+
+}
+
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
: descriptor_(descriptor),
field_generators_(
@@ -82,7 +96,11 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
case FieldDescriptor::CPPTYPE_MESSAGE:
return new RepeatedMessageFieldGenerator(field);
case FieldDescriptor::CPPTYPE_STRING:
- return new RepeatedStringFieldGenerator(field);
+ switch (field->options().ctype()) {
+ default: // RepeatedStringFieldGenerator handles unknown ctypes.
+ case FieldOptions::STRING:
+ return new RepeatedStringFieldGenerator(field);
+ }
case FieldDescriptor::CPPTYPE_ENUM:
return new RepeatedEnumFieldGenerator(field);
default:
@@ -93,7 +111,11 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field) {
case FieldDescriptor::CPPTYPE_MESSAGE:
return new MessageFieldGenerator(field);
case FieldDescriptor::CPPTYPE_STRING:
- return new StringFieldGenerator(field);
+ switch (field->options().ctype()) {
+ default: // StringFieldGenerator handles unknown ctypes.
+ case FieldOptions::STRING:
+ return new StringFieldGenerator(field);
+ }
case FieldDescriptor::CPPTYPE_ENUM:
return new EnumFieldGenerator(field);
default:
@@ -110,6 +132,7 @@ const FieldGenerator& FieldGeneratorMap::get(
return *field_generators_[field->index()];
}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index 00ec2c7c..c303a337 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -118,6 +118,11 @@ class FieldGenerator {
// message's MergeFromCodedStream() method.
virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
+ // Generate lines to decode this field from a packed value, which will be
+ // placed inside the message's MergeFromCodedStream() method.
+ virtual void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer)
+ const;
+
// Generate lines to serialize this field, which are placed within the
// message's SerializeWithCachedSizes() method.
virtual void GenerateSerializeWithCachedSizes(io::Printer* printer) const = 0;
@@ -153,6 +158,7 @@ class FieldGeneratorMap {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
};
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 51859bb3..80da7e40 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/compiler/cpp/cpp_extension.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/compiler/cpp/cpp_message.h>
+#include <google/protobuf/compiler/cpp/cpp_field.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>
@@ -93,12 +94,14 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
// Generate top of header.
printer->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
"\n"
"#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
"#define PROTOBUF_$filename_identifier$__INCLUDED\n"
"\n"
"#include <string>\n"
"\n",
+ "filename", file_->name(),
"filename_identifier", filename_identifier);
printer->Print(
@@ -132,19 +135,23 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
if (HasDescriptorMethods(file_)) {
printer->Print(
"#include <google/protobuf/generated_message_reflection.h>\n");
+ }
- if (file_->service_count() > 0) {
- printer->Print(
- "#include <google/protobuf/service.h>\n");
- }
+ if (HasGenericServices(file_)) {
+ printer->Print(
+ "#include <google/protobuf/service.h>\n");
}
+
for (int i = 0; i < file_->dependency_count(); i++) {
printer->Print(
"#include \"$dependency$.pb.h\"\n",
"dependency", StripProto(file_->dependency(i)->name()));
}
+ printer->Print(
+ "// @@protoc_insertion_point(includes)\n");
+
// Open namespace.
GenerateNamespaceOpeners(printer);
@@ -198,7 +205,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
printer->Print(kThickSeparator);
printer->Print("\n");
- if (HasDescriptorMethods(file_)) {
+ if (HasGenericServices(file_)) {
// Generate service definitions.
for (int i = 0; i < file_->service_count(); i++) {
if (i > 0) {
@@ -232,6 +239,10 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
message_generators_[i]->GenerateInlineMethods(printer);
}
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n");
+
// Close up namespace.
GenerateNamespaceClosers(printer);
@@ -255,11 +266,15 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
printer->Print(
"\n"
"} // namespace google\n} // namespace protobuf\n"
- "#endif // SWIG\n"
- "\n");
+ "#endif // SWIG\n");
}
printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(global_scope)\n"
+ "\n");
+
+ printer->Print(
"#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
"filename_identifier", filename_identifier);
}
@@ -285,6 +300,9 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"#include <google/protobuf/wire_format.h>\n");
}
+ printer->Print(
+ "// @@protoc_insertion_point(includes)\n");
+
GenerateNamespaceOpeners(printer);
if (HasDescriptorMethods(file_)) {
@@ -300,10 +318,13 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"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());
+
+ if (HasGenericServices(file_)) {
+ 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(
@@ -329,7 +350,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
message_generators_[i]->GenerateClassMethods(printer);
}
- if (HasDescriptorMethods(file_)) {
+ if (HasGenericServices(file_)) {
// Generate services.
for (int i = 0; i < file_->service_count(); i++) {
if (i == 0) printer->Print("\n");
@@ -344,7 +365,15 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
extension_generators_[i]->GenerateDefinition(printer);
}
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n");
+
GenerateNamespaceClosers(printer);
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(global_scope)\n");
}
void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
@@ -397,8 +426,10 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
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);
+ if (HasGenericServices(file_)) {
+ for (int i = 0; i < file_->service_count(); i++) {
+ service_generators_[i]->GenerateDescriptorInitializer(printer, i);
+ }
}
printer->Outdent();
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 723a8b45..e3df88b0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -32,6 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <limits>
#include <vector>
#include <google/protobuf/stubs/hash.h>
@@ -40,6 +41,7 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
+
namespace google {
namespace protobuf {
namespace compiler {
@@ -111,6 +113,7 @@ const char kThinSeparator[] =
"// -------------------------------------------------------------------\n";
string ClassName(const Descriptor* descriptor, bool qualified) {
+
// Find "outer", the descriptor of the top-level message in which
// "descriptor" is embedded.
const Descriptor* outer = descriptor;
@@ -141,6 +144,12 @@ string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
}
}
+
+string SuperClassName(const Descriptor* descriptor) {
+ return HasDescriptorMethods(descriptor->file()) ?
+ "::google::protobuf::Message" : "::google::protobuf::MessageLite";
+}
+
string FieldName(const FieldDescriptor* field) {
string result = field->name();
LowerString(&result);
@@ -166,6 +175,12 @@ string FieldConstantName(const FieldDescriptor *field) {
return result;
}
+string FieldMessageTypeName(const FieldDescriptor* field) {
+ // Note: The Google-internal version of Protocol Buffers uses this function
+ // as a hook point for hacks to support legacy code.
+ return ClassName(field->message_type(), true);
+}
+
string StripProto(const string& filename) {
if (HasSuffixString(filename, ".protodevel")) {
return StripSuffixString(filename, ".protodevel");
@@ -235,17 +250,37 @@ string DefaultValue(const FieldDescriptor* field) {
return "GOOGLE_LONGLONG(" + SimpleItoa(field->default_value_int64()) + ")";
case FieldDescriptor::CPPTYPE_UINT64:
return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
- case FieldDescriptor::CPPTYPE_DOUBLE:
- return SimpleDtoa(field->default_value_double());
+ case FieldDescriptor::CPPTYPE_DOUBLE: {
+ double value = field->default_value_double();
+ if (value == numeric_limits<double>::infinity()) {
+ return "::google::protobuf::internal::Infinity()";
+ } else if (value == -numeric_limits<double>::infinity()) {
+ return "-::google::protobuf::internal::Infinity()";
+ } else if (value != value) {
+ return "::google::protobuf::internal::NaN()";
+ } else {
+ return SimpleDtoa(value);
+ }
+ }
case FieldDescriptor::CPPTYPE_FLOAT:
{
- // If floating point value contains a period (.) or an exponent (either
- // E or e), then append suffix 'f' to make it a floating-point literal.
- string float_value = SimpleFtoa(field->default_value_float());
- if (float_value.find_first_of(".eE") != string::npos) {
- float_value.push_back('f');
+ float value = field->default_value_float();
+ if (value == numeric_limits<float>::infinity()) {
+ return "static_cast<float>(::google::protobuf::internal::Infinity())";
+ } else if (value == -numeric_limits<float>::infinity()) {
+ return "static_cast<float>(-::google::protobuf::internal::Infinity())";
+ } else if (value != value) {
+ return "static_cast<float>(::google::protobuf::internal::NaN())";
+ } else {
+ string float_value = SimpleFtoa(value);
+ // If floating point value contains a period (.) or an exponent
+ // (either E or e), then append suffix 'f' to make it a float
+ // literal.
+ if (float_value.find_first_of(".eE") != string::npos) {
+ float_value.push_back('f');
+ }
+ return float_value;
}
- return float_value;
}
case FieldDescriptor::CPPTYPE_BOOL:
return field->default_value_bool() ? "true" : "false";
@@ -259,7 +294,7 @@ string DefaultValue(const FieldDescriptor* field) {
case FieldDescriptor::CPPTYPE_STRING:
return "\"" + CEscape(field->default_value_string()) + "\"";
case FieldDescriptor::CPPTYPE_MESSAGE:
- return ClassName(field->message_type(), true) + "::default_instance()";
+ return FieldMessageTypeName(field) + "::default_instance()";
}
// Can't actually get here; make compiler happy. (We could add a default
// case above but then we wouldn't get the nice compiler warning when a
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 83e12501..f99b5fe8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -60,6 +60,8 @@ extern const char kThinSeparator[];
string ClassName(const Descriptor* descriptor, bool qualified);
string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
+string SuperClassName(const Descriptor* descriptor);
+
// Get the (unqualified) name that should be used for this field in C++ code.
// The name is coerced to lower-case to emulate proto1 behavior. People
// should be using lowercase-with-underscores style for proto field names
@@ -77,6 +79,10 @@ inline const Descriptor* FieldScope(const FieldDescriptor* field) {
field->extension_scope() : field->containing_type();
}
+// Returns the fully-qualified type name field->message_type(). Usually this
+// is just ClassName(field->message_type(), true);
+string FieldMessageTypeName(const FieldDescriptor* field);
+
// Strips ".proto" or ".protodevel" from the end of a filename.
string StripProto(const string& filename);
@@ -107,33 +113,41 @@ string GlobalAssignDescriptorsName(const string& filename);
string GlobalShutdownFileName(const string& filename);
// Do message classes in this file keep track of unknown fields?
-inline const bool HasUnknownFields(const FileDescriptor *file) {
+inline 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) {
+inline 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) {
+inline bool HasDescriptorMethods(const FileDescriptor *file) {
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
}
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor *file) {
+ return file->service_count() > 0 &&
+ file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
+ file->options().cc_generic_services();
+}
+
// Should string fields in this file verify that their contents are UTF-8?
-inline const bool HasUtf8Verification(const FileDescriptor* file) {
+inline 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) {
+inline 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 eb836418..cbdcce8f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -308,11 +308,10 @@ GenerateClassDefinition(io::Printer* printer) {
} else {
vars["dllexport"] = dllexport_decl_ + " ";
}
- vars["superclass"] = HasDescriptorMethods(descriptor_->file()) ?
- "Message" : "MessageLite";
+ vars["superclass"] = SuperClassName(descriptor_);
printer->Print(vars,
- "class $dllexport$$classname$ : public ::google::protobuf::$superclass$ {\n"
+ "class $dllexport$$classname$ : public $superclass$ {\n"
" public:\n");
printer->Indent();
@@ -349,6 +348,10 @@ GenerateClassDefinition(io::Printer* printer) {
printer->Print(vars,
"static const $classname$& default_instance();\n"
+ "\n");
+
+
+ printer->Print(vars,
"void Swap($classname$* other);\n"
"\n"
"// implements Message ----------------------------------------------\n"
@@ -387,7 +390,7 @@ GenerateClassDefinition(io::Printer* printer) {
"private:\n"
"void SharedCtor();\n"
"void SharedDtor();\n"
- "void SetCachedSize(int size) const { _cached_size_ = size; }\n"
+ "void SetCachedSize(int size) const;\n"
"public:\n"
"\n");
@@ -436,6 +439,11 @@ GenerateClassDefinition(io::Printer* printer) {
extension_generators_[i]->GenerateDeclaration(printer);
}
+
+ printer->Print(
+ "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
// Generate private members for fields.
printer->Outdent();
printer->Print(" private:\n");
@@ -623,6 +631,7 @@ GenerateDefaultInstanceAllocator(io::Printer* printer) {
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
nested_generators_[i]->GenerateDefaultInstanceAllocator(printer);
}
+
}
void MessageGenerator::
@@ -751,6 +760,7 @@ GenerateClassMethods(io::Printer* printer) {
"classname", classname_,
"type_name", descriptor_->full_name());
}
+
}
void MessageGenerator::
@@ -833,9 +843,8 @@ GenerateSharedDestructorCode(io::Printer* printer) {
void MessageGenerator::
GenerateStructors(io::Printer* printer) {
- string superclass = HasDescriptorMethods(descriptor_->file()) ?
- "Message" : "MessageLite";
-
+ string superclass = SuperClassName(descriptor_);
+
// Generate the default constructor.
printer->Print(
"$classname$::$classname$()\n"
@@ -864,7 +873,7 @@ GenerateStructors(io::Printer* printer) {
printer->Print(
" $name$_ = const_cast< $type$*>(&$type$::default_instance());\n",
"name", FieldName(field),
- "type", ClassName(field->message_type(), true));
+ "type", FieldMessageTypeName(field));
}
}
printer->Print(
@@ -896,6 +905,15 @@ GenerateStructors(io::Printer* printer) {
// Generate the shared destructor code.
GenerateSharedDestructorCode(printer);
+ // Generate SetCachedSize.
+ printer->Print(
+ "void $classname$::SetCachedSize(int size) const {\n"
+ " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
+ " _cached_size_ = size;\n"
+ " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
+ "}\n",
+ "classname", classname_);
+
// Only generate this member if it's not disabled.
if (HasDescriptorMethods(descriptor_->file()) &&
!descriptor_->options().no_standard_descriptor_accessor()) {
@@ -924,6 +942,7 @@ GenerateStructors(io::Printer* printer) {
"classname", classname_,
"adddescriptorsname",
GlobalAddDescriptorsName(descriptor_->file()->name()));
+
}
void MessageGenerator::
@@ -1237,12 +1256,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
PrintFieldComment(printer, field);
printer->Print(
- "case $number$: {\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()),
+ "case $number$: {\n",
+ "number", SimpleItoa(field->number()));
+ printer->Indent();
+ const FieldGenerator& field_generator = field_generators_.get(field);
+
+ // Emit code to parse the common, expected case.
+ printer->Print(
+ "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n"
+ " ::google::protobuf::internal::WireFormatLite::WIRETYPE_$wiretype$) {\n",
"wiretype", kWireTypeNames[WireFormat::WireTypeForField(field)]);
if (i > 0 || (field->is_repeated() && !field->options().packed())) {
@@ -1252,8 +1274,38 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
}
printer->Indent();
+ if (field->options().packed()) {
+ field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
+ } else {
+ field_generator.GenerateMergeFromCodedStream(printer);
+ }
+ printer->Outdent();
- field_generators_.get(field).GenerateMergeFromCodedStream(printer);
+ // Emit code to parse unexpectedly packed or unpacked values.
+ if (field->is_packable() && field->options().packed()) {
+ printer->Print(
+ "} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n"
+ " == ::google::protobuf::internal::WireFormatLite::\n"
+ " WIRETYPE_$wiretype$) {\n",
+ "wiretype",
+ kWireTypeNames[WireFormat::WireTypeForFieldType(field->type())]);
+ printer->Indent();
+ field_generator.GenerateMergeFromCodedStream(printer);
+ printer->Outdent();
+ } else if (field->is_packable() && !field->options().packed()) {
+ printer->Print(
+ "} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n"
+ " == ::google::protobuf::internal::WireFormatLite::\n"
+ " WIRETYPE_LENGTH_DELIMITED) {\n");
+ printer->Indent();
+ field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
+ printer->Outdent();
+ }
+
+ printer->Print(
+ "} else {\n"
+ " goto handle_uninterpreted;\n"
+ "}\n");
// switch() is slow since it can't be predicted well. Insert some if()s
// here that attempt to predict the next tag.
@@ -1434,18 +1486,6 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) {
"classname", classname_);
printer->Indent();
- 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();
@@ -1555,7 +1595,9 @@ GenerateByteSize(io::Printer* printer) {
" ComputeUnknownMessageSetItemsSize(unknown_fields());\n");
}
printer->Print(
+ " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
" _cached_size_ = total_size;\n"
+ " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
" return total_size;\n"
"}\n");
return;
@@ -1647,7 +1689,9 @@ GenerateByteSize(io::Printer* printer) {
// exact same value, it works on all common processors. In a future version
// of C++, _cached_size_ should be made into an atomic<int>.
printer->Print(
+ "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
"_cached_size_ = total_size;\n"
+ "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
"return total_size;\n");
printer->Outdent();
@@ -1719,6 +1763,7 @@ GenerateIsInitialized(io::Printer* printer) {
"}\n");
}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index f1c57141..04778f6d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -150,6 +150,7 @@ class MessageGenerator {
io::Printer* printer, const Descriptor::ExtensionRange* range,
bool unbounded);
+
const Descriptor* descriptor_;
string classname_;
string dllexport_decl_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index 059fba6e..c04bdc66 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -47,7 +47,11 @@ namespace {
void SetMessageVariables(const FieldDescriptor* descriptor,
map<string, string>* variables) {
SetCommonFieldVariables(descriptor, variables);
- (*variables)["type"] = ClassName(descriptor->message_type(), true);
+ (*variables)["type"] = FieldMessageTypeName(descriptor);
+ (*variables)["stream_writer"] = (*variables)["declared_type"] +
+ (HasFastArraySerialization(descriptor->message_type()->file()) ?
+ "MaybeToArray" :
+ "");
}
} // namespace
@@ -125,7 +129,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
void MessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
- "::google::protobuf::internal::WireFormatLite::Write$declared_type$NoVirtual(\n"
+ "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
" $number$, this->$name$(), output);\n");
}
@@ -164,26 +168,19 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedMessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "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");
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ " $name$() const$deprecation$;\n"
+ "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ " mutable_$name$()$deprecation$;\n");
}
void RepeatedMessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
- "$classname$::$name$() const {\n"
- " return $name$_;\n"
- "}\n"
- "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
- "$classname$::mutable_$name$() {\n"
- " return &$name$_;\n"
- "}\n"
"inline const $type$& $classname$::$name$(int index) const {\n"
" return $name$_.Get(index);\n"
"}\n"
@@ -193,6 +190,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"inline $type$* $classname$::add_$name$() {\n"
" return $name$_.Add();\n"
"}\n");
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ "$classname$::$name$() const {\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ "$classname$::mutable_$name$() {\n"
+ " return &$name$_;\n"
+ "}\n");
}
void RepeatedMessageFieldGenerator::
@@ -232,7 +238,7 @@ void RepeatedMessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n"
- " ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoVirtual(\n"
+ " ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
" $number$, this->$name$(i), output);\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 81f5ce07..a69c48b5 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -84,10 +84,14 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
SetCommonFieldVariables(descriptor, variables);
(*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
(*variables)["default"] = DefaultValue(descriptor);
+ (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
int fixed_size = FixedSize(descriptor->type());
if (fixed_size != -1) {
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
}
+ (*variables)["wire_format_field_type"] =
+ "::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name(
+ static_cast<FieldDescriptorProto_Type>(descriptor->type()));
}
} // namespace
@@ -149,8 +153,9 @@ GenerateConstructorCode(io::Printer* printer) const {
void PrimitiveFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
- "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
- " input, &$name$_));\n"
+ "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
+ " $type$, $wire_format_field_type$>(\n"
+ " input, &$name$_)));\n"
"_set_bit($index$);\n");
}
@@ -188,6 +193,14 @@ RepeatedPrimitiveFieldGenerator::
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor)
: descriptor_(descriptor) {
SetPrimitiveVariables(descriptor, &variables_);
+
+ if (descriptor->options().packed()) {
+ variables_["packed_reader"] = "ReadPackedPrimitive";
+ variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
+ } else {
+ variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
+ variables_["repeated_reader"] = "ReadRepeatedPrimitive";
+ }
}
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
@@ -205,25 +218,19 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "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");
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
+ " $name$() const$deprecation$;\n"
+ "inline ::google::protobuf::RepeatedField< $type$ >*\n"
+ " mutable_$name$()$deprecation$;\n");
}
void RepeatedPrimitiveFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
- "$classname$::$name$() const {\n"
- " return $name$_;\n"
- "}\n"
- "inline ::google::protobuf::RepeatedField< $type$ >*\n"
- "$classname$::mutable_$name$() {\n"
- " return &$name$_;\n"
- "}\n"
"inline $type$ $classname$::$name$(int index) const {\n"
" return $name$_.Get(index);\n"
"}\n"
@@ -233,6 +240,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"inline void $classname$::add_$name$($type$ value) {\n"
" $name$_.Add(value);\n"
"}\n");
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
+ "$classname$::$name$() const {\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline ::google::protobuf::RepeatedField< $type$ >*\n"
+ "$classname$::mutable_$name$() {\n"
+ " return &$name$_;\n"
+ "}\n");
}
void RepeatedPrimitiveFieldGenerator::
@@ -257,30 +273,18 @@ GenerateConstructorCode(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
- printer->Print("{\n");
- printer->Indent();
- printer->Print(variables_,
- "::google::protobuf::uint32 length;\n"
- "DO_(input->ReadVarint32(&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::WireFormatLite::Read$declared_type$(\n"
- " input, &value));\n"
- " add_$name$(value);\n"
- "}\n"
- "input->PopLimit(limit);\n");
- printer->Outdent();
- printer->Print("}\n");
- } else {
- printer->Print(variables_,
- "$type$ value;\n"
- "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
- " input, &value));\n"
- "add_$name$(value);\n");
- }
+ printer->Print(variables_,
+ "DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n"
+ " $type$, $wire_format_field_type$>(\n"
+ " $tag_size$, $tag$, input, this->mutable_$name$())));\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
+ printer->Print(variables_,
+ "DO_((::google::protobuf::internal::WireFormatLite::$packed_reader$<\n"
+ " $type$, $wire_format_field_type$>(\n"
+ " input, this->mutable_$name$())));\n");
}
void RepeatedPrimitiveFieldGenerator::
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index 6b96614c..8fcd74ae 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -83,6 +83,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
+ void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 72258e89..ea6809a9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -91,7 +91,7 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
// files that applied the ctype. The field can still be accessed via the
// reflection interface since the reflection interface is independent of
// the string's underlying representation.
- if (descriptor_->options().has_ctype()) {
+ if (descriptor_->options().ctype() != FieldOptions::STRING) {
printer->Outdent();
printer->Print(
" private:\n"
@@ -107,7 +107,7 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"$deprecation$;\n"
"inline ::std::string* mutable_$name$()$deprecation$;\n");
- if (descriptor_->options().has_ctype()) {
+ if (descriptor_->options().ctype() != FieldOptions::STRING) {
printer->Outdent();
printer->Print(" public:\n");
printer->Indent();
@@ -278,7 +278,7 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedStringFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
// See comment above about unknown ctypes.
- if (descriptor_->options().has_ctype()) {
+ if (descriptor_->options().ctype() != FieldOptions::STRING) {
printer->Outdent();
printer->Print(
" private:\n"
@@ -287,10 +287,6 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
}
printer->Print(variables_,
- "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"
@@ -304,7 +300,13 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"inline void add_$name$(const $pointer_type$* value, size_t size)"
"$deprecation$;\n");
- if (descriptor_->options().has_ctype()) {
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
+ "$deprecation$;\n"
+ "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
+ "$deprecation$;\n");
+
+ if (descriptor_->options().ctype() != FieldOptions::STRING) {
printer->Outdent();
printer->Print(" public:\n");
printer->Indent();
@@ -314,14 +316,6 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
void RepeatedStringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
- "$classname$::$name$() const {\n"
- " return $name$_;\n"
- "}\n"
- "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
- "$classname$::mutable_$name$() {\n"
- " return &$name$_;\n"
- "}\n"
"inline const ::std::string& $classname$::$name$(int index) const {\n"
" return $name$_.Get(index);\n"
"}\n"
@@ -353,6 +347,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
" $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
"}\n");
+ printer->Print(variables_,
+ "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
+ "$classname$::$name$() const {\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
+ "$classname$::mutable_$name$() {\n"
+ " return &$name$_;\n"
+ "}\n");
}
void RepeatedStringFieldGenerator::
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index d7575c05..a7e852de 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -49,6 +49,7 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_optimize_for.pb.h>
#include <google/protobuf/unittest_embed_optimize_for.pb.h>
+#include <google/protobuf/unittest_no_generic_services.pb.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h>
#include <google/protobuf/compiler/importer.h>
@@ -154,6 +155,16 @@ TEST(GeneratedMessageTest, FloatingPointDefaults) {
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());
+ EXPECT_EQ(numeric_limits<double>::infinity(),
+ extreme_default.inf_double());
+ EXPECT_EQ(-numeric_limits<double>::infinity(),
+ extreme_default.neg_inf_double());
+ EXPECT_TRUE(extreme_default.nan_double() != extreme_default.nan_double());
+ EXPECT_EQ(numeric_limits<float>::infinity(),
+ extreme_default.inf_float());
+ EXPECT_EQ(-numeric_limits<float>::infinity(),
+ extreme_default.neg_inf_float());
+ EXPECT_TRUE(extreme_default.nan_float() != extreme_default.nan_float());
}
TEST(GeneratedMessageTest, Accessors) {
@@ -779,22 +790,39 @@ TEST(GeneratedEnumTest, IsValidValue) {
}
TEST(GeneratedEnumTest, MinAndMax) {
- EXPECT_EQ(unittest::TestAllTypes::FOO,unittest::TestAllTypes::NestedEnum_MIN);
- EXPECT_EQ(unittest::TestAllTypes::BAZ,unittest::TestAllTypes::NestedEnum_MAX);
+ EXPECT_EQ(unittest::TestAllTypes::FOO,
+ unittest::TestAllTypes::NestedEnum_MIN);
+ EXPECT_EQ(unittest::TestAllTypes::BAZ,
+ unittest::TestAllTypes::NestedEnum_MAX);
+ EXPECT_EQ(4, unittest::TestAllTypes::NestedEnum_ARRAYSIZE);
EXPECT_EQ(unittest::FOREIGN_FOO, unittest::ForeignEnum_MIN);
EXPECT_EQ(unittest::FOREIGN_BAZ, unittest::ForeignEnum_MAX);
+ EXPECT_EQ(7, unittest::ForeignEnum_ARRAYSIZE);
EXPECT_EQ(1, unittest::TestEnumWithDupValue_MIN);
EXPECT_EQ(3, unittest::TestEnumWithDupValue_MAX);
+ EXPECT_EQ(4, unittest::TestEnumWithDupValue_ARRAYSIZE);
EXPECT_EQ(unittest::SPARSE_E, unittest::TestSparseEnum_MIN);
EXPECT_EQ(unittest::SPARSE_C, unittest::TestSparseEnum_MAX);
+ EXPECT_EQ(12589235, unittest::TestSparseEnum_ARRAYSIZE);
- // Make sure we can use _MIN and _MAX as switch cases.
- switch(unittest::SPARSE_A) {
+ // Make sure we can take the address of _MIN, _MAX and _ARRAYSIZE.
+ void* nullptr = 0; // NULL may be integer-type, not pointer-type.
+ EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_MIN);
+ EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_MAX);
+ EXPECT_NE(nullptr, &unittest::TestAllTypes::NestedEnum_ARRAYSIZE);
+
+ EXPECT_NE(nullptr, &unittest::ForeignEnum_MIN);
+ EXPECT_NE(nullptr, &unittest::ForeignEnum_MAX);
+ EXPECT_NE(nullptr, &unittest::ForeignEnum_ARRAYSIZE);
+
+ // Make sure we can use _MIN, _MAX and _ARRAYSIZE as switch cases.
+ switch (unittest::SPARSE_A) {
case unittest::TestSparseEnum_MIN:
case unittest::TestSparseEnum_MAX:
+ case unittest::TestSparseEnum_ARRAYSIZE:
break;
default:
break;
@@ -1136,6 +1164,43 @@ TEST_F(GeneratedServiceTest, NotImplemented) {
EXPECT_TRUE(controller.called_);
}
+} // namespace cpp_unittest
+} // namespace cpp
+} // namespace compiler
+
+namespace no_generic_services_test {
+ // Verify that no class called "TestService" was defined in
+ // unittest_no_generic_services.pb.h by defining a different type by the same
+ // name. If such a service was generated, this will not compile.
+ struct TestService {
+ int i;
+ };
+}
+
+namespace compiler {
+namespace cpp {
+namespace cpp_unittest {
+
+TEST_F(GeneratedServiceTest, NoGenericServices) {
+ // Verify that non-services in unittest_no_generic_services.proto were
+ // generated.
+ no_generic_services_test::TestMessage message;
+ message.set_a(1);
+ message.SetExtension(no_generic_services_test::test_extension, 123);
+ no_generic_services_test::TestEnum e = no_generic_services_test::FOO;
+ EXPECT_EQ(e, 1);
+
+ // Verify that a ServiceDescriptor is generated for the service even if the
+ // class itself is not.
+ const FileDescriptor* file =
+ no_generic_services_test::TestMessage::descriptor()->file();
+
+ ASSERT_EQ(1, file->service_count());
+ EXPECT_EQ("TestService", file->service(0)->name());
+ ASSERT_EQ(1, file->service(0)->method_count());
+ EXPECT_EQ("Foo", file->service(0)->method(0)->name());
+}
+
#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 8ade50c9..85e39f53 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -223,6 +223,11 @@ void EnumGenerator::Generate(io::Printer* printer) {
"file", ClassName(descriptor_->file()));
}
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(enum_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
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 dc36e06e..af6b1cd2 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -62,7 +62,7 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
(*variables)["default"] = DefaultValue(descriptor);
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
(*variables)["tag_size"] = SimpleItoa(
- internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
+ internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
}
} // namespace
@@ -81,7 +81,7 @@ void EnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private boolean has$capitalized_name$;\n"
- "private $type$ $name$_ = $default$;\n"
+ "private $type$ $name$_;\n"
"public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
"public $type$ get$capitalized_name$() { return $name$_; }\n");
}
@@ -111,6 +111,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void EnumFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void EnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\n"
@@ -241,6 +246,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void RepeatedEnumFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Initialized inline.
+}
+
+void RepeatedEnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!other.$name$_.isEmpty()) {\n"
@@ -262,15 +272,6 @@ GenerateBuildingCode(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
- // If packed, set up the while loop
- if (descriptor_->options().packed()) {
- printer->Print(variables_,
- "int length = input.readRawVarint32();\n"
- "int oldLimit = input.pushLimit(length);\n"
- "while(input.getBytesUntilLimit() > 0) {\n");
- printer->Indent();
- }
-
// Read and store the enum
printer->Print(variables_,
"int rawValue = input.readEnum();\n"
@@ -287,13 +288,24 @@ GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
" add$capitalized_name$(value);\n"
"}\n");
+}
- if (descriptor_->options().packed()) {
- printer->Outdent();
- printer->Print(variables_,
- "}\n"
- "input.popLimit(oldLimit);\n");
- }
+void RepeatedEnumFieldGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ // Wrap GenerateParsingCode's contents with a while loop.
+
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int oldLimit = input.pushLimit(length);\n"
+ "while(input.getBytesUntilLimit() > 0) {\n");
+ printer->Indent();
+
+ GenerateParsingCode(printer);
+
+ printer->Outdent();
+ printer->Print(variables_,
+ "}\n"
+ "input.popLimit(oldLimit);\n");
}
void RepeatedEnumFieldGenerator::
diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h
index 63f68153..c54a0faf 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.h
+++ b/src/google/protobuf/compiler/java/java_enum_field.h
@@ -52,6 +52,7 @@ class EnumFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
@@ -75,9 +76,11 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingCodeFromPacked(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc
index 4403220b..5932433f 100644
--- a/src/google/protobuf/compiler/java/java_extension.cc
+++ b/src/google/protobuf/compiler/java/java_extension.cc
@@ -133,7 +133,7 @@ void ExtensionGenerator::GenerateInitializationCode(io::Printer* printer) {
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["type_constant"] = TypeName(GetType(descriptor_));
vars["packed"] = descriptor_->options().packed() ? "true" : "false";
vars["enum_map"] = "null";
vars["prototype"] = "null";
@@ -208,5 +208,4 @@ void ExtensionGenerator::GenerateRegistrationCode(io::Printer* printer) {
} // namespace java
} // namespace compiler
} // namespace protobuf
-
} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index f9d34ad7..978c8f33 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -46,6 +46,16 @@ namespace java {
FieldGenerator::~FieldGenerator() {}
+void FieldGenerator::GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ // Reaching here indicates a bug. Cases are:
+ // - This FieldGenerator should support packing, but this method should be
+ // overridden.
+ // - This FieldGenerator doesn't support packing, and this method should
+ // never have been called.
+ GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "
+ << "called on field generator that does not support packing.";
+}
+
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
: descriptor_(descriptor),
field_generators_(
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index cab463c8..f5bef7ab 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -57,9 +57,11 @@ class FieldGenerator {
virtual void GenerateMembers(io::Printer* printer) const = 0;
virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
+ virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
virtual void GenerateBuildingCode(io::Printer* printer) const = 0;
virtual void GenerateParsingCode(io::Printer* printer) const = 0;
+ virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const;
virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index 2aedde5e..7ea127c0 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -64,7 +64,7 @@ bool UsesExtensions(const Message& message) {
for (int i = 0; i < fields.size(); i++) {
if (fields[i]->is_extension()) return true;
- if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
if (fields[i]->is_repeated()) {
int size = reflection->FieldSize(message, fields[i]);
for (int j = 0; j < size; j++) {
@@ -82,6 +82,7 @@ bool UsesExtensions(const Message& message) {
return false;
}
+
} // namespace
FileGenerator::FileGenerator(const FileDescriptor* file)
@@ -134,7 +135,9 @@ void FileGenerator::Generate(io::Printer* printer) {
// fully-qualified names in the generated source.
printer->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
- "\n");
+ "// source: $filename$\n"
+ "\n",
+ "filename", file_->name());
if (!java_package_.empty()) {
printer->Print(
"package $package$;\n"
@@ -178,8 +181,10 @@ void FileGenerator::Generate(io::Printer* printer) {
for (int i = 0; i < file_->message_type_count(); i++) {
MessageGenerator(file_->message_type(i)).Generate(printer);
}
- for (int i = 0; i < file_->service_count(); i++) {
- ServiceGenerator(file_->service(i)).Generate(printer);
+ if (HasGenericServices(file_)) {
+ for (int i = 0; i < file_->service_count(); i++) {
+ ServiceGenerator(file_->service(i)).Generate(printer);
+ }
}
}
@@ -228,6 +233,10 @@ void FileGenerator::Generate(io::Printer* printer) {
"\n"
"public static void internalForceInit() {}\n");
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(outer_class_scope)\n");
+
printer->Outdent();
printer->Print("}\n");
}
@@ -245,6 +254,7 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
// embedded raw, which is what we want.
FileDescriptorProto file_proto;
file_->CopyTo(&file_proto);
+
string file_data;
file_proto.SerializeToString(&file_data);
@@ -343,9 +353,11 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
" new com.google.protobuf.Descriptors.FileDescriptor[] {\n");
for (int i = 0; i < file_->dependency_count(); i++) {
- printer->Print(
- " $dependency$.getDescriptor(),\n",
- "dependency", ClassName(file_->dependency(i)));
+ if (ShouldIncludeDependency(file_->dependency(i))) {
+ printer->Print(
+ " $dependency$.getDescriptor(),\n",
+ "dependency", ClassName(file_->dependency(i)));
+ }
}
printer->Print(
@@ -396,14 +408,20 @@ void FileGenerator::GenerateSiblings(const string& package_dir,
file_->message_type(i),
output_directory, file_list);
}
- for (int i = 0; i < file_->service_count(); i++) {
- GenerateSibling<ServiceGenerator>(package_dir, java_package_,
- file_->service(i),
- output_directory, file_list);
+ if (HasGenericServices(file_)) {
+ for (int i = 0; i < file_->service_count(); i++) {
+ GenerateSibling<ServiceGenerator>(package_dir, java_package_,
+ file_->service(i),
+ output_directory, file_list);
+ }
}
}
}
+bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor) {
+ return true;
+}
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h
index cb82cea2..9e35d330 100644
--- a/src/google/protobuf/compiler/java/java_file.h
+++ b/src/google/protobuf/compiler/java/java_file.h
@@ -77,6 +77,11 @@ class FileGenerator {
const string& classname() { return classname_; }
private:
+ // Returns whether the dependency should be included in the output file.
+ // Always returns true for opensource, but used internally at Google to help
+ // improve compatibility with version 1 of protocol buffers.
+ bool ShouldIncludeDependency(const FileDescriptor* descriptor);
+
const FileDescriptor* file_;
string java_package_;
string classname_;
diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc
index 8ed3affb..745b55ae 100644
--- a/src/google/protobuf/compiler/java/java_generator.cc
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -45,6 +45,7 @@ namespace protobuf {
namespace compiler {
namespace java {
+
JavaGenerator::JavaGenerator() {}
JavaGenerator::~JavaGenerator() {}
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index dc6748e3..7ed0c3cc 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -32,6 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <limits>
#include <vector>
#include <google/protobuf/compiler/java/java_helpers.h>
@@ -57,7 +58,7 @@ const string& FieldName(const FieldDescriptor* field) {
// Groups are hacky: The name of the field is just the lower-cased name
// of the group type. In Java, though, we would like to retain the original
// capitalization of the type name.
- if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ if (GetType(field) == FieldDescriptor::TYPE_GROUP) {
return field->message_type()->name();
} else {
return field->name();
@@ -178,8 +179,12 @@ string FieldConstantName(const FieldDescriptor *field) {
return name;
}
-JavaType GetJavaType(FieldDescriptor::Type field_type) {
- switch (field_type) {
+FieldDescriptor::Type GetType(const FieldDescriptor* field) {
+ return field->type();
+}
+
+JavaType GetJavaType(const FieldDescriptor* field) {
+ switch (GetType(field)) {
case FieldDescriptor::TYPE_INT32:
case FieldDescriptor::TYPE_UINT32:
case FieldDescriptor::TYPE_SINT32:
@@ -254,7 +259,7 @@ bool AllAscii(const string& text) {
}
string DefaultValue(const FieldDescriptor* field) {
- // Switch on cpp_type since we need to know which default_value_* method
+ // Switch on CppType since we need to know which default_value_* method
// of FieldDescriptor to call.
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
@@ -267,14 +272,34 @@ string DefaultValue(const FieldDescriptor* field) {
case FieldDescriptor::CPPTYPE_UINT64:
return SimpleItoa(static_cast<int64>(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_DOUBLE: {
+ double value = field->default_value_double();
+ if (value == numeric_limits<double>::infinity()) {
+ return "Double.POSITIVE_INFINITY";
+ } else if (value == -numeric_limits<double>::infinity()) {
+ return "Double.NEGATIVE_INFINITY";
+ } else if (value != value) {
+ return "Double.NaN";
+ } else {
+ return SimpleDtoa(value) + "D";
+ }
+ }
+ case FieldDescriptor::CPPTYPE_FLOAT: {
+ float value = field->default_value_float();
+ if (value == numeric_limits<float>::infinity()) {
+ return "Float.POSITIVE_INFINITY";
+ } else if (value == -numeric_limits<float>::infinity()) {
+ return "Float.NEGATIVE_INFINITY";
+ } else if (value != value) {
+ return "Float.NaN";
+ } else {
+ return SimpleFtoa(value) + "F";
+ }
+ }
case FieldDescriptor::CPPTYPE_BOOL:
return field->default_value_bool() ? "true" : "false";
case FieldDescriptor::CPPTYPE_STRING:
- if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ if (GetType(field) == FieldDescriptor::TYPE_BYTES) {
if (field->has_default_value()) {
// See comments in Internal.java for gory details.
return strings::Substitute(
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index f1b643c3..3c8974c9 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -93,6 +93,11 @@ string ClassName(const FileDescriptor* descriptor);
// number constant.
string FieldConstantName(const FieldDescriptor *field);
+// Returns the type of the FieldDescriptor.
+// This does nothing interesting for the open source release, but is used for
+// hacks that improve compatability with version 1 protocol buffers at Google.
+FieldDescriptor::Type GetType(const FieldDescriptor* field);
+
enum JavaType {
JAVATYPE_INT,
JAVATYPE_LONG,
@@ -105,11 +110,7 @@ enum JavaType {
JAVATYPE_MESSAGE
};
-JavaType GetJavaType(FieldDescriptor::Type field_type);
-
-inline JavaType GetJavaType(const FieldDescriptor* field) {
- return GetJavaType(field->type());
-}
+JavaType GetJavaType(const FieldDescriptor* field);
// Get the fully-qualified class name for a boxed primitive type, e.g.
// "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message
@@ -145,6 +146,13 @@ inline bool HasDescriptorMethods(const FileDescriptor* descriptor) {
FileOptions::LITE_RUNTIME;
}
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor *file) {
+ return file->service_count() > 0 &&
+ file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
+ file->options().java_generic_services();
+}
+
} // 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 99b57c95..1f8e209c 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -127,7 +127,7 @@ static bool HasRequiredFields(
if (field->is_required()) {
return true;
}
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (GetJavaType(field) == JAVATYPE_MESSAGE) {
if (HasRequiredFields(field->message_type(), already_seen)) {
return true;
}
@@ -292,9 +292,14 @@ void MessageGenerator::Generate(io::Printer* printer) {
printer->Indent();
printer->Print(
"// Use $classname$.newBuilder() to construct.\n"
- "private $classname$() {}\n"
+ "private $classname$() {\n"
+ " initFields();\n"
+ "}\n"
+ // Used when constructing the default instance, which cannot be initialized
+ // immediately because it may cyclically refer to other default instances.
+ "private $classname$(boolean noInit) {}\n"
"\n"
- "private static final $classname$ defaultInstance = new $classname$();\n"
+ "private static final $classname$ defaultInstance;\n"
"public static $classname$ getDefaultInstance() {\n"
" return defaultInstance;\n"
"}\n"
@@ -344,6 +349,17 @@ void MessageGenerator::Generate(io::Printer* printer) {
printer->Print("\n");
}
+ // Called by the constructor, except in the case of the default instance,
+ // in which case this is called by static init code later on.
+ printer->Print("private void initFields() {\n");
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateInitializationCode(printer);
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+
if (HasGeneratedMethods(descriptor_)) {
GenerateIsInitialized(printer);
GenerateMessageSerializationMethods(printer);
@@ -352,25 +368,23 @@ void MessageGenerator::Generate(io::Printer* printer) {
GenerateParseFromMethods(printer);
GenerateBuilder(printer);
- 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.
+ // not be initialized. Also carefully initialize the default instance in
+ // such a way that it doesn't conflict with other initialization.
printer->Print(
"\n"
"static {\n"
+ " defaultInstance = new $classname$(true);\n"
" $file$.internalForceInit();\n"
+ " defaultInstance.initFields();\n"
"}\n",
- "file", ClassName(descriptor_->file()));
+ "file", ClassName(descriptor_->file()),
+ "classname", descriptor_->name());
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
printer->Outdent();
printer->Print("}\n\n");
@@ -529,14 +543,23 @@ GenerateParseFromMethods(io::Printer* printer) {
"}\n"
"public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
" throws java.io.IOException {\n"
- " return newBuilder().mergeDelimitedFrom(input).buildParsed();\n"
+ " Builder builder = newBuilder();\n"
+ " if (builder.mergeDelimitedFrom(input)) {\n"
+ " return builder.buildParsed();\n"
+ " } else {\n"
+ " return null;\n"
+ " }\n"
"}\n"
"public static $classname$ parseDelimitedFrom(\n"
" java.io.InputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return newBuilder().mergeDelimitedFrom(input, extensionRegistry)\n"
- " .buildParsed();\n"
+ " Builder builder = newBuilder();\n"
+ " if (builder.mergeDelimitedFrom(input, extensionRegistry)) {\n"
+ " return builder.buildParsed();\n"
+ " } else {\n"
+ " return null;\n"
+ " }\n"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.CodedInputStream input)\n"
@@ -827,7 +850,7 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = sorted_fields[i];
uint32 tag = WireFormatLite::MakeTag(field->number(),
- WireFormat::WireTypeForField(field));
+ WireFormat::WireTypeForFieldType(field->type()));
printer->Print(
"case $tag$: {\n",
@@ -840,6 +863,24 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
printer->Print(
" break;\n"
"}\n");
+
+ if (field->is_packable()) {
+ // To make packed = true wire compatible, we generate parsing code from a
+ // packed version of this field regardless of field->options().packed().
+ uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ printer->Print(
+ "case $tag$: {\n",
+ "tag", SimpleItoa(packed_tag));
+ printer->Indent();
+
+ field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " break;\n"
+ "}\n");
+ }
}
printer->Outdent();
@@ -875,7 +916,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
// Now check that all embedded messages are initialized.
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
HasRequiredFields(field->message_type())) {
switch (field->label()) {
case FieldDescriptor::LABEL_REQUIRED:
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index bbddddde..71edc024 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -59,7 +59,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(*variables)["number"] = SimpleItoa(descriptor->number());
(*variables)["type"] = ClassName(descriptor->message_type());
(*variables)["group_or_message"] =
- (descriptor->type() == FieldDescriptor::TYPE_GROUP) ?
+ (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ?
"Group" : "Message";
}
@@ -79,7 +79,7 @@ void MessageFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private boolean has$capitalized_name$;\n"
- "private $type$ $name$_ = $type$.getDefaultInstance();\n"
+ "private $type$ $name$_;\n"
"public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
"public $type$ get$capitalized_name$() { return $name$_; }\n");
}
@@ -125,6 +125,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void MessageFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n");
+}
+
+void MessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\n"
@@ -145,7 +150,7 @@ GenerateParsingCode(io::Printer* printer) const {
" subBuilder.mergeFrom(get$capitalized_name$());\n"
"}\n");
- if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
"input.readGroup($number$, subBuilder, extensionRegistry);\n");
} else {
@@ -262,6 +267,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void RepeatedMessageFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Initialized inline.
+}
+
+void RepeatedMessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!other.$name$_.isEmpty()) {\n"
@@ -286,7 +296,7 @@ GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"$type$.Builder subBuilder = $type$.newBuilder();\n");
- if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
"input.readGroup($number$, subBuilder, extensionRegistry);\n");
} else {
diff --git a/src/google/protobuf/compiler/java/java_message_field.h b/src/google/protobuf/compiler/java/java_message_field.h
index 90a90976..66bdd884 100644
--- a/src/google/protobuf/compiler/java/java_message_field.h
+++ b/src/google/protobuf/compiler/java/java_message_field.h
@@ -52,6 +52,7 @@ class MessageFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
@@ -75,6 +76,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 1fbca5a2..f6179bfa 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -93,7 +93,7 @@ bool IsReferenceType(JavaType type) {
}
const char* GetCapitalizedType(const FieldDescriptor* field) {
- switch (field->type()) {
+ switch (GetType(field)) {
case FieldDescriptor::TYPE_INT32 : return "Int32" ;
case FieldDescriptor::TYPE_UINT32 : return "UInt32" ;
case FieldDescriptor::TYPE_SINT32 : return "SInt32" ;
@@ -166,7 +166,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
(*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
(*variables)["tag_size"] = SimpleItoa(
- WireFormat::TagSize(descriptor->number(), descriptor->type()));
+ WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
if (IsReferenceType(GetJavaType(descriptor))) {
(*variables)["null_check"] =
" if (value == null) {\n"
@@ -175,7 +175,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
} else {
(*variables)["null_check"] = "";
}
- int fixed_size = FixedSize(descriptor->type());
+ int fixed_size = FixedSize(GetType(descriptor));
if (fixed_size != -1) {
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
}
@@ -218,7 +218,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
"}\n"
"public Builder clear$capitalized_name$() {\n"
" result.has$capitalized_name$ = false;\n");
- if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ JavaType type = GetJavaType(descriptor_);
+ if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
// 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_,
@@ -233,6 +234,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void PrimitiveFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Initialized inline.
+}
+
+void PrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\n"
@@ -346,6 +352,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void RepeatedPrimitiveFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Initialized inline.
+}
+
+void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!other.$name$_.isEmpty()) {\n"
@@ -367,18 +378,19 @@ GenerateBuildingCode(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
- printer->Print(variables_,
- "int length = input.readRawVarint32();\n"
- "int limit = input.pushLimit(length);\n"
- "while (input.getBytesUntilLimit() > 0) {\n"
- " add$capitalized_name$(input.read$capitalized_type$());\n"
- "}\n"
- "input.popLimit(limit);\n");
- } else {
- printer->Print(variables_,
- "add$capitalized_name$(input.read$capitalized_type$());\n");
- }
+ printer->Print(variables_,
+ "add$capitalized_name$(input.read$capitalized_type$());\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int limit = input.pushLimit(length);\n"
+ "while (input.getBytesUntilLimit() > 0) {\n"
+ " add$capitalized_name$(input.read$capitalized_type$());\n"
+ "}\n"
+ "input.popLimit(limit);\n");
}
void RepeatedPrimitiveFieldGenerator::
@@ -407,7 +419,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
" int dataSize = 0;\n");
printer->Indent();
- if (FixedSize(descriptor_->type()) == -1) {
+ if (FixedSize(GetType(descriptor_)) == -1) {
printer->Print(variables_,
"for ($type$ element : get$capitalized_name$List()) {\n"
" dataSize += com.google.protobuf.CodedOutputStream\n"
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.h b/src/google/protobuf/compiler/java/java_primitive_field.h
index f9da0a62..4e482a05 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.h
+++ b/src/google/protobuf/compiler/java/java_primitive_field.h
@@ -52,6 +52,7 @@ class PrimitiveFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
@@ -75,9 +76,11 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingCodeFromPacked(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index 0a2c0b2c..d9b0c3f9 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -39,6 +39,7 @@
int main(int argc, char* argv[]) {
google::protobuf::compiler::CommandLineInterface cli;
+ cli.AllowPlugins("protoc-");
// Proto2 C++
google::protobuf::compiler::cpp::CppGenerator cpp_generator;
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 02304d6d..758f70dc 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -34,8 +34,9 @@
//
// Recursive descent FTW.
-#include <google/protobuf/stubs/hash.h>
#include <float.h>
+#include <google/protobuf/stubs/hash.h>
+#include <limits>
#include <google/protobuf/compiler/parser.h>
@@ -206,6 +207,14 @@ bool Parser::ConsumeNumber(double* output, const char* error) {
*output = value;
input_->Next();
return true;
+ } else if (LookingAt("inf")) {
+ *output = numeric_limits<double>::infinity();
+ input_->Next();
+ return true;
+ } else if (LookingAt("nan")) {
+ *output = numeric_limits<double>::quiet_NaN();
+ input_->Next();
+ return true;
} else {
AddError(error);
return false;
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index c4f08e7f..e2262b8b 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -336,6 +336,9 @@ TEST_F(ParseMessageTest, FieldDefaults) {
" required double foo = 1 [default= 10.5];\n"
" required double foo = 1 [default=-11.5];\n"
" required double foo = 1 [default= 12 ];\n"
+ " required double foo = 1 [default= inf ];\n"
+ " required double foo = 1 [default=-inf ];\n"
+ " required double foo = 1 [default= nan ];\n"
" required string foo = 1 [default='13\\001'];\n"
" required string foo = 1 [default='a' \"b\" \n \"c\"];\n"
" required bytes foo = 1 [default='14\\002'];\n"
@@ -367,6 +370,9 @@ TEST_F(ParseMessageTest, FieldDefaults) {
" field { type:TYPE_DOUBLE default_value:\"10.5\" "ETC" }"
" field { type:TYPE_DOUBLE default_value:\"-11.5\" "ETC" }"
" field { type:TYPE_DOUBLE default_value:\"12\" "ETC" }"
+ " field { type:TYPE_DOUBLE default_value:\"inf\" "ETC" }"
+ " field { type:TYPE_DOUBLE default_value:\"-inf\" "ETC" }"
+ " field { type:TYPE_DOUBLE default_value:\"nan\" "ETC" }"
" field { type:TYPE_STRING default_value:\"13\\001\" "ETC" }"
" field { type:TYPE_STRING default_value:\"abc\" "ETC" }"
" field { type:TYPE_BYTES default_value:\"14\\\\002\" "ETC" }"
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index d301f015..54ab0a2d 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -42,8 +42,9 @@
// performance-minded Python code leverage the fast C++ implementation
// directly.
-#include <utility>
+#include <limits>
#include <map>
+#include <utility>
#include <string>
#include <vector>
@@ -105,6 +106,13 @@ string NamePrefixedWithNestedTypes(const DescriptorT& descriptor,
const char kDescriptorKey[] = "DESCRIPTOR";
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor *file) {
+ return file->service_count() > 0 &&
+ file->options().py_generic_services();
+}
+
+
// Prints the common boilerplate needed at the top of every .py
// file output by this generator.
void PrintTopBoilerplate(
@@ -115,14 +123,21 @@ void PrintTopBoilerplate(
"\n"
"from google.protobuf import descriptor\n"
"from google.protobuf import message\n"
- "from google.protobuf import reflection\n"
- "from google.protobuf import service\n"
- "from google.protobuf import service_reflection\n");
+ "from google.protobuf import reflection\n");
+ if (HasGenericServices(file)) {
+ printer->Print(
+ "from google.protobuf import service\n"
+ "from google.protobuf import service_reflection\n");
+ }
+
// Avoid circular imports if this module is descriptor_pb2.
if (!descriptor_proto) {
printer->Print(
"from google.protobuf import descriptor_pb2\n");
}
+ printer->Print(
+ "# @@protoc_insertion_point(imports)\n");
+ printer->Print("\n\n");
}
@@ -150,10 +165,30 @@ string StringifyDefaultValue(const FieldDescriptor& field) {
return SimpleItoa(field.default_value_int64());
case FieldDescriptor::CPPTYPE_UINT64:
return SimpleItoa(field.default_value_uint64());
- case FieldDescriptor::CPPTYPE_DOUBLE:
- return SimpleDtoa(field.default_value_double());
- case FieldDescriptor::CPPTYPE_FLOAT:
- return SimpleFtoa(field.default_value_float());
+ case FieldDescriptor::CPPTYPE_DOUBLE: {
+ double value = field.default_value_double();
+ if (value == numeric_limits<double>::infinity()) {
+ return "float('inf')";
+ } else if (value == -numeric_limits<double>::infinity()) {
+ return "float('-inf')";
+ } else if (value != value) {
+ return "float('nan')";
+ } else {
+ return SimpleDtoa(value);
+ }
+ }
+ case FieldDescriptor::CPPTYPE_FLOAT: {
+ float value = field.default_value_float();
+ if (value == numeric_limits<float>::infinity()) {
+ return "float('inf')";
+ } else if (value == -numeric_limits<float>::infinity()) {
+ return "float('-inf')";
+ } else if (value != value) {
+ return "float('nan')";
+ } else {
+ return SimpleFtoa(value);
+ }
+ }
case FieldDescriptor::CPPTYPE_BOOL:
return field.default_value_bool() ? "True" : "False";
case FieldDescriptor::CPPTYPE_ENUM:
@@ -204,6 +239,10 @@ bool Generator::Generate(const FileDescriptor* file,
StripString(&filename, ".", '/');
filename += ".py";
+ FileDescriptorProto fdp;
+ file_->CopyTo(&fdp);
+ fdp.SerializeToString(&file_descriptor_serialized_);
+
scoped_ptr<io::ZeroCopyOutputStream> output(output_directory->Open(filename));
GOOGLE_CHECK(output.get());
@@ -211,6 +250,7 @@ bool Generator::Generate(const FileDescriptor* file,
printer_ = &printer;
PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto());
+ PrintFileDescriptor();
PrintTopLevelEnums();
PrintTopLevelExtensions();
PrintAllNestedEnumsInFile();
@@ -224,7 +264,13 @@ bool Generator::Generate(const FileDescriptor* file,
// since they need to call static RegisterExtension() methods on these
// classes.
FixForeignFieldsInExtensions();
- PrintServices();
+ if (HasGenericServices(file)) {
+ PrintServices();
+ }
+
+ printer.Print(
+ "# @@protoc_insertion_point(module_scope)\n");
+
return !printer.failed();
}
@@ -238,6 +284,30 @@ void Generator::PrintImports() const {
printer_->Print("\n");
}
+// Prints the single file descriptor for this file.
+void Generator::PrintFileDescriptor() const {
+ map<string, string> m;
+ m["descriptor_name"] = kDescriptorKey;
+ m["name"] = file_->name();
+ m["package"] = file_->package();
+ const char file_descriptor_template[] =
+ "$descriptor_name$ = descriptor.FileDescriptor(\n"
+ " name='$name$',\n"
+ " package='$package$',\n";
+ printer_->Print(m, file_descriptor_template);
+ printer_->Indent();
+ printer_->Print(
+ "serialized_pb='$value$'",
+ "value", strings::CHexEscape(file_descriptor_serialized_));
+
+ // TODO(falk): Also print options and fix the message_type, enum_type,
+ // service and extension later in the generation.
+
+ printer_->Outdent();
+ printer_->Print(")\n");
+ printer_->Print("\n");
+}
+
// Prints descriptors and module-level constants for all top-level
// enums defined in |file|.
void Generator::PrintTopLevelEnums() const {
@@ -277,12 +347,13 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
m["descriptor_name"] = ModuleLevelDescriptorName(enum_descriptor);
m["name"] = enum_descriptor.name();
m["full_name"] = enum_descriptor.full_name();
- m["filename"] = enum_descriptor.name();
+ m["file"] = kDescriptorKey;
const char enum_descriptor_template[] =
"$descriptor_name$ = descriptor.EnumDescriptor(\n"
" name='$name$',\n"
" full_name='$full_name$',\n"
- " filename='$filename$',\n"
+ " filename=None,\n"
+ " file=$file$,\n"
" values=[\n";
string options_string;
enum_descriptor.options().SerializeToString(&options_string);
@@ -295,9 +366,12 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
}
printer_->Outdent();
printer_->Print("],\n");
+ printer_->Print("containing_type=None,\n");
printer_->Print("options=$options_value$,\n",
"options_value",
OptionsValue("EnumOptions", CEscape(options_string)));
+ EnumDescriptorProto edp;
+ PrintSerializedPbInterval(enum_descriptor, edp);
printer_->Outdent();
printer_->Print(")\n");
printer_->Print("\n");
@@ -362,15 +436,21 @@ void Generator::PrintServiceDescriptor(
map<string, string> m;
m["name"] = descriptor.name();
m["full_name"] = descriptor.full_name();
+ m["file"] = kDescriptorKey;
m["index"] = SimpleItoa(descriptor.index());
m["options_value"] = OptionsValue("ServiceOptions", options_string);
const char required_function_arguments[] =
"name='$name$',\n"
"full_name='$full_name$',\n"
+ "file=$file$,\n"
"index=$index$,\n"
- "options=$options_value$,\n"
- "methods=[\n";
+ "options=$options_value$,\n";
printer_->Print(m, required_function_arguments);
+
+ ServiceDescriptorProto sdp;
+ PrintSerializedPbInterval(descriptor, sdp);
+
+ printer_->Print("methods=[\n");
for (int i = 0; i < descriptor.method_count(); ++i) {
const MethodDescriptor* method = descriptor.method(i);
string options_string;
@@ -444,17 +524,27 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
map<string, string> m;
m["name"] = message_descriptor.name();
m["full_name"] = message_descriptor.full_name();
- m["filename"] = message_descriptor.file()->name();
+ m["file"] = kDescriptorKey;
const char required_function_arguments[] =
"name='$name$',\n"
"full_name='$full_name$',\n"
- "filename='$filename$',\n"
- "containing_type=None,\n"; // TODO(robinson): Implement containing_type.
+ "filename=None,\n"
+ "file=$file$,\n"
+ "containing_type=None,\n";
printer_->Print(m, required_function_arguments);
PrintFieldsInDescriptor(message_descriptor);
PrintExtensionsInDescriptor(message_descriptor);
- // TODO(robinson): implement printing of nested_types.
- printer_->Print("nested_types=[], # TODO(robinson): Implement.\n");
+
+ // Nested types
+ printer_->Print("nested_types=[");
+ for (int i = 0; i < message_descriptor.nested_type_count(); ++i) {
+ const string nested_name = ModuleLevelDescriptorName(
+ *message_descriptor.nested_type(i));
+ printer_->Print("$name$, ", "name", nested_name);
+ }
+ printer_->Print("],\n");
+
+ // Enum types
printer_->Print("enum_types=[\n");
printer_->Indent();
for (int i = 0; i < message_descriptor.enum_type_count(); ++i) {
@@ -468,8 +558,28 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
string options_string;
message_descriptor.options().SerializeToString(&options_string);
printer_->Print(
- "options=$options_value$",
- "options_value", OptionsValue("MessageOptions", options_string));
+ "options=$options_value$,\n"
+ "is_extendable=$extendable$",
+ "options_value", OptionsValue("MessageOptions", options_string),
+ "extendable", message_descriptor.extension_range_count() > 0 ?
+ "True" : "False");
+ printer_->Print(",\n");
+
+ // Extension ranges
+ printer_->Print("extension_ranges=[");
+ for (int i = 0; i < message_descriptor.extension_range_count(); ++i) {
+ const Descriptor::ExtensionRange* range =
+ message_descriptor.extension_range(i);
+ printer_->Print("($start$, $end$), ",
+ "start", SimpleItoa(range->start),
+ "end", SimpleItoa(range->end));
+ }
+ printer_->Print("],\n");
+
+ // Serialization of proto
+ DescriptorProto edp;
+ PrintSerializedPbInterval(message_descriptor, edp);
+
printer_->Outdent();
printer_->Print(")\n");
}
@@ -511,6 +621,12 @@ void Generator::PrintMessage(
m["descriptor_key"] = kDescriptorKey;
m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor);
printer_->Print(m, "$descriptor_key$ = $descriptor_name$\n");
+
+ printer_->Print(
+ "\n"
+ "# @@protoc_insertion_point(class_scope:$full_name$)\n",
+ "full_name", message_descriptor.full_name());
+
printer_->Outdent();
}
@@ -527,16 +643,27 @@ void Generator::PrintNestedMessages(
// Recursively fixes foreign fields in all nested types in |descriptor|, then
// sets the message_type and enum_type of all message and enum fields to point
// to their respective descriptors.
+// Args:
+// descriptor: descriptor to print fields for.
+// containing_descriptor: if descriptor is a nested type, this is its
+// containing type, or NULL if this is a root/top-level type.
void Generator::FixForeignFieldsInDescriptor(
- const Descriptor& descriptor) const {
+ const Descriptor& descriptor,
+ const Descriptor* containing_descriptor) const {
for (int i = 0; i < descriptor.nested_type_count(); ++i) {
- FixForeignFieldsInDescriptor(*descriptor.nested_type(i));
+ FixForeignFieldsInDescriptor(*descriptor.nested_type(i), &descriptor);
}
for (int i = 0; i < descriptor.field_count(); ++i) {
const FieldDescriptor& field_descriptor = *descriptor.field(i);
FixForeignFieldsInField(&descriptor, field_descriptor, "fields_by_name");
}
+
+ FixContainingTypeInDescriptor(descriptor, containing_descriptor);
+ for (int i = 0; i < descriptor.enum_type_count(); ++i) {
+ const EnumDescriptor& enum_descriptor = *descriptor.enum_type(i);
+ FixContainingTypeInDescriptor(enum_descriptor, &descriptor);
+ }
}
// Sets any necessary message_type and enum_type attributes
@@ -593,13 +720,29 @@ string Generator::FieldReferencingExpression(
python_dict_name, field.name());
}
+// Prints containing_type for nested descriptors or enum descriptors.
+template <typename DescriptorT>
+void Generator::FixContainingTypeInDescriptor(
+ const DescriptorT& descriptor,
+ const Descriptor* containing_descriptor) const {
+ if (containing_descriptor != NULL) {
+ const string nested_name = ModuleLevelDescriptorName(descriptor);
+ const string parent_name = ModuleLevelDescriptorName(
+ *containing_descriptor);
+ printer_->Print(
+ "$nested_name$.containing_type = $parent_name$;\n",
+ "nested_name", nested_name,
+ "parent_name", parent_name);
+ }
+}
+
// Prints statements setting the message_type and enum_type fields in the
// Python descriptor objects we've already output in ths file. We must
// do this in a separate step due to circular references (otherwise, we'd
// just set everything in the initial assignment statements).
void Generator::FixForeignFieldsInDescriptors() const {
for (int i = 0; i < file_->message_type_count(); ++i) {
- FixForeignFieldsInDescriptor(*file_->message_type(i));
+ FixForeignFieldsInDescriptor(*file_->message_type(i), NULL);
}
printer_->Print("\n");
}
@@ -696,6 +839,7 @@ void Generator::PrintFieldDescriptor(
m["type"] = SimpleItoa(field.type());
m["cpp_type"] = SimpleItoa(field.cpp_type());
m["label"] = SimpleItoa(field.label());
+ m["has_default_value"] = field.has_default_value() ? "True" : "False";
m["default_value"] = StringifyDefaultValue(field);
m["is_extension"] = is_extension ? "True" : "False";
m["options"] = OptionsValue("FieldOptions", options_string);
@@ -703,13 +847,13 @@ void Generator::PrintFieldDescriptor(
// these fields in correctly after all referenced descriptors have been
// defined and/or imported (see FixForeignFieldsInDescriptors()).
const char field_descriptor_decl[] =
- "descriptor.FieldDescriptor(\n"
- " name='$name$', full_name='$full_name$', index=$index$,\n"
- " number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n"
- " default_value=$default_value$,\n"
- " message_type=None, enum_type=None, containing_type=None,\n"
- " is_extension=$is_extension$, extension_scope=None,\n"
- " options=$options$)";
+ "descriptor.FieldDescriptor(\n"
+ " name='$name$', full_name='$full_name$', index=$index$,\n"
+ " number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n"
+ " has_default_value=$has_default_value$, default_value=$default_value$,\n"
+ " message_type=None, enum_type=None, containing_type=None,\n"
+ " is_extension=$is_extension$, extension_scope=None,\n"
+ " options=$options$)";
printer_->Print(m, field_descriptor_decl);
}
@@ -811,6 +955,29 @@ string Generator::ModuleLevelServiceDescriptorName(
return name;
}
+// Prints standard constructor arguments serialized_start and serialized_end.
+// Args:
+// descriptor: The cpp descriptor to have a serialized reference.
+// proto: A proto
+// Example printer output:
+// serialized_start=41,
+// serialized_end=43,
+//
+template <typename DescriptorT, typename DescriptorProtoT>
+void Generator::PrintSerializedPbInterval(
+ const DescriptorT& descriptor, DescriptorProtoT& proto) const {
+ descriptor.CopyTo(&proto);
+ string sp;
+ proto.SerializeToString(&sp);
+ int offset = file_descriptor_serialized_.find(sp);
+ GOOGLE_CHECK_GE(offset, 0);
+
+ printer_->Print("serialized_start=$serialized_start$,\n"
+ "serialized_end=$serialized_end$,\n",
+ "serialized_start", SimpleItoa(offset),
+ "serialized_end", SimpleItoa(offset + sp.size()));
+}
+
} // namespace python
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index 8b99d624..43c20876 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -71,6 +71,7 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
private:
void PrintImports() const;
+ void PrintFileDescriptor() const;
void PrintTopLevelEnums() const;
void PrintAllNestedEnumsInFile() const;
void PrintNestedEnums(const Descriptor& descriptor) const;
@@ -97,13 +98,19 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
void PrintNestedMessages(const Descriptor& containing_descriptor) const;
void FixForeignFieldsInDescriptors() const;
- void FixForeignFieldsInDescriptor(const Descriptor& descriptor) const;
+ void FixForeignFieldsInDescriptor(
+ const Descriptor& descriptor,
+ const Descriptor* containing_descriptor) const;
void FixForeignFieldsInField(const Descriptor* containing_type,
const FieldDescriptor& field,
const string& python_dict_name) const;
string FieldReferencingExpression(const Descriptor* containing_type,
const FieldDescriptor& field,
const string& python_dict_name) const;
+ template <typename DescriptorT>
+ void FixContainingTypeInDescriptor(
+ const DescriptorT& descriptor,
+ const Descriptor* containing_descriptor) const;
void FixForeignFieldsInExtensions() const;
void FixForeignFieldsInExtension(
@@ -126,10 +133,15 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
string ModuleLevelServiceDescriptorName(
const ServiceDescriptor& descriptor) const;
+ template <typename DescriptorT, typename DescriptorProtoT>
+ void PrintSerializedPbInterval(
+ const DescriptorT& descriptor, DescriptorProtoT& proto) const;
+
// Very coarse-grained lock to ensure that Generate() is reentrant.
- // Guards file_ and printer_.
+ // Guards file_, printer_ and file_descriptor_serialized_.
mutable Mutex mutex_;
mutable const FileDescriptor* file_; // Set in Generate(). Under mutex_.
+ mutable string file_descriptor_serialized_;
mutable io::Printer* printer_; // Set in Generate(). Under mutex_.
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator);
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index a12e4e72..e0a95077 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -796,9 +796,10 @@ bool DescriptorPool::InternalIsFileLoaded(const string& filename) const {
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_;
@@ -810,6 +811,7 @@ void DeleteGeneratedPool() {
void InitGeneratedPool() {
generated_database_ = new EncodedDescriptorDatabase;
generated_pool_ = new DescriptorPool(generated_database_);
+
internal::OnShutdown(&DeleteGeneratedPool);
}
@@ -3651,17 +3653,11 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field,
}
// Only repeated primitive fields may be packed.
- if (field->options().packed()) {
- if (!field->is_repeated() ||
- field->type() == FieldDescriptor::TYPE_STRING ||
- field->type() == FieldDescriptor::TYPE_GROUP ||
- field->type() == FieldDescriptor::TYPE_MESSAGE ||
- field->type() == FieldDescriptor::TYPE_BYTES) {
- AddError(
- field->full_name(), proto,
- DescriptorPool::ErrorCollector::TYPE,
- "[packed = true] can only be specified for repeated primitive fields.");
- }
+ if (field->options().packed() && !field->is_packable()) {
+ AddError(
+ field->full_name(), proto,
+ DescriptorPool::ErrorCollector::TYPE,
+ "[packed = true] can only be specified for repeated primitive fields.");
}
// Note: Default instance may not yet be initialized here, so we have to
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 5b629a5d..7f87dd80 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -395,6 +395,8 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
bool is_required() const; // shorthand for label() == LABEL_REQUIRED
bool is_optional() const; // shorthand for label() == LABEL_OPTIONAL
bool is_repeated() const; // shorthand for label() == LABEL_REPEATED
+ bool is_packable() const; // shorthand for is_repeated() &&
+ // IsTypePackable(type())
// Index of this field within the message's field array, or the file or
// extension scope's extensions array.
@@ -474,6 +476,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
// Helper method to get the CppType for a particular Type.
static CppType TypeToCppType(Type type);
+ // Return true iff [packed = true] is valid for fields of this type.
+ static inline bool IsTypePackable(Type field_type);
+
private:
typedef FieldOptions OptionsType;
@@ -1069,10 +1074,6 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
// These methods may contain hidden pitfalls and may be removed in a
// future library version.
- // DEPRECATED: Use of underlays can lead to many subtle gotchas. Instead,
- // try to formulate what you want to do in terms of DescriptorDatabases.
- // This constructor will be removed soon.
- //
// Create a DescriptorPool which is overlaid on top of some other pool.
// If you search for a descriptor in the overlay and it is not found, the
// underlay will be searched as a backup. If the underlay has its own
@@ -1090,6 +1091,9 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
// types directly into generated_pool(): this is not allowed, and would be
// bad design anyway. So, instead, you could use generated_pool() as an
// underlay for a new DescriptorPool in which you add only the new file.
+ //
+ // WARNING: Use of underlays can lead to many subtle gotchas. Instead,
+ // try to formulate what you want to do in terms of DescriptorDatabases.
explicit DescriptorPool(const DescriptorPool* underlay);
// Called by generated classes at init time to add their descriptors to
@@ -1294,6 +1298,10 @@ inline bool FieldDescriptor::is_repeated() const {
return label() == LABEL_REPEATED;
}
+inline bool FieldDescriptor::is_packable() const {
+ return is_repeated() && IsTypePackable(type());
+}
+
// To save space, index() is computed by looking at the descriptor's position
// in the parent's array of children.
inline int FieldDescriptor::index() const {
@@ -1342,6 +1350,13 @@ inline FieldDescriptor::CppType FieldDescriptor::TypeToCppType(Type type) {
return kTypeToCppTypeMap[type];
}
+inline bool FieldDescriptor::IsTypePackable(Type field_type) {
+ return (field_type != FieldDescriptor::TYPE_STRING &&
+ field_type != FieldDescriptor::TYPE_GROUP &&
+ field_type != FieldDescriptor::TYPE_MESSAGE &&
+ field_type != FieldDescriptor::TYPE_BYTES);
+}
+
inline const FileDescriptor* FileDescriptor::dependency(int index) const {
return dependencies_[index];
}
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 276c6009..f61e7cd0 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -8,6 +8,7 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
namespace google {
namespace protobuf {
@@ -250,11 +251,14 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
::google::protobuf::MessageFactory::generated_factory(),
sizeof(MethodDescriptorProto));
FileOptions_descriptor_ = file->message_type(8);
- static const int FileOptions_offsets_[5] = {
+ static const int FileOptions_offsets_[8] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, optimize_for_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_generic_services_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generic_services_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_),
};
FileOptions_reflection_ =
@@ -552,43 +556,47 @@ 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\"\271\002\n\013FileOptions\022\024\n\014java_"
+ "f.MethodOptions\"\244\003\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\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\"`\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);
+ "FileOptions.OptimizeMode:\005SPEED\022!\n\023cc_ge"
+ "neric_services\030\020 \001(\010:\004true\022#\n\025java_gener"
+ "ic_services\030\021 \001(\010:\004true\022!\n\023py_generic_se"
+ "rvices\030\022 \001(\010:\004true\022C\n\024uninterpreted_opti"
+ "on\030\347\007 \003(\0132$.google.protobuf.Uninterprete"
+ "dOption\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCO"
+ "DE_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\027message_set_wire_fo"
+ "rmat\030\001 \001(\010:\005false\022.\n\037no_standard_descrip"
+ "tor_accessor\030\002 \001(\010:\005false\022C\n\024uninterpret"
+ "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint"
+ "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"\224\002\n\014FieldOptio"
+ "ns\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Fiel"
+ "dOptions.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\031"
+ "\n\ndeprecated\030\003 \001(\010:\005false\022\034\n\024experimenta"
+ "l_map_key\030\t \001(\t\022C\n\024uninterpreted_option\030"
+ "\347\007 \003(\0132$.google.protobuf.UninterpretedOp"
+ "tion\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014S"
+ "TRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022"
+ "C\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\024uninterpreted_opt"
+ "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret"
+ "edOption*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceOptions\022C\n"
+ "\024uninterpreted_option\030\347\007 \003(\0132$.google.pr"
+ "otobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"_\n"
+ "\rMethodOptions\022C\n\024uninterpreted_option\030\347"
+ "\007 \003(\0132$.google.protobuf.UninterpretedOpt"
+ "ion*\t\010\350\007\020\200\200\200\200\002\"\205\002\n\023UninterpretedOption\022;"
+ "\n\004name\030\002 \003(\0132-.google.protobuf.Uninterpr"
+ "etedOption.NamePart\022\030\n\020identifier_value\030"
+ "\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022neg"
+ "ative_int_value\030\005 \001(\003\022\024\n\014double_value\030\006 "
+ "\001(\001\022\024\n\014string_value\030\007 \001(\014\0323\n\010NamePart\022\021\n"
+ "\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010B)"
+ "\n\023com.google.protobufB\020DescriptorProtosH"
+ "\001", 3681);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -645,7 +653,7 @@ const int FileDescriptorSet::kFileFieldNumber;
#endif // !_MSC_VER
FileDescriptorSet::FileDescriptorSet()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -653,7 +661,7 @@ void FileDescriptorSet::InitAsDefaultInstance() {
}
FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -672,6 +680,11 @@ void FileDescriptorSet::SharedDtor() {
}
}
+void FileDescriptorSet::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* FileDescriptorSet::descriptor() {
protobuf_AssignDescriptorsOnce();
return FileDescriptorSet_descriptor_;
@@ -701,13 +714,14 @@ bool FileDescriptorSet::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// repeated .google.protobuf.FileDescriptorProto file = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_file:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_file()));
+ } else {
goto handle_uninterpreted;
}
- parse_file:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, add_file()));
if (input->ExpectTag(10)) goto parse_file;
if (input->ExpectAtEnd()) return true;
break;
@@ -731,15 +745,9 @@ bool FileDescriptorSet::MergePartialFromCodedStream(
void FileDescriptorSet::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- FileDescriptorSet::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// repeated .google.protobuf.FileDescriptorProto file = 1;
for (int i = 0; i < this->file_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
1, this->file(i), output);
}
@@ -781,7 +789,9 @@ int FileDescriptorSet::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -857,7 +867,7 @@ const int FileDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
FileDescriptorProto::FileDescriptorProto()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -866,7 +876,7 @@ void FileDescriptorProto::InitAsDefaultInstance() {
}
FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -895,6 +905,11 @@ void FileDescriptorProto::SharedDtor() {
}
}
+void FileDescriptorProto::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* FileDescriptorProto::descriptor() {
protobuf_AssignDescriptorsOnce();
return FileDescriptorProto_descriptor_;
@@ -943,47 +958,50 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ 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);
+ } else {
goto handle_uninterpreted;
}
- 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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_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);
+ } else {
goto handle_uninterpreted;
}
- parse_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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_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);
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -991,13 +1009,14 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.DescriptorProto message_type = 4;
case 4: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_message_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_message_type()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -1005,13 +1024,14 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
case 5: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_enum_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_enum_type()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -1019,13 +1039,14 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
case 6: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_service:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_service()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -1033,13 +1054,14 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
case 7: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_extension:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_extension()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -1047,13 +1069,14 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// optional .google.protobuf.FileOptions options = 8;
case 8: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_options()));
+ } else {
goto handle_uninterpreted;
}
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_options()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -1076,12 +1099,6 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
void FileDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- FileDescriptorProto::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string name = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -1111,31 +1128,31 @@ void FileDescriptorProto::SerializeWithCachedSizes(
// repeated .google.protobuf.DescriptorProto message_type = 4;
for (int i = 0; i < this->message_type_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
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::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
5, this->enum_type(i), output);
}
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
for (int i = 0; i < this->service_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
6, this->service(i), output);
}
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
for (int i = 0; i < this->extension_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
7, this->extension(i), output);
}
// optional .google.protobuf.FileOptions options = 8;
if (_has_bit(7)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
8, this->options(), output);
}
@@ -1288,7 +1305,9 @@ int FileDescriptorProto::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -1390,7 +1409,7 @@ const int DescriptorProto_ExtensionRange::kEndFieldNumber;
#endif // !_MSC_VER
DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -1398,7 +1417,7 @@ void DescriptorProto_ExtensionRange::InitAsDefaultInstance() {
}
DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -1419,6 +1438,11 @@ void DescriptorProto_ExtensionRange::SharedDtor() {
}
}
+void DescriptorProto_ExtensionRange::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange::descriptor() {
protobuf_AssignDescriptorsOnce();
return DescriptorProto_ExtensionRange_descriptor_;
@@ -1451,27 +1475,31 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional int32 start = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &start_)));
+ _set_bit(0);
+ } else {
goto handle_uninterpreted;
}
- DO_(::google::protobuf::internal::WireFormatLite::ReadInt32(
- input, &start_));
- _set_bit(0);
if (input->ExpectTag(16)) goto parse_end;
break;
}
// optional int32 end = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_end:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &end_)));
+ _set_bit(1);
+ } else {
goto handle_uninterpreted;
}
- parse_end:
- DO_(::google::protobuf::internal::WireFormatLite::ReadInt32(
- input, &end_));
- _set_bit(1);
if (input->ExpectAtEnd()) return true;
break;
}
@@ -1494,12 +1522,6 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream(
void DescriptorProto_ExtensionRange::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- DescriptorProto_ExtensionRange::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional int32 start = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output);
@@ -1559,7 +1581,9 @@ int DescriptorProto_ExtensionRange::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -1638,7 +1662,7 @@ const int DescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
DescriptorProto::DescriptorProto()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -1647,7 +1671,7 @@ void DescriptorProto::InitAsDefaultInstance() {
}
DescriptorProto::DescriptorProto(const DescriptorProto& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -1672,6 +1696,11 @@ void DescriptorProto::SharedDtor() {
}
}
+void DescriptorProto::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* DescriptorProto::descriptor() {
protobuf_AssignDescriptorsOnce();
return DescriptorProto_descriptor_;
@@ -1715,28 +1744,30 @@ bool DescriptorProto::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ 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);
+ } else {
goto handle_uninterpreted;
}
- 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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_field:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_field()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -1744,13 +1775,14 @@ bool DescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.DescriptorProto nested_type = 3;
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_nested_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_nested_type()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -1758,13 +1790,14 @@ bool DescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
case 4: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_enum_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_enum_type()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -1772,13 +1805,14 @@ bool DescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
case 5: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_extension_range:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_extension_range()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -1786,13 +1820,14 @@ bool DescriptorProto::MergePartialFromCodedStream(
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
case 6: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_extension:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_extension()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -1800,13 +1835,14 @@ bool DescriptorProto::MergePartialFromCodedStream(
// optional .google.protobuf.MessageOptions options = 7;
case 7: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_options()));
+ } else {
goto handle_uninterpreted;
}
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_options()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -1829,12 +1865,6 @@ bool DescriptorProto::MergePartialFromCodedStream(
void DescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- DescriptorProto::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string name = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -1846,37 +1876,37 @@ void DescriptorProto::SerializeWithCachedSizes(
// repeated .google.protobuf.FieldDescriptorProto field = 2;
for (int i = 0; i < this->field_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
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::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
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::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
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::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
5, this->extension_range(i), output);
}
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
for (int i = 0; i < this->extension_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
6, this->extension(i), output);
}
// optional .google.protobuf.MessageOptions options = 7;
if (_has_bit(6)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
7, this->options(), output);
}
@@ -2011,7 +2041,9 @@ int DescriptorProto::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -2154,6 +2186,7 @@ const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT32;
const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT64;
const FieldDescriptorProto_Type FieldDescriptorProto::Type_MIN;
const FieldDescriptorProto_Type FieldDescriptorProto::Type_MAX;
+const int FieldDescriptorProto::Type_ARRAYSIZE;
#endif // _MSC_VER
const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor() {
protobuf_AssignDescriptorsOnce();
@@ -2176,6 +2209,7 @@ const FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REQUIRED;
const FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REPEATED;
const FieldDescriptorProto_Label FieldDescriptorProto::Label_MIN;
const FieldDescriptorProto_Label FieldDescriptorProto::Label_MAX;
+const int FieldDescriptorProto::Label_ARRAYSIZE;
#endif // _MSC_VER
const ::std::string FieldDescriptorProto::_default_name_;
const ::std::string FieldDescriptorProto::_default_type_name_;
@@ -2193,7 +2227,7 @@ const int FieldDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
FieldDescriptorProto::FieldDescriptorProto()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -2202,7 +2236,7 @@ void FieldDescriptorProto::InitAsDefaultInstance() {
}
FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -2242,6 +2276,11 @@ void FieldDescriptorProto::SharedDtor() {
}
}
+void FieldDescriptorProto::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* FieldDescriptorProto::descriptor() {
protobuf_AssignDescriptorsOnce();
return FieldDescriptorProto_descriptor_;
@@ -2298,62 +2337,69 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ 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);
+ } else {
goto handle_uninterpreted;
}
- 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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_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);
+ } else {
goto handle_uninterpreted;
}
- parse_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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_number:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &number_)));
+ _set_bit(1);
+ } else {
goto handle_uninterpreted;
}
- parse_number:
- DO_(::google::protobuf::internal::WireFormatLite::ReadInt32(
- input, &number_));
- _set_bit(1);
if (input->ExpectTag(32)) goto parse_label;
break;
}
// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
case 4: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- goto handle_uninterpreted;
- }
- parse_label:
- int 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));
+ parse_label:
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ if (::google::protobuf::FieldDescriptorProto_Label_IsValid(value)) {
+ set_label(static_cast< ::google::protobuf::FieldDescriptorProto_Label >(value));
+ } else {
+ mutable_unknown_fields()->AddVarint(4, value);
+ }
} else {
- mutable_unknown_fields()->AddVarint(4, value);
+ goto handle_uninterpreted;
}
if (input->ExpectTag(40)) goto parse_type;
break;
@@ -2361,17 +2407,20 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
case 5: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- goto handle_uninterpreted;
- }
- parse_type:
- int 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));
+ parse_type:
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ if (::google::protobuf::FieldDescriptorProto_Type_IsValid(value)) {
+ set_type(static_cast< ::google::protobuf::FieldDescriptorProto_Type >(value));
+ } else {
+ mutable_unknown_fields()->AddVarint(5, value);
+ }
} else {
- mutable_unknown_fields()->AddVarint(5, value);
+ goto handle_uninterpreted;
}
if (input->ExpectTag(50)) goto parse_type_name;
break;
@@ -2379,45 +2428,48 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
// optional string type_name = 6;
case 6: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_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);
+ } else {
goto handle_uninterpreted;
}
- parse_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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_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);
+ } else {
goto handle_uninterpreted;
}
- parse_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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_options()));
+ } else {
goto handle_uninterpreted;
}
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_options()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -2440,12 +2492,6 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
void FieldDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- FieldDescriptorProto::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string name = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2501,7 +2547,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
// optional .google.protobuf.FieldOptions options = 8;
if (_has_bit(7)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
8, this->options(), output);
}
@@ -2648,7 +2694,9 @@ int FieldDescriptorProto::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -2750,7 +2798,7 @@ const int EnumDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
EnumDescriptorProto::EnumDescriptorProto()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -2759,7 +2807,7 @@ void EnumDescriptorProto::InitAsDefaultInstance() {
}
EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -2784,6 +2832,11 @@ void EnumDescriptorProto::SharedDtor() {
}
}
+void EnumDescriptorProto::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* EnumDescriptorProto::descriptor() {
protobuf_AssignDescriptorsOnce();
return EnumDescriptorProto_descriptor_;
@@ -2823,28 +2876,30 @@ bool EnumDescriptorProto::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ 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);
+ } else {
goto handle_uninterpreted;
}
- 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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_value:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_value()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -2852,13 +2907,14 @@ bool EnumDescriptorProto::MergePartialFromCodedStream(
// optional .google.protobuf.EnumOptions options = 3;
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_options()));
+ } else {
goto handle_uninterpreted;
}
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_options()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -2881,12 +2937,6 @@ bool EnumDescriptorProto::MergePartialFromCodedStream(
void EnumDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- EnumDescriptorProto::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string name = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -2898,13 +2948,13 @@ void EnumDescriptorProto::SerializeWithCachedSizes(
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
for (int i = 0; i < this->value_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
2, this->value(i), output);
}
// optional .google.protobuf.EnumOptions options = 3;
if (_has_bit(2)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
3, this->options(), output);
}
@@ -2979,7 +3029,9 @@ int EnumDescriptorProto::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -3062,7 +3114,7 @@ const int EnumValueDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
EnumValueDescriptorProto::EnumValueDescriptorProto()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -3071,7 +3123,7 @@ void EnumValueDescriptorProto::InitAsDefaultInstance() {
}
EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProto& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -3097,6 +3149,11 @@ void EnumValueDescriptorProto::SharedDtor() {
}
}
+void EnumValueDescriptorProto::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* EnumValueDescriptorProto::descriptor() {
protobuf_AssignDescriptorsOnce();
return EnumValueDescriptorProto_descriptor_;
@@ -3136,42 +3193,46 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ 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);
+ } else {
goto handle_uninterpreted;
}
- 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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_number:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &number_)));
+ _set_bit(1);
+ } else {
goto handle_uninterpreted;
}
- parse_number:
- DO_(::google::protobuf::internal::WireFormatLite::ReadInt32(
- input, &number_));
- _set_bit(1);
if (input->ExpectTag(26)) goto parse_options;
break;
}
// optional .google.protobuf.EnumValueOptions options = 3;
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_options()));
+ } else {
goto handle_uninterpreted;
}
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_options()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -3194,12 +3255,6 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream(
void EnumValueDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- EnumValueDescriptorProto::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string name = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -3216,7 +3271,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes(
// optional .google.protobuf.EnumValueOptions options = 3;
if (_has_bit(2)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
3, this->options(), output);
}
@@ -3288,7 +3343,9 @@ int EnumValueDescriptorProto::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -3370,7 +3427,7 @@ const int ServiceDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
ServiceDescriptorProto::ServiceDescriptorProto()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -3379,7 +3436,7 @@ void ServiceDescriptorProto::InitAsDefaultInstance() {
}
ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -3404,6 +3461,11 @@ void ServiceDescriptorProto::SharedDtor() {
}
}
+void ServiceDescriptorProto::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* ServiceDescriptorProto::descriptor() {
protobuf_AssignDescriptorsOnce();
return ServiceDescriptorProto_descriptor_;
@@ -3443,28 +3505,30 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ 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);
+ } else {
goto handle_uninterpreted;
}
- 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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_method:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_method()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -3472,13 +3536,14 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream(
// optional .google.protobuf.ServiceOptions options = 3;
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_options()));
+ } else {
goto handle_uninterpreted;
}
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_options()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -3501,12 +3566,6 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream(
void ServiceDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- ServiceDescriptorProto::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string name = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -3518,13 +3577,13 @@ void ServiceDescriptorProto::SerializeWithCachedSizes(
// repeated .google.protobuf.MethodDescriptorProto method = 2;
for (int i = 0; i < this->method_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
2, this->method(i), output);
}
// optional .google.protobuf.ServiceOptions options = 3;
if (_has_bit(2)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
3, this->options(), output);
}
@@ -3599,7 +3658,9 @@ int ServiceDescriptorProto::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -3685,7 +3746,7 @@ const int MethodDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
MethodDescriptorProto::MethodDescriptorProto()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -3694,7 +3755,7 @@ void MethodDescriptorProto::InitAsDefaultInstance() {
}
MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -3727,6 +3788,11 @@ void MethodDescriptorProto::SharedDtor() {
}
}
+void MethodDescriptorProto::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* MethodDescriptorProto::descriptor() {
protobuf_AssignDescriptorsOnce();
return MethodDescriptorProto_descriptor_;
@@ -3775,60 +3841,64 @@ bool MethodDescriptorProto::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string name = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ 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);
+ } else {
goto handle_uninterpreted;
}
- 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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_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);
+ } else {
goto handle_uninterpreted;
}
- parse_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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_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);
+ } else {
goto handle_uninterpreted;
}
- parse_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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, mutable_options()));
+ } else {
goto handle_uninterpreted;
}
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
- input, mutable_options()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -3851,12 +3921,6 @@ bool MethodDescriptorProto::MergePartialFromCodedStream(
void MethodDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- MethodDescriptorProto::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string name = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -3886,7 +3950,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
// optional .google.protobuf.MethodOptions options = 4;
if (_has_bit(3)) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
4, this->options(), output);
}
@@ -3980,7 +4044,9 @@ int MethodDescriptorProto::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -4079,6 +4145,7 @@ const FileOptions_OptimizeMode FileOptions::CODE_SIZE;
const FileOptions_OptimizeMode FileOptions::LITE_RUNTIME;
const FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN;
const FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX;
+const int FileOptions::OptimizeMode_ARRAYSIZE;
#endif // _MSC_VER
const ::std::string FileOptions::_default_java_package_;
const ::std::string FileOptions::_default_java_outer_classname_;
@@ -4087,11 +4154,14 @@ const int FileOptions::kJavaPackageFieldNumber;
const int FileOptions::kJavaOuterClassnameFieldNumber;
const int FileOptions::kJavaMultipleFilesFieldNumber;
const int FileOptions::kOptimizeForFieldNumber;
+const int FileOptions::kCcGenericServicesFieldNumber;
+const int FileOptions::kJavaGenericServicesFieldNumber;
+const int FileOptions::kPyGenericServicesFieldNumber;
const int FileOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
FileOptions::FileOptions()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -4099,7 +4169,7 @@ void FileOptions::InitAsDefaultInstance() {
}
FileOptions::FileOptions(const FileOptions& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -4110,6 +4180,9 @@ void FileOptions::SharedCtor() {
java_outer_classname_ = const_cast< ::std::string*>(&_default_java_outer_classname_);
java_multiple_files_ = false;
optimize_for_ = 1;
+ cc_generic_services_ = true;
+ java_generic_services_ = true;
+ py_generic_services_ = true;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -4128,6 +4201,11 @@ void FileOptions::SharedDtor() {
}
}
+void FileOptions::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* FileOptions::descriptor() {
protobuf_AssignDescriptorsOnce();
return FileOptions_descriptor_;
@@ -4158,6 +4236,9 @@ void FileOptions::Clear() {
}
java_multiple_files_ = false;
optimize_for_ = 1;
+ cc_generic_services_ = true;
+ java_generic_services_ = true;
+ py_generic_services_ = true;
}
uninterpreted_option_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -4172,48 +4253,53 @@ bool FileOptions::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string java_package = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ 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);
+ } else {
goto handle_uninterpreted;
}
- 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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_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);
+ } else {
goto handle_uninterpreted;
}
- parse_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::WireFormatLite::GetTagWireType(tag) !=
+ 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::WireFormatLite::ReadEnum(input, &value));
- if (::google::protobuf::FileOptions_OptimizeMode_IsValid(value)) {
- set_optimize_for(static_cast< ::google::protobuf::FileOptions_OptimizeMode >(value));
+ parse_optimize_for:
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ if (::google::protobuf::FileOptions_OptimizeMode_IsValid(value)) {
+ set_optimize_for(static_cast< ::google::protobuf::FileOptions_OptimizeMode >(value));
+ } else {
+ mutable_unknown_fields()->AddVarint(9, value);
+ }
} else {
- mutable_unknown_fields()->AddVarint(9, value);
+ goto handle_uninterpreted;
}
if (input->ExpectTag(80)) goto parse_java_multiple_files;
break;
@@ -4221,27 +4307,78 @@ bool FileOptions::MergePartialFromCodedStream(
// optional bool java_multiple_files = 10 [default = false];
case 10: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_java_multiple_files:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &java_multiple_files_)));
+ _set_bit(2);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(128)) goto parse_cc_generic_services;
+ break;
+ }
+
+ // optional bool cc_generic_services = 16 [default = true];
+ case 16: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_cc_generic_services:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &cc_generic_services_)));
+ _set_bit(4);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(136)) goto parse_java_generic_services;
+ break;
+ }
+
+ // optional bool java_generic_services = 17 [default = true];
+ case 17: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_java_generic_services:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &java_generic_services_)));
+ _set_bit(5);
+ } else {
+ goto handle_uninterpreted;
+ }
+ if (input->ExpectTag(144)) goto parse_py_generic_services;
+ break;
+ }
+
+ // optional bool py_generic_services = 18 [default = true];
+ case 18: {
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_py_generic_services:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &py_generic_services_)));
+ _set_bit(6);
+ } else {
goto handle_uninterpreted;
}
- parse_java_multiple_files:
- DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
- input, &java_multiple_files_));
- _set_bit(2);
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
break;
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_uninterpreted_option()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -4270,12 +4407,6 @@ bool FileOptions::MergePartialFromCodedStream(
void FileOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- FileOptions::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional string java_package = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -4305,9 +4436,24 @@ void FileOptions::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteBool(10, this->java_multiple_files(), output);
}
+ // optional bool cc_generic_services = 16 [default = true];
+ if (_has_bit(4)) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(16, this->cc_generic_services(), output);
+ }
+
+ // optional bool java_generic_services = 17 [default = true];
+ if (_has_bit(5)) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(17, this->java_generic_services(), output);
+ }
+
+ // optional bool py_generic_services = 18 [default = true];
+ if (_has_bit(6)) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(18, this->py_generic_services(), output);
+ }
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
@@ -4354,6 +4500,21 @@ void FileOptions::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->java_multiple_files(), target);
}
+ // optional bool cc_generic_services = 16 [default = true];
+ if (_has_bit(4)) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(16, this->cc_generic_services(), target);
+ }
+
+ // optional bool java_generic_services = 17 [default = true];
+ if (_has_bit(5)) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(17, this->java_generic_services(), target);
+ }
+
+ // optional bool py_generic_services = 18 [default = true];
+ if (_has_bit(6)) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(18, this->py_generic_services(), target);
+ }
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
@@ -4401,6 +4562,21 @@ int FileOptions::ByteSize() const {
::google::protobuf::internal::WireFormatLite::EnumSize(this->optimize_for());
}
+ // optional bool cc_generic_services = 16 [default = true];
+ if (has_cc_generic_services()) {
+ total_size += 2 + 1;
+ }
+
+ // optional bool java_generic_services = 17 [default = true];
+ if (has_java_generic_services()) {
+ total_size += 2 + 1;
+ }
+
+ // optional bool py_generic_services = 18 [default = true];
+ if (has_py_generic_services()) {
+ total_size += 2 + 1;
+ }
+
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
total_size += 2 * this->uninterpreted_option_size();
@@ -4417,7 +4593,9 @@ int FileOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -4449,6 +4627,15 @@ void FileOptions::MergeFrom(const FileOptions& from) {
if (from._has_bit(3)) {
set_optimize_for(from.optimize_for());
}
+ if (from._has_bit(4)) {
+ set_cc_generic_services(from.cc_generic_services());
+ }
+ if (from._has_bit(5)) {
+ set_java_generic_services(from.java_generic_services());
+ }
+ if (from._has_bit(6)) {
+ set_py_generic_services(from.py_generic_services());
+ }
}
_extensions_.MergeFrom(from._extensions_);
mutable_unknown_fields()->MergeFrom(from.unknown_fields());
@@ -4481,6 +4668,9 @@ void FileOptions::Swap(FileOptions* other) {
std::swap(java_outer_classname_, other->java_outer_classname_);
std::swap(java_multiple_files_, other->java_multiple_files_);
std::swap(optimize_for_, other->optimize_for_);
+ std::swap(cc_generic_services_, other->cc_generic_services_);
+ std::swap(java_generic_services_, other->java_generic_services_);
+ std::swap(py_generic_services_, other->py_generic_services_);
uninterpreted_option_.Swap(&other->uninterpreted_option_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_unknown_fields_.Swap(&other->_unknown_fields_);
@@ -4507,7 +4697,7 @@ const int MessageOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
MessageOptions::MessageOptions()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -4515,7 +4705,7 @@ void MessageOptions::InitAsDefaultInstance() {
}
MessageOptions::MessageOptions(const MessageOptions& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -4536,6 +4726,11 @@ void MessageOptions::SharedDtor() {
}
}
+void MessageOptions::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* MessageOptions::descriptor() {
protobuf_AssignDescriptorsOnce();
return MessageOptions_descriptor_;
@@ -4570,40 +4765,45 @@ bool MessageOptions::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional bool message_set_wire_format = 1 [default = false];
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &message_set_wire_format_)));
+ _set_bit(0);
+ } else {
goto handle_uninterpreted;
}
- 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) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_no_standard_descriptor_accessor:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &no_standard_descriptor_accessor_)));
+ _set_bit(1);
+ } else {
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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_uninterpreted_option()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -4632,12 +4832,6 @@ bool MessageOptions::MergePartialFromCodedStream(
void MessageOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- MessageOptions::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// optional bool message_set_wire_format = 1 [default = false];
if (_has_bit(0)) {
::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output);
@@ -4650,7 +4844,7 @@ void MessageOptions::SerializeWithCachedSizes(
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
@@ -4724,7 +4918,9 @@ int MessageOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -4805,6 +5001,7 @@ const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor() {
}
bool FieldOptions_CType_IsValid(int value) {
switch(value) {
+ case 0:
case 1:
case 2:
return true;
@@ -4814,10 +5011,12 @@ bool FieldOptions_CType_IsValid(int value) {
}
#ifndef _MSC_VER
+const FieldOptions_CType FieldOptions::STRING;
const FieldOptions_CType FieldOptions::CORD;
const FieldOptions_CType FieldOptions::STRING_PIECE;
const FieldOptions_CType FieldOptions::CType_MIN;
const FieldOptions_CType FieldOptions::CType_MAX;
+const int FieldOptions::CType_ARRAYSIZE;
#endif // _MSC_VER
const ::std::string FieldOptions::_default_experimental_map_key_;
#ifndef _MSC_VER
@@ -4829,7 +5028,7 @@ const int FieldOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
FieldOptions::FieldOptions()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -4837,14 +5036,14 @@ void FieldOptions::InitAsDefaultInstance() {
}
FieldOptions::FieldOptions(const FieldOptions& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
void FieldOptions::SharedCtor() {
_cached_size_ = 0;
- ctype_ = 1;
+ ctype_ = 0;
packed_ = false;
deprecated_ = false;
experimental_map_key_ = const_cast< ::std::string*>(&_default_experimental_map_key_);
@@ -4863,6 +5062,11 @@ void FieldOptions::SharedDtor() {
}
}
+void FieldOptions::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* FieldOptions::descriptor() {
protobuf_AssignDescriptorsOnce();
return FieldOptions_descriptor_;
@@ -4881,7 +5085,7 @@ FieldOptions* FieldOptions::New() const {
void FieldOptions::Clear() {
_extensions_.Clear();
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- ctype_ = 1;
+ ctype_ = 0;
packed_ = false;
deprecated_ = false;
if (_has_bit(3)) {
@@ -4901,18 +5105,21 @@ bool FieldOptions::MergePartialFromCodedStream(
::google::protobuf::uint32 tag;
while ((tag = input->ReadTag()) != 0) {
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
- // optional .google.protobuf.FieldOptions.CType ctype = 1;
+ // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
- goto handle_uninterpreted;
- }
- int 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));
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ if (::google::protobuf::FieldOptions_CType_IsValid(value)) {
+ set_ctype(static_cast< ::google::protobuf::FieldOptions_CType >(value));
+ } else {
+ mutable_unknown_fields()->AddVarint(1, value);
+ }
} else {
- mutable_unknown_fields()->AddVarint(1, value);
+ goto handle_uninterpreted;
}
if (input->ExpectTag(16)) goto parse_packed;
break;
@@ -4920,57 +5127,63 @@ bool FieldOptions::MergePartialFromCodedStream(
// optional bool packed = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_packed:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &packed_)));
+ _set_bit(1);
+ } else {
goto handle_uninterpreted;
}
- parse_packed:
- DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
- input, &packed_));
- _set_bit(1);
if (input->ExpectTag(24)) goto parse_deprecated;
break;
}
// optional bool deprecated = 3 [default = false];
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_deprecated:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &deprecated_)));
+ _set_bit(2);
+ } else {
goto handle_uninterpreted;
}
- parse_deprecated:
- DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
- input, &deprecated_));
- _set_bit(2);
if (input->ExpectTag(74)) goto parse_experimental_map_key;
break;
}
// optional string experimental_map_key = 9;
case 9: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_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);
+ } else {
goto handle_uninterpreted;
}
- parse_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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_uninterpreted_option()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -4999,13 +5212,7 @@ bool FieldOptions::MergePartialFromCodedStream(
void FieldOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- FieldOptions::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
- // optional .google.protobuf.FieldOptions.CType ctype = 1;
+ // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
if (_has_bit(0)) {
::google::protobuf::internal::WireFormatLite::WriteEnum(
1, this->ctype(), output);
@@ -5032,7 +5239,7 @@ void FieldOptions::SerializeWithCachedSizes(
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
@@ -5048,7 +5255,7 @@ void FieldOptions::SerializeWithCachedSizes(
::google::protobuf::uint8* FieldOptions::SerializeWithCachedSizesToArray(
::google::protobuf::uint8* target) const {
- // optional .google.protobuf.FieldOptions.CType ctype = 1;
+ // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
if (_has_bit(0)) {
target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
1, this->ctype(), target);
@@ -5096,7 +5303,7 @@ int FieldOptions::ByteSize() const {
int total_size = 0;
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- // optional .google.protobuf.FieldOptions.CType ctype = 1;
+ // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
if (has_ctype()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::EnumSize(this->ctype());
@@ -5135,7 +5342,9 @@ int FieldOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -5223,7 +5432,7 @@ const int EnumOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
EnumOptions::EnumOptions()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -5231,7 +5440,7 @@ void EnumOptions::InitAsDefaultInstance() {
}
EnumOptions::EnumOptions(const EnumOptions& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -5250,6 +5459,11 @@ void EnumOptions::SharedDtor() {
}
}
+void EnumOptions::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* EnumOptions::descriptor() {
protobuf_AssignDescriptorsOnce();
return EnumOptions_descriptor_;
@@ -5280,13 +5494,14 @@ bool EnumOptions::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_uninterpreted_option()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -5315,15 +5530,9 @@ bool EnumOptions::MergePartialFromCodedStream(
void EnumOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- EnumOptions::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
@@ -5375,7 +5584,9 @@ int EnumOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -5445,7 +5656,7 @@ const int EnumValueOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
EnumValueOptions::EnumValueOptions()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -5453,7 +5664,7 @@ void EnumValueOptions::InitAsDefaultInstance() {
}
EnumValueOptions::EnumValueOptions(const EnumValueOptions& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -5472,6 +5683,11 @@ void EnumValueOptions::SharedDtor() {
}
}
+void EnumValueOptions::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* EnumValueOptions::descriptor() {
protobuf_AssignDescriptorsOnce();
return EnumValueOptions_descriptor_;
@@ -5502,13 +5718,14 @@ bool EnumValueOptions::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_uninterpreted_option()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -5537,15 +5754,9 @@ bool EnumValueOptions::MergePartialFromCodedStream(
void EnumValueOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- EnumValueOptions::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
@@ -5597,7 +5808,9 @@ int EnumValueOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -5667,7 +5880,7 @@ const int ServiceOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
ServiceOptions::ServiceOptions()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -5675,7 +5888,7 @@ void ServiceOptions::InitAsDefaultInstance() {
}
ServiceOptions::ServiceOptions(const ServiceOptions& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -5694,6 +5907,11 @@ void ServiceOptions::SharedDtor() {
}
}
+void ServiceOptions::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* ServiceOptions::descriptor() {
protobuf_AssignDescriptorsOnce();
return ServiceOptions_descriptor_;
@@ -5724,13 +5942,14 @@ bool ServiceOptions::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_uninterpreted_option()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -5759,15 +5978,9 @@ bool ServiceOptions::MergePartialFromCodedStream(
void ServiceOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- ServiceOptions::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
@@ -5819,7 +6032,9 @@ int ServiceOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -5889,7 +6104,7 @@ const int MethodOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
MethodOptions::MethodOptions()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -5897,7 +6112,7 @@ void MethodOptions::InitAsDefaultInstance() {
}
MethodOptions::MethodOptions(const MethodOptions& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -5916,6 +6131,11 @@ void MethodOptions::SharedDtor() {
}
}
+void MethodOptions::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* MethodOptions::descriptor() {
protobuf_AssignDescriptorsOnce();
return MethodOptions_descriptor_;
@@ -5946,13 +6166,14 @@ bool MethodOptions::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
case 999: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_uninterpreted_option()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -5981,15 +6202,9 @@ bool MethodOptions::MergePartialFromCodedStream(
void MethodOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- MethodOptions::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
999, this->uninterpreted_option(i), output);
}
@@ -6041,7 +6256,9 @@ int MethodOptions::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -6113,7 +6330,7 @@ const int UninterpretedOption_NamePart::kIsExtensionFieldNumber;
#endif // !_MSC_VER
UninterpretedOption_NamePart::UninterpretedOption_NamePart()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -6121,7 +6338,7 @@ void UninterpretedOption_NamePart::InitAsDefaultInstance() {
}
UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -6145,6 +6362,11 @@ void UninterpretedOption_NamePart::SharedDtor() {
}
}
+void UninterpretedOption_NamePart::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* UninterpretedOption_NamePart::descriptor() {
protobuf_AssignDescriptorsOnce();
return UninterpretedOption_NamePart_descriptor_;
@@ -6181,29 +6403,32 @@ bool UninterpretedOption_NamePart::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// required string name_part = 1;
case 1: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ 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);
+ } else {
goto handle_uninterpreted;
}
- 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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_is_extension:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &is_extension_)));
+ _set_bit(1);
+ } else {
goto handle_uninterpreted;
}
- parse_is_extension:
- DO_(::google::protobuf::internal::WireFormatLite::ReadBool(
- input, &is_extension_));
- _set_bit(1);
if (input->ExpectAtEnd()) return true;
break;
}
@@ -6226,12 +6451,6 @@ bool UninterpretedOption_NamePart::MergePartialFromCodedStream(
void UninterpretedOption_NamePart::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- UninterpretedOption_NamePart::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// required string name_part = 1;
if (_has_bit(0)) {
::google::protobuf::internal::WireFormat::VerifyUTF8String(
@@ -6298,7 +6517,9 @@ int UninterpretedOption_NamePart::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -6378,7 +6599,7 @@ const int UninterpretedOption::kStringValueFieldNumber;
#endif // !_MSC_VER
UninterpretedOption::UninterpretedOption()
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
}
@@ -6386,7 +6607,7 @@ void UninterpretedOption::InitAsDefaultInstance() {
}
UninterpretedOption::UninterpretedOption(const UninterpretedOption& from)
- : Message() {
+ : ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
}
@@ -6416,6 +6637,11 @@ void UninterpretedOption::SharedDtor() {
}
}
+void UninterpretedOption::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
const ::google::protobuf::Descriptor* UninterpretedOption::descriptor() {
protobuf_AssignDescriptorsOnce();
return UninterpretedOption_descriptor_;
@@ -6460,13 +6686,14 @@ bool UninterpretedOption::MergePartialFromCodedStream(
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_name:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ input, add_name()));
+ } else {
goto handle_uninterpreted;
}
- parse_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;
@@ -6474,71 +6701,79 @@ bool UninterpretedOption::MergePartialFromCodedStream(
// optional string identifier_value = 3;
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_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);
+ } else {
goto handle_uninterpreted;
}
- parse_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::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_positive_int_value:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
+ input, &positive_int_value_)));
+ _set_bit(2);
+ } else {
goto handle_uninterpreted;
}
- parse_positive_int_value:
- DO_(::google::protobuf::internal::WireFormatLite::ReadUInt64(
- input, &positive_int_value_));
- _set_bit(2);
if (input->ExpectTag(40)) goto parse_negative_int_value;
break;
}
// optional int64 negative_int_value = 5;
case 5: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ parse_negative_int_value:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
+ input, &negative_int_value_)));
+ _set_bit(3);
+ } else {
goto handle_uninterpreted;
}
- parse_negative_int_value:
- DO_(::google::protobuf::internal::WireFormatLite::ReadInt64(
- input, &negative_int_value_));
- _set_bit(3);
if (input->ExpectTag(49)) goto parse_double_value;
break;
}
// optional double double_value = 6;
case 6: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) {
+ parse_double_value:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
+ input, &double_value_)));
+ _set_bit(4);
+ } else {
goto handle_uninterpreted;
}
- parse_double_value:
- DO_(::google::protobuf::internal::WireFormatLite::ReadDouble(
- input, &double_value_));
- _set_bit(4);
if (input->ExpectTag(58)) goto parse_string_value;
break;
}
// optional bytes string_value = 7;
case 7: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+ if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ parse_string_value:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+ input, this->mutable_string_value()));
+ } else {
goto handle_uninterpreted;
}
- parse_string_value:
- DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
- input, this->mutable_string_value()));
if (input->ExpectAtEnd()) return true;
break;
}
@@ -6561,15 +6796,9 @@ bool UninterpretedOption::MergePartialFromCodedStream(
void UninterpretedOption::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
- ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
- if (raw_buffer != NULL) {
- UninterpretedOption::SerializeWithCachedSizesToArray(raw_buffer);
- return;
- }
-
// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
for (int i = 0; i < this->name_size(); i++) {
- ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
2, this->name(i), output);
}
@@ -6708,7 +6937,9 @@ int UninterpretedOption::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
@@ -6790,5 +7021,9 @@ void UninterpretedOption::Swap(UninterpretedOption* other) {
}
+// @@protoc_insertion_point(namespace_scope)
+
} // namespace protobuf
} // namespace google
+
+// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 4bf7369f..7df3ae16 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -1,4 +1,5 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/descriptor.proto
#ifndef PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
#define PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
@@ -22,6 +23,7 @@
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/generated_message_reflection.h>
+// @@protoc_insertion_point(includes)
namespace google {
namespace protobuf {
@@ -73,6 +75,7 @@ enum FieldDescriptorProto_Type {
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;
+const int FieldDescriptorProto_Type_Type_ARRAYSIZE = FieldDescriptorProto_Type_Type_MAX + 1;
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor();
inline const ::std::string& FieldDescriptorProto_Type_Name(FieldDescriptorProto_Type value) {
@@ -92,6 +95,7 @@ enum FieldDescriptorProto_Label {
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;
+const int FieldDescriptorProto_Label_Label_ARRAYSIZE = FieldDescriptorProto_Label_Label_MAX + 1;
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor();
inline const ::std::string& FieldDescriptorProto_Label_Name(FieldDescriptorProto_Label value) {
@@ -111,6 +115,7 @@ enum FileOptions_OptimizeMode {
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_LITE_RUNTIME;
+const int FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE = FileOptions_OptimizeMode_OptimizeMode_MAX + 1;
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor();
inline const ::std::string& FileOptions_OptimizeMode_Name(FileOptions_OptimizeMode value) {
@@ -123,12 +128,14 @@ inline bool FileOptions_OptimizeMode_Parse(
FileOptions_OptimizeMode_descriptor(), name, value);
}
enum FieldOptions_CType {
+ FieldOptions_CType_STRING = 0,
FieldOptions_CType_CORD = 1,
FieldOptions_CType_STRING_PIECE = 2
};
LIBPROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value);
-const FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_CORD;
+const FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_STRING;
const FieldOptions_CType FieldOptions_CType_CType_MAX = FieldOptions_CType_STRING_PIECE;
+const int FieldOptions_CType_CType_ARRAYSIZE = FieldOptions_CType_CType_MAX + 1;
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor();
inline const ::std::string& FieldOptions_CType_Name(FieldOptions_CType value) {
@@ -164,6 +171,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
static const ::google::protobuf::Descriptor* descriptor();
static const FileDescriptorSet& default_instance();
+
void Swap(FileDescriptorSet* other);
// implements Message ----------------------------------------------
@@ -186,7 +194,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -199,12 +207,15 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
inline int file_size() const;
inline void clear_file();
static const int kFileFieldNumber = 1;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& file() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* mutable_file();
inline const ::google::protobuf::FileDescriptorProto& file(int index) const;
inline ::google::protobuf::FileDescriptorProto* mutable_file(int index);
inline ::google::protobuf::FileDescriptorProto* add_file();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+ file() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+ mutable_file();
+ // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -254,6 +265,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
static const ::google::protobuf::Descriptor* descriptor();
static const FileDescriptorProto& default_instance();
+
void Swap(FileDescriptorProto* other);
// implements Message ----------------------------------------------
@@ -276,7 +288,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -309,8 +321,6 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline int dependency_size() const;
inline void clear_dependency();
static const int kDependencyFieldNumber = 3;
- inline const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const;
- inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency();
inline const ::std::string& dependency(int index) const;
inline ::std::string* mutable_dependency(int index);
inline void set_dependency(int index, const ::std::string& value);
@@ -320,46 +330,56 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline void add_dependency(const ::std::string& value);
inline void add_dependency(const char* value);
inline void add_dependency(const char* value, size_t size);
+ inline const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const;
+ inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency();
// repeated .google.protobuf.DescriptorProto message_type = 4;
inline int message_type_size() const;
inline void clear_message_type();
static const int kMessageTypeFieldNumber = 4;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& message_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* mutable_message_type();
inline const ::google::protobuf::DescriptorProto& message_type(int index) const;
inline ::google::protobuf::DescriptorProto* mutable_message_type(int index);
inline ::google::protobuf::DescriptorProto* add_message_type();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+ message_type() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+ mutable_message_type();
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
inline int enum_type_size() const;
inline void clear_enum_type();
static const int kEnumTypeFieldNumber = 5;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& enum_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* mutable_enum_type();
inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
inline ::google::protobuf::EnumDescriptorProto* add_enum_type();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+ enum_type() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+ mutable_enum_type();
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
inline int service_size() const;
inline void clear_service();
static const int kServiceFieldNumber = 6;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& service() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* mutable_service();
inline const ::google::protobuf::ServiceDescriptorProto& service(int index) const;
inline ::google::protobuf::ServiceDescriptorProto* mutable_service(int index);
inline ::google::protobuf::ServiceDescriptorProto* add_service();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+ service() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
+ mutable_service();
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
inline int extension_size() const;
inline void clear_extension();
static const int kExtensionFieldNumber = 7;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& extension() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_extension();
inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
inline ::google::protobuf::FieldDescriptorProto* add_extension();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ extension() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+ mutable_extension();
// optional .google.protobuf.FileOptions options = 8;
inline bool has_options() const;
@@ -368,6 +388,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline const ::google::protobuf::FileOptions& options() const;
inline ::google::protobuf::FileOptions* mutable_options();
+ // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -426,6 +447,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
static const ::google::protobuf::Descriptor* descriptor();
static const DescriptorProto_ExtensionRange& default_instance();
+
void Swap(DescriptorProto_ExtensionRange* other);
// implements Message ----------------------------------------------
@@ -448,7 +470,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -471,6 +493,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
inline ::google::protobuf::int32 end() const;
inline void set_end(::google::protobuf::int32 value);
+ // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -521,6 +544,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const DescriptorProto& default_instance();
+
void Swap(DescriptorProto* other);
// implements Message ----------------------------------------------
@@ -543,7 +567,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -568,51 +592,61 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
inline int field_size() const;
inline void clear_field();
static const int kFieldFieldNumber = 2;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& field() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_field();
inline const ::google::protobuf::FieldDescriptorProto& field(int index) const;
inline ::google::protobuf::FieldDescriptorProto* mutable_field(int index);
inline ::google::protobuf::FieldDescriptorProto* add_field();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ field() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+ mutable_field();
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
inline int extension_size() const;
inline void clear_extension();
static const int kExtensionFieldNumber = 6;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& extension() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_extension();
inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
inline ::google::protobuf::FieldDescriptorProto* add_extension();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ extension() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+ mutable_extension();
// repeated .google.protobuf.DescriptorProto nested_type = 3;
inline int nested_type_size() const;
inline void clear_nested_type();
static const int kNestedTypeFieldNumber = 3;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& nested_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* mutable_nested_type();
inline const ::google::protobuf::DescriptorProto& nested_type(int index) const;
inline ::google::protobuf::DescriptorProto* mutable_nested_type(int index);
inline ::google::protobuf::DescriptorProto* add_nested_type();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+ nested_type() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+ mutable_nested_type();
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
inline int enum_type_size() const;
inline void clear_enum_type();
static const int kEnumTypeFieldNumber = 4;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& enum_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* mutable_enum_type();
inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
inline ::google::protobuf::EnumDescriptorProto* add_enum_type();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+ enum_type() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+ mutable_enum_type();
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
inline int extension_range_size() const;
inline void clear_extension_range();
static const int kExtensionRangeFieldNumber = 5;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& extension_range() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* mutable_extension_range();
inline const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const;
inline ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index);
inline ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+ extension_range() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
+ mutable_extension_range();
// optional .google.protobuf.MessageOptions options = 7;
inline bool has_options() const;
@@ -621,6 +655,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
inline const ::google::protobuf::MessageOptions& options() const;
inline ::google::protobuf::MessageOptions* mutable_options();
+ // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -677,6 +712,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
static const ::google::protobuf::Descriptor* descriptor();
static const FieldDescriptorProto& default_instance();
+
void Swap(FieldDescriptorProto* other);
// implements Message ----------------------------------------------
@@ -699,7 +735,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -732,6 +768,8 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
FieldDescriptorProto_Type_Type_MIN;
static const Type Type_MAX =
FieldDescriptorProto_Type_Type_MAX;
+ static const int Type_ARRAYSIZE =
+ FieldDescriptorProto_Type_Type_ARRAYSIZE;
static inline const ::google::protobuf::EnumDescriptor*
Type_descriptor() {
return FieldDescriptorProto_Type_descriptor();
@@ -755,6 +793,8 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
FieldDescriptorProto_Label_Label_MIN;
static const Label Label_MAX =
FieldDescriptorProto_Label_Label_MAX;
+ static const int Label_ARRAYSIZE =
+ FieldDescriptorProto_Label_Label_ARRAYSIZE;
static inline const ::google::protobuf::EnumDescriptor*
Label_descriptor() {
return FieldDescriptorProto_Label_descriptor();
@@ -837,6 +877,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline const ::google::protobuf::FieldOptions& options() const;
inline ::google::protobuf::FieldOptions* mutable_options();
+ // @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -897,6 +938,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
static const ::google::protobuf::Descriptor* descriptor();
static const EnumDescriptorProto& default_instance();
+
void Swap(EnumDescriptorProto* other);
// implements Message ----------------------------------------------
@@ -919,7 +961,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -942,11 +984,13 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
inline int value_size() const;
inline void clear_value();
static const int kValueFieldNumber = 2;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& value() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* mutable_value();
inline const ::google::protobuf::EnumValueDescriptorProto& value(int index) const;
inline ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index);
inline ::google::protobuf::EnumValueDescriptorProto* add_value();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+ value() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
+ mutable_value();
// optional .google.protobuf.EnumOptions options = 3;
inline bool has_options() const;
@@ -955,6 +999,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
inline const ::google::protobuf::EnumOptions& options() const;
inline ::google::protobuf::EnumOptions* mutable_options();
+ // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -1007,6 +1052,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
static const ::google::protobuf::Descriptor* descriptor();
static const EnumValueDescriptorProto& default_instance();
+
void Swap(EnumValueDescriptorProto* other);
// implements Message ----------------------------------------------
@@ -1029,7 +1075,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1062,6 +1108,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
inline const ::google::protobuf::EnumValueOptions& options() const;
inline ::google::protobuf::EnumValueOptions* mutable_options();
+ // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -1114,6 +1161,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
static const ::google::protobuf::Descriptor* descriptor();
static const ServiceDescriptorProto& default_instance();
+
void Swap(ServiceDescriptorProto* other);
// implements Message ----------------------------------------------
@@ -1136,7 +1184,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1159,11 +1207,13 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
inline int method_size() const;
inline void clear_method();
static const int kMethodFieldNumber = 2;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& method() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* mutable_method();
inline const ::google::protobuf::MethodDescriptorProto& method(int index) const;
inline ::google::protobuf::MethodDescriptorProto* mutable_method(int index);
inline ::google::protobuf::MethodDescriptorProto* add_method();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ method() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
+ mutable_method();
// optional .google.protobuf.ServiceOptions options = 3;
inline bool has_options() const;
@@ -1172,6 +1222,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
inline const ::google::protobuf::ServiceOptions& options() const;
inline ::google::protobuf::ServiceOptions* mutable_options();
+ // @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -1224,6 +1275,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
static const ::google::protobuf::Descriptor* descriptor();
static const MethodDescriptorProto& default_instance();
+
void Swap(MethodDescriptorProto* other);
// implements Message ----------------------------------------------
@@ -1246,7 +1298,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1292,6 +1344,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
inline const ::google::protobuf::MethodOptions& options() const;
inline ::google::protobuf::MethodOptions* mutable_options();
+ // @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -1347,6 +1400,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const FileOptions& default_instance();
+
void Swap(FileOptions* other);
// implements Message ----------------------------------------------
@@ -1369,7 +1423,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1387,6 +1441,8 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
FileOptions_OptimizeMode_OptimizeMode_MIN;
static const OptimizeMode OptimizeMode_MAX =
FileOptions_OptimizeMode_OptimizeMode_MAX;
+ static const int OptimizeMode_ARRAYSIZE =
+ FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE;
static inline const ::google::protobuf::EnumDescriptor*
OptimizeMode_descriptor() {
return FileOptions_OptimizeMode_descriptor();
@@ -1435,17 +1491,41 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
inline ::google::protobuf::FileOptions_OptimizeMode optimize_for() const;
inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value);
+ // optional bool cc_generic_services = 16 [default = true];
+ inline bool has_cc_generic_services() const;
+ inline void clear_cc_generic_services();
+ static const int kCcGenericServicesFieldNumber = 16;
+ inline bool cc_generic_services() const;
+ inline void set_cc_generic_services(bool value);
+
+ // optional bool java_generic_services = 17 [default = true];
+ inline bool has_java_generic_services() const;
+ inline void clear_java_generic_services();
+ static const int kJavaGenericServicesFieldNumber = 17;
+ inline bool java_generic_services() const;
+ inline void set_java_generic_services(bool value);
+
+ // optional bool py_generic_services = 18 [default = true];
+ inline bool has_py_generic_services() const;
+ inline void clear_py_generic_services();
+ static const int kPyGenericServicesFieldNumber = 18;
+ inline bool py_generic_services() const;
+ inline void set_py_generic_services(bool value);
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option();
inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions)
+ // @@protoc_insertion_point(class_scope:google.protobuf.FileOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -1457,12 +1537,15 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
static const ::std::string _default_java_outer_classname_;
bool java_multiple_files_;
int optimize_for_;
+ bool cc_generic_services_;
+ bool java_generic_services_;
+ bool py_generic_services_;
::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_[(5 + 31) / 32];
+ ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
inline bool _has_bit(int index) const {
@@ -1502,6 +1585,7 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const MessageOptions& default_instance();
+
void Swap(MessageOptions* other);
// implements Message ----------------------------------------------
@@ -1524,7 +1608,7 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1551,13 +1635,16 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option();
inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions)
+ // @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -1610,6 +1697,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const FieldOptions& default_instance();
+
void Swap(FieldOptions* other);
// implements Message ----------------------------------------------
@@ -1632,7 +1720,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1640,6 +1728,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
// nested types ----------------------------------------------------
typedef FieldOptions_CType CType;
+ static const CType STRING = FieldOptions_CType_STRING;
static const CType CORD = FieldOptions_CType_CORD;
static const CType STRING_PIECE = FieldOptions_CType_STRING_PIECE;
static inline bool CType_IsValid(int value) {
@@ -1649,6 +1738,8 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
FieldOptions_CType_CType_MIN;
static const CType CType_MAX =
FieldOptions_CType_CType_MAX;
+ static const int CType_ARRAYSIZE =
+ FieldOptions_CType_CType_ARRAYSIZE;
static inline const ::google::protobuf::EnumDescriptor*
CType_descriptor() {
return FieldOptions_CType_descriptor();
@@ -1663,7 +1754,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
- // optional .google.protobuf.FieldOptions.CType ctype = 1;
+ // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
inline bool has_ctype() const;
inline void clear_ctype();
static const int kCtypeFieldNumber = 1;
@@ -1698,13 +1789,16 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option();
inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions)
+ // @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -1760,6 +1854,7 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const EnumOptions& default_instance();
+
void Swap(EnumOptions* other);
// implements Message ----------------------------------------------
@@ -1782,7 +1877,7 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1795,13 +1890,16 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option();
inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions)
+ // @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -1852,6 +1950,7 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const EnumValueOptions& default_instance();
+
void Swap(EnumValueOptions* other);
// implements Message ----------------------------------------------
@@ -1874,7 +1973,7 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1887,13 +1986,16 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option();
inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions)
+ // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -1944,6 +2046,7 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const ServiceOptions& default_instance();
+
void Swap(ServiceOptions* other);
// implements Message ----------------------------------------------
@@ -1966,7 +2069,7 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -1979,13 +2082,16 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option();
inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions)
+ // @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -2036,6 +2142,7 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const MethodOptions& default_instance();
+
void Swap(MethodOptions* other);
// implements Message ----------------------------------------------
@@ -2058,7 +2165,7 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -2071,13 +2178,16 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option();
inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions)
+ // @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -2128,6 +2238,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
static const ::google::protobuf::Descriptor* descriptor();
static const UninterpretedOption_NamePart& default_instance();
+
void Swap(UninterpretedOption_NamePart* other);
// implements Message ----------------------------------------------
@@ -2150,7 +2261,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -2176,6 +2287,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
inline bool is_extension() const;
inline void set_is_extension(bool value);
+ // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -2227,6 +2339,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
static const ::google::protobuf::Descriptor* descriptor();
static const UninterpretedOption& default_instance();
+
void Swap(UninterpretedOption* other);
// implements Message ----------------------------------------------
@@ -2249,7 +2362,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
private:
void SharedCtor();
void SharedDtor();
- void SetCachedSize(int size) const { _cached_size_ = size; }
+ void SetCachedSize(int size) const;
public:
::google::protobuf::Metadata GetMetadata() const;
@@ -2264,11 +2377,13 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
inline int name_size() const;
inline void clear_name();
static const int kNameFieldNumber = 2;
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& name() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* mutable_name();
inline const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const;
inline ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index);
inline ::google::protobuf::UninterpretedOption_NamePart* add_name();
+ inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+ name() const;
+ inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
+ mutable_name();
// optional string identifier_value = 3;
inline bool has_identifier_value() const;
@@ -2311,6 +2426,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
inline void set_string_value(const void* value, size_t size);
inline ::std::string* mutable_string_value();
+ // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption)
private:
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
@@ -2348,9 +2464,6 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
// ===================================================================
-
-// ===================================================================
-
// FileDescriptorSet
// repeated .google.protobuf.FileDescriptorProto file = 1;
@@ -2360,14 +2473,6 @@ inline int FileDescriptorSet::file_size() const {
inline void FileDescriptorSet::clear_file() {
file_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
-FileDescriptorSet::file() const {
- return file_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
-FileDescriptorSet::mutable_file() {
- return &file_;
-}
inline const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const {
return file_.Get(index);
}
@@ -2377,6 +2482,14 @@ inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(
inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() {
return file_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+FileDescriptorSet::file() const {
+ return file_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+FileDescriptorSet::mutable_file() {
+ return &file_;
+}
// -------------------------------------------------------------------
@@ -2473,14 +2586,6 @@ inline int FileDescriptorProto::dependency_size() const {
inline void FileDescriptorProto::clear_dependency() {
dependency_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
-FileDescriptorProto::dependency() const {
- return dependency_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::std::string>*
-FileDescriptorProto::mutable_dependency() {
- return &dependency_;
-}
inline const ::std::string& FileDescriptorProto::dependency(int index) const {
return dependency_.Get(index);
}
@@ -2509,6 +2614,14 @@ inline void FileDescriptorProto::add_dependency(const char* value) {
inline void FileDescriptorProto::add_dependency(const char* value, size_t size) {
dependency_.Add()->assign(reinterpret_cast<const char*>(value), size);
}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+FileDescriptorProto::dependency() const {
+ return dependency_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+FileDescriptorProto::mutable_dependency() {
+ return &dependency_;
+}
// repeated .google.protobuf.DescriptorProto message_type = 4;
inline int FileDescriptorProto::message_type_size() const {
@@ -2517,14 +2630,6 @@ inline int FileDescriptorProto::message_type_size() const {
inline void FileDescriptorProto::clear_message_type() {
message_type_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
-FileDescriptorProto::message_type() const {
- return message_type_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
-FileDescriptorProto::mutable_message_type() {
- return &message_type_;
-}
inline const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const {
return message_type_.Get(index);
}
@@ -2534,6 +2639,14 @@ inline ::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message
inline ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() {
return message_type_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+FileDescriptorProto::message_type() const {
+ return message_type_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+FileDescriptorProto::mutable_message_type() {
+ return &message_type_;
+}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
inline int FileDescriptorProto::enum_type_size() const {
@@ -2542,14 +2655,6 @@ inline int FileDescriptorProto::enum_type_size() const {
inline void FileDescriptorProto::clear_enum_type() {
enum_type_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
-FileDescriptorProto::enum_type() const {
- return enum_type_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
-FileDescriptorProto::mutable_enum_type() {
- return &enum_type_;
-}
inline const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const {
return enum_type_.Get(index);
}
@@ -2559,6 +2664,14 @@ inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enu
inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() {
return enum_type_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+FileDescriptorProto::enum_type() const {
+ return enum_type_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+FileDescriptorProto::mutable_enum_type() {
+ return &enum_type_;
+}
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
inline int FileDescriptorProto::service_size() const {
@@ -2567,14 +2680,6 @@ inline int FileDescriptorProto::service_size() const {
inline void FileDescriptorProto::clear_service() {
service_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
-FileDescriptorProto::service() const {
- return service_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
-FileDescriptorProto::mutable_service() {
- return &service_;
-}
inline const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const {
return service_.Get(index);
}
@@ -2584,6 +2689,14 @@ inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_
inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() {
return service_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+FileDescriptorProto::service() const {
+ return service_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
+FileDescriptorProto::mutable_service() {
+ return &service_;
+}
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
inline int FileDescriptorProto::extension_size() const {
@@ -2592,14 +2705,6 @@ inline int FileDescriptorProto::extension_size() const {
inline void FileDescriptorProto::clear_extension() {
extension_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-FileDescriptorProto::extension() const {
- return extension_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
-FileDescriptorProto::mutable_extension() {
- return &extension_;
-}
inline const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const {
return extension_.Get(index);
}
@@ -2609,6 +2714,14 @@ inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_ex
inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() {
return extension_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+FileDescriptorProto::extension() const {
+ return extension_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+FileDescriptorProto::mutable_extension() {
+ return &extension_;
+}
// optional .google.protobuf.FileOptions options = 8;
inline bool FileDescriptorProto::has_options() const {
@@ -2716,14 +2829,6 @@ inline int DescriptorProto::field_size() const {
inline void DescriptorProto::clear_field() {
field_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-DescriptorProto::field() const {
- return field_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
-DescriptorProto::mutable_field() {
- return &field_;
-}
inline const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const {
return field_.Get(index);
}
@@ -2733,6 +2838,14 @@ inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(
inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() {
return field_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::field() const {
+ return field_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+DescriptorProto::mutable_field() {
+ return &field_;
+}
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
inline int DescriptorProto::extension_size() const {
@@ -2741,14 +2854,6 @@ inline int DescriptorProto::extension_size() const {
inline void DescriptorProto::clear_extension() {
extension_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-DescriptorProto::extension() const {
- return extension_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
-DescriptorProto::mutable_extension() {
- return &extension_;
-}
inline const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const {
return extension_.Get(index);
}
@@ -2758,6 +2863,14 @@ inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extens
inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() {
return extension_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::extension() const {
+ return extension_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+DescriptorProto::mutable_extension() {
+ return &extension_;
+}
// repeated .google.protobuf.DescriptorProto nested_type = 3;
inline int DescriptorProto::nested_type_size() const {
@@ -2766,14 +2879,6 @@ inline int DescriptorProto::nested_type_size() const {
inline void DescriptorProto::clear_nested_type() {
nested_type_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
-DescriptorProto::nested_type() const {
- return nested_type_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
-DescriptorProto::mutable_nested_type() {
- return &nested_type_;
-}
inline const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const {
return nested_type_.Get(index);
}
@@ -2783,6 +2888,14 @@ inline ::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type
inline ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() {
return nested_type_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+DescriptorProto::nested_type() const {
+ return nested_type_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+DescriptorProto::mutable_nested_type() {
+ return &nested_type_;
+}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
inline int DescriptorProto::enum_type_size() const {
@@ -2791,14 +2904,6 @@ inline int DescriptorProto::enum_type_size() const {
inline void DescriptorProto::clear_enum_type() {
enum_type_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
-DescriptorProto::enum_type() const {
- return enum_type_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
-DescriptorProto::mutable_enum_type() {
- return &enum_type_;
-}
inline const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const {
return enum_type_.Get(index);
}
@@ -2808,6 +2913,14 @@ inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_ty
inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() {
return enum_type_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+DescriptorProto::enum_type() const {
+ return enum_type_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+DescriptorProto::mutable_enum_type() {
+ return &enum_type_;
+}
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
inline int DescriptorProto::extension_range_size() const {
@@ -2816,14 +2929,6 @@ inline int DescriptorProto::extension_range_size() const {
inline void DescriptorProto::clear_extension_range() {
extension_range_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
-DescriptorProto::extension_range() const {
- return extension_range_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
-DescriptorProto::mutable_extension_range() {
- return &extension_range_;
-}
inline const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const {
return extension_range_.Get(index);
}
@@ -2833,6 +2938,14 @@ inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::muta
inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() {
return extension_range_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+DescriptorProto::extension_range() const {
+ return extension_range_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
+DescriptorProto::mutable_extension_range() {
+ return &extension_range_;
+}
// optional .google.protobuf.MessageOptions options = 7;
inline bool DescriptorProto::has_options() const {
@@ -3143,14 +3256,6 @@ inline int EnumDescriptorProto::value_size() const {
inline void EnumDescriptorProto::clear_value() {
value_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
-EnumDescriptorProto::value() const {
- return value_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
-EnumDescriptorProto::mutable_value() {
- return &value_;
-}
inline const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const {
return value_.Get(index);
}
@@ -3160,6 +3265,14 @@ inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutabl
inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() {
return value_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+EnumDescriptorProto::value() const {
+ return value_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
+EnumDescriptorProto::mutable_value() {
+ return &value_;
+}
// optional .google.protobuf.EnumOptions options = 3;
inline bool EnumDescriptorProto::has_options() const {
@@ -3310,14 +3423,6 @@ inline int ServiceDescriptorProto::method_size() const {
inline void ServiceDescriptorProto::clear_method() {
method_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
-ServiceDescriptorProto::method() const {
- return method_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
-ServiceDescriptorProto::mutable_method() {
- return &method_;
-}
inline const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const {
return method_.Get(index);
}
@@ -3327,6 +3432,14 @@ inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutabl
inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() {
return method_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ServiceDescriptorProto::method() const {
+ return method_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
+ServiceDescriptorProto::mutable_method() {
+ return &method_;
+}
// optional .google.protobuf.ServiceOptions options = 3;
inline bool ServiceDescriptorProto::has_options() const {
@@ -3613,6 +3726,54 @@ inline void FileOptions::set_optimize_for(::google::protobuf::FileOptions_Optimi
optimize_for_ = value;
}
+// optional bool cc_generic_services = 16 [default = true];
+inline bool FileOptions::has_cc_generic_services() const {
+ return _has_bit(4);
+}
+inline void FileOptions::clear_cc_generic_services() {
+ cc_generic_services_ = true;
+ _clear_bit(4);
+}
+inline bool FileOptions::cc_generic_services() const {
+ return cc_generic_services_;
+}
+inline void FileOptions::set_cc_generic_services(bool value) {
+ _set_bit(4);
+ cc_generic_services_ = value;
+}
+
+// optional bool java_generic_services = 17 [default = true];
+inline bool FileOptions::has_java_generic_services() const {
+ return _has_bit(5);
+}
+inline void FileOptions::clear_java_generic_services() {
+ java_generic_services_ = true;
+ _clear_bit(5);
+}
+inline bool FileOptions::java_generic_services() const {
+ return java_generic_services_;
+}
+inline void FileOptions::set_java_generic_services(bool value) {
+ _set_bit(5);
+ java_generic_services_ = value;
+}
+
+// optional bool py_generic_services = 18 [default = true];
+inline bool FileOptions::has_py_generic_services() const {
+ return _has_bit(6);
+}
+inline void FileOptions::clear_py_generic_services() {
+ py_generic_services_ = true;
+ _clear_bit(6);
+}
+inline bool FileOptions::py_generic_services() const {
+ return py_generic_services_;
+}
+inline void FileOptions::set_py_generic_services(bool value) {
+ _set_bit(6);
+ py_generic_services_ = value;
+}
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int FileOptions::uninterpreted_option_size() const {
return uninterpreted_option_.size();
@@ -3620,14 +3781,6 @@ inline int FileOptions::uninterpreted_option_size() const {
inline void FileOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-FileOptions::uninterpreted_option() const {
- return uninterpreted_option_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
-FileOptions::mutable_uninterpreted_option() {
- return &uninterpreted_option_;
-}
inline const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const {
return uninterpreted_option_.Get(index);
}
@@ -3637,6 +3790,14 @@ inline ::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpret
inline ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() {
return uninterpreted_option_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FileOptions::uninterpreted_option() const {
+ return uninterpreted_option_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+FileOptions::mutable_uninterpreted_option() {
+ return &uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -3681,14 +3842,6 @@ inline int MessageOptions::uninterpreted_option_size() const {
inline void MessageOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-MessageOptions::uninterpreted_option() const {
- return uninterpreted_option_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
-MessageOptions::mutable_uninterpreted_option() {
- return &uninterpreted_option_;
-}
inline const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const {
return uninterpreted_option_.Get(index);
}
@@ -3698,17 +3851,25 @@ inline ::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterp
inline ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() {
return uninterpreted_option_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MessageOptions::uninterpreted_option() const {
+ return uninterpreted_option_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+MessageOptions::mutable_uninterpreted_option() {
+ return &uninterpreted_option_;
+}
// -------------------------------------------------------------------
// FieldOptions
-// optional .google.protobuf.FieldOptions.CType ctype = 1;
+// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
inline bool FieldOptions::has_ctype() const {
return _has_bit(0);
}
inline void FieldOptions::clear_ctype() {
- ctype_ = 1;
+ ctype_ = 0;
_clear_bit(0);
}
inline ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const {
@@ -3801,14 +3962,6 @@ inline int FieldOptions::uninterpreted_option_size() const {
inline void FieldOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-FieldOptions::uninterpreted_option() const {
- return uninterpreted_option_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
-FieldOptions::mutable_uninterpreted_option() {
- return &uninterpreted_option_;
-}
inline const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const {
return uninterpreted_option_.Get(index);
}
@@ -3818,6 +3971,14 @@ inline ::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpre
inline ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() {
return uninterpreted_option_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FieldOptions::uninterpreted_option() const {
+ return uninterpreted_option_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+FieldOptions::mutable_uninterpreted_option() {
+ return &uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -3830,14 +3991,6 @@ inline int EnumOptions::uninterpreted_option_size() const {
inline void EnumOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-EnumOptions::uninterpreted_option() const {
- return uninterpreted_option_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
-EnumOptions::mutable_uninterpreted_option() {
- return &uninterpreted_option_;
-}
inline const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const {
return uninterpreted_option_.Get(index);
}
@@ -3847,6 +4000,14 @@ inline ::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpret
inline ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() {
return uninterpreted_option_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumOptions::uninterpreted_option() const {
+ return uninterpreted_option_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+EnumOptions::mutable_uninterpreted_option() {
+ return &uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -3859,14 +4020,6 @@ inline int EnumValueOptions::uninterpreted_option_size() const {
inline void EnumValueOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-EnumValueOptions::uninterpreted_option() const {
- return uninterpreted_option_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
-EnumValueOptions::mutable_uninterpreted_option() {
- return &uninterpreted_option_;
-}
inline const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const {
return uninterpreted_option_.Get(index);
}
@@ -3876,6 +4029,14 @@ inline ::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninte
inline ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() {
return uninterpreted_option_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumValueOptions::uninterpreted_option() const {
+ return uninterpreted_option_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+EnumValueOptions::mutable_uninterpreted_option() {
+ return &uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -3888,14 +4049,6 @@ inline int ServiceOptions::uninterpreted_option_size() const {
inline void ServiceOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-ServiceOptions::uninterpreted_option() const {
- return uninterpreted_option_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
-ServiceOptions::mutable_uninterpreted_option() {
- return &uninterpreted_option_;
-}
inline const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const {
return uninterpreted_option_.Get(index);
}
@@ -3905,6 +4058,14 @@ inline ::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterp
inline ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() {
return uninterpreted_option_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ServiceOptions::uninterpreted_option() const {
+ return uninterpreted_option_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ServiceOptions::mutable_uninterpreted_option() {
+ return &uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -3917,14 +4078,6 @@ inline int MethodOptions::uninterpreted_option_size() const {
inline void MethodOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-MethodOptions::uninterpreted_option() const {
- return uninterpreted_option_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
-MethodOptions::mutable_uninterpreted_option() {
- return &uninterpreted_option_;
-}
inline const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const {
return uninterpreted_option_.Get(index);
}
@@ -3934,6 +4087,14 @@ inline ::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpr
inline ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() {
return uninterpreted_option_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MethodOptions::uninterpreted_option() const {
+ return uninterpreted_option_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+MethodOptions::mutable_uninterpreted_option() {
+ return &uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -4008,14 +4169,6 @@ inline int UninterpretedOption::name_size() const {
inline void UninterpretedOption::clear_name() {
name_.Clear();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
-UninterpretedOption::name() const {
- return name_;
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
-UninterpretedOption::mutable_name() {
- return &name_;
-}
inline const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const {
return name_.Get(index);
}
@@ -4025,6 +4178,14 @@ inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mu
inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() {
return name_.Add();
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+UninterpretedOption::name() const {
+ return name_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
+UninterpretedOption::mutable_name() {
+ return &name_;
+}
// optional string identifier_value = 3;
inline bool UninterpretedOption::has_identifier_value() const {
@@ -4159,6 +4320,8 @@ inline ::std::string* UninterpretedOption::mutable_string_value() {
}
+// @@protoc_insertion_point(namespace_scope)
+
} // namespace protobuf
} // namespace google
@@ -4187,4 +4350,6 @@ inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions
} // namespace protobuf
#endif // SWIG
+// @@protoc_insertion_point(global_scope)
+
#endif // PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index 4db88a82..cc04aa8e 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -256,6 +256,22 @@ message FileOptions {
+
+ // Should generic services be generated in each language? "Generic" services
+ // are not specific to any particular RPC system. They are generated by the
+ // main code generators in each language (without additional plugins).
+ // Generic services were the only kind of service generation supported by
+ // early versions of proto2.
+ //
+ // Generic services are now considered deprecated in favor of using plugins
+ // that generate code specific to your particular RPC system. If you are
+ // using such a plugin, set these to false. In the future, we may change
+ // the default to false, so if you explicitly want generic services, you
+ // should explicitly set these to true.
+ optional bool cc_generic_services = 16 [default=true];
+ optional bool java_generic_services = 17 [default=true];
+ optional bool py_generic_services = 18 [default=true];
+
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
@@ -301,8 +317,11 @@ message FieldOptions {
// representation of the field than it normally would. See the specific
// options below. This option is not yet implemented in the open source
// release -- sorry, we'll try to include it in a future version!
- optional CType ctype = 1;
+ optional CType ctype = 1 [default = STRING];
enum CType {
+ // Default mode.
+ STRING = 0;
+
CORD = 1;
STRING_PIECE = 2;
@@ -313,6 +332,7 @@ message FieldOptions {
// a single length-delimited blob.
optional bool packed = 2;
+
// Is this field deprecated?
// Depending on the target platform, this can emit Deprecated annotations
// for accessors, or it will be completely ignored; in the very least, this
diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc
index 6ea674d1..95708d94 100644
--- a/src/google/protobuf/descriptor_database.cc
+++ b/src/google/protobuf/descriptor_database.cc
@@ -37,6 +37,7 @@
#include <set>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/stl_util-inl.h>
#include <google/protobuf/stubs/map-util.h>
@@ -336,6 +337,35 @@ bool EncodedDescriptorDatabase::FindFileContainingSymbol(
return MaybeParse(index_.FindSymbol(symbol_name), output);
}
+bool EncodedDescriptorDatabase::FindNameOfFileContainingSymbol(
+ const string& symbol_name,
+ string* output) {
+ pair<const void*, int> encoded_file = index_.FindSymbol(symbol_name);
+ if (encoded_file.first == NULL) return false;
+
+ // Optimization: The name should be the first field in the encoded message.
+ // Try to just read it directly.
+ io::CodedInputStream input(reinterpret_cast<const uint8*>(encoded_file.first),
+ encoded_file.second);
+
+ const uint32 kNameTag = internal::WireFormatLite::MakeTag(
+ FileDescriptorProto::kNameFieldNumber,
+ internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+
+ if (input.ReadTag() == kNameTag) {
+ // Success!
+ return internal::WireFormatLite::ReadString(&input, output);
+ } else {
+ // Slow path. Parse whole message.
+ FileDescriptorProto file_proto;
+ if (!file_proto.ParseFromArray(encoded_file.first, encoded_file.second)) {
+ return false;
+ }
+ *output = file_proto.name();
+ return true;
+ }
+}
+
bool EncodedDescriptorDatabase::FindFileContainingExtension(
const string& containing_type,
int field_number,
diff --git a/src/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h
index c23ab75f..f32b1db9 100644
--- a/src/google/protobuf/descriptor_database.h
+++ b/src/google/protobuf/descriptor_database.h
@@ -280,6 +280,10 @@ class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
// need to keep it around.
bool AddCopy(const void* encoded_file_descriptor, int size);
+ // Like FindFileContainingSymbol but returns only the name of the file.
+ bool FindNameOfFileContainingSymbol(const string& symbol_name,
+ string* output);
+
// implements DescriptorDatabase -----------------------------------
bool FindFileByName(const string& filename,
FileDescriptorProto* output);
diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc
index 33de1348..ac72ddcd 100644
--- a/src/google/protobuf/descriptor_database_unittest.cc
+++ b/src/google/protobuf/descriptor_database_unittest.cc
@@ -480,6 +480,40 @@ INSTANTIATE_TEST_CASE_P(Pool, DescriptorDatabaseTest,
#endif // GTEST_HAS_PARAM_TEST
+TEST(EncodedDescriptorDatabaseExtraTest, FindNameOfFileContainingSymbol) {
+ // Create two files, one of which is in two parts.
+ FileDescriptorProto file1, file2a, file2b;
+ file1.set_name("foo.proto");
+ file1.set_package("foo");
+ file1.add_message_type()->set_name("Foo");
+ file2a.set_name("bar.proto");
+ file2b.set_package("bar");
+ file2b.add_message_type()->set_name("Bar");
+
+ // Normal serialization allows our optimization to kick in.
+ string data1 = file1.SerializeAsString();
+
+ // Force out-of-order serialization to test slow path.
+ string data2 = file2b.SerializeAsString() + file2a.SerializeAsString();
+
+ // Create EncodedDescriptorDatabase containing both files.
+ EncodedDescriptorDatabase db;
+ db.Add(data1.data(), data1.size());
+ db.Add(data2.data(), data2.size());
+
+ // Test!
+ string filename;
+ EXPECT_TRUE(db.FindNameOfFileContainingSymbol("foo.Foo", &filename));
+ EXPECT_EQ("foo.proto", filename);
+ EXPECT_TRUE(db.FindNameOfFileContainingSymbol("foo.Foo.Blah", &filename));
+ EXPECT_EQ("foo.proto", filename);
+ EXPECT_TRUE(db.FindNameOfFileContainingSymbol("bar.Bar", &filename));
+ EXPECT_EQ("bar.proto", filename);
+ EXPECT_FALSE(db.FindNameOfFileContainingSymbol("foo", &filename));
+ EXPECT_FALSE(db.FindNameOfFileContainingSymbol("bar", &filename));
+ EXPECT_FALSE(db.FindNameOfFileContainingSymbol("baz.Baz", &filename));
+}
+
// ===================================================================
class MergedDescriptorDatabaseTest : public testing::Test {
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index 8fcfba3e..ec2c8152 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -3948,6 +3948,9 @@ TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) {
EXPECT_EQ(0, call_counter.call_count_);
}
+// ===================================================================
+
+
} // namespace descriptor_unittest
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index f8b5b4ea..c711a2da 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -106,7 +106,11 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
case FD::CPPTYPE_MESSAGE: return sizeof(RepeatedPtrField<Message>);
case FD::CPPTYPE_STRING:
- return sizeof(RepeatedPtrField<string>);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ return sizeof(RepeatedPtrField<string>);
+ }
break;
}
} else {
@@ -122,7 +126,11 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
case FD::CPPTYPE_MESSAGE: return sizeof(Message*);
case FD::CPPTYPE_STRING:
- return sizeof(string*);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ return sizeof(string*);
+ }
break;
}
}
@@ -262,19 +270,24 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info)
break;
case FieldDescriptor::CPPTYPE_STRING:
- if (!field->is_repeated()) {
- if (is_prototype()) {
- new(field_ptr) const string*(&field->default_value_string());
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ if (!field->is_repeated()) {
+ if (is_prototype()) {
+ new(field_ptr) const string*(&field->default_value_string());
+ } else {
+ string* default_value =
+ *reinterpret_cast<string* const*>(
+ type_info_->prototype->OffsetToPointer(
+ type_info_->offsets[i]));
+ new(field_ptr) string*(default_value);
+ }
} else {
- string* default_value =
- *reinterpret_cast<string* const*>(
- type_info_->prototype->OffsetToPointer(
- type_info_->offsets[i]));
- new(field_ptr) string*(default_value);
+ new(field_ptr) RepeatedPtrField<string>();
}
- } else {
- new(field_ptr) RepeatedPtrField<string>();
- }
+ break;
+ }
break;
case FieldDescriptor::CPPTYPE_MESSAGE: {
@@ -329,8 +342,13 @@ DynamicMessage::~DynamicMessage() {
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING:
- reinterpret_cast<RepeatedPtrField<string>*>(field_ptr)
- ->~RepeatedPtrField<string>();
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ reinterpret_cast<RepeatedPtrField<string>*>(field_ptr)
+ ->~RepeatedPtrField<string>();
+ break;
+ }
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
@@ -340,10 +358,16 @@ DynamicMessage::~DynamicMessage() {
}
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
- string* ptr = *reinterpret_cast<string**>(field_ptr);
- if (ptr != &field->default_value_string()) {
- delete ptr;
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING: {
+ string* ptr = *reinterpret_cast<string**>(field_ptr);
+ if (ptr != &field->default_value_string()) {
+ delete ptr;
+ }
+ break;
}
+ }
} else if ((field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) &&
!is_prototype()) {
Message* message = *reinterpret_cast<Message**>(field_ptr);
@@ -373,7 +397,7 @@ void DynamicMessage::CrossLinkPrototypes() {
// For singular fields, the field is just a pointer which should
// point to the prototype.
*reinterpret_cast<const Message**>(field_ptr) =
- factory->GetPrototype(field->message_type());
+ factory->GetPrototypeNoLock(field->message_type());
}
}
}
@@ -410,11 +434,13 @@ struct DynamicMessageFactory::PrototypeMap {
};
DynamicMessageFactory::DynamicMessageFactory()
- : pool_(NULL), prototypes_(new PrototypeMap) {
+ : pool_(NULL), delegate_to_generated_factory_(false),
+ prototypes_(new PrototypeMap) {
}
DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool)
- : pool_(pool), prototypes_(new PrototypeMap) {
+ : pool_(pool), delegate_to_generated_factory_(false),
+ prototypes_(new PrototypeMap) {
}
DynamicMessageFactory::~DynamicMessageFactory() {
@@ -424,8 +450,18 @@ DynamicMessageFactory::~DynamicMessageFactory() {
}
}
-
const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
+ MutexLock lock(&prototypes_mutex_);
+ return GetPrototypeNoLock(type);
+}
+
+const Message* DynamicMessageFactory::GetPrototypeNoLock(
+ const Descriptor* type) {
+ if (delegate_to_generated_factory_ &&
+ type->file()->pool() == DescriptorPool::generated_pool()) {
+ return MessageFactory::generated_factory()->GetPrototype(type);
+ }
+
const DynamicMessage::TypeInfo** target = &prototypes_->map_[type];
if (*target != NULL) {
// Already exists.
diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h
index f38d3b09..81dd2c63 100644
--- a/src/google/protobuf/dynamic_message.h
+++ b/src/google/protobuf/dynamic_message.h
@@ -73,9 +73,25 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
// Construct a DynamicMessageFactory that will search for extensions in
// the given DescriptorPool.
+ //
+ // DEPRECATED: Use CodedInputStream::SetExtensionRegistry() to tell the
+ // parser to look for extensions in an alternate pool. However, note that
+ // this is almost never what you want to do. Almost all users should use
+ // the zero-arg constructor.
DynamicMessageFactory(const DescriptorPool* pool);
+
~DynamicMessageFactory();
+ // Call this to tell the DynamicMessageFactory that if it is given a
+ // Descriptor d for which:
+ // d->file()->pool() == DescriptorPool::generated_pool(),
+ // then it should delegate to MessageFactory::generated_factory() instead
+ // of constructing a dynamic implementation of the message. In theory there
+ // is no down side to doing this, so it may become the default in the future.
+ void SetDelegateToGeneratedFactory(bool enable) {
+ delegate_to_generated_factory_ = enable;
+ }
+
// implements MessageFactory ---------------------------------------
// Given a Descriptor, constructs the default (prototype) Message of that
@@ -92,14 +108,12 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
// The given descriptor must outlive the returned message, and hence must
// outlive the DynamicMessageFactory.
//
- // Note that while GetPrototype() is idempotent, it is not const. This
- // implies that it is not thread-safe to call GetPrototype() on the same
- // DynamicMessageFactory in two different threads simultaneously. However,
- // the returned objects are just as thread-safe as any other Message.
+ // The method is thread-safe.
const Message* GetPrototype(const Descriptor* type);
private:
const DescriptorPool* pool_;
+ bool delegate_to_generated_factory_;
// This struct just contains a hash_map. We can't #include <google/protobuf/stubs/hash.h> from
// this header due to hacks needed for hash_map portability in the open source
@@ -108,6 +122,10 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
// headers may only #include other public headers.
struct PrototypeMap;
scoped_ptr<PrototypeMap> prototypes_;
+ mutable Mutex prototypes_mutex_;
+
+ friend class DynamicMessage;
+ const Message* GetPrototypeNoLock(const Descriptor* type);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory);
};
@@ -116,4 +134,3 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
} // namespace google
#endif // GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
-
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index 4d5eb6cc..b1ffb0f5 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -59,24 +59,10 @@ inline WireFormatLite::CppType cpp_type(FieldType type) {
}
// Registry stuff.
-struct ExtensionInfo {
- inline ExtensionInfo(FieldType type, bool is_repeated, bool is_packed)
- : type(type), is_repeated(is_repeated), is_packed(is_packed) {}
-
- FieldType type;
- bool is_repeated;
- bool is_packed;
-
- union {
- ExtensionSet::EnumValidityFunc* enum_is_valid;
- const MessageLite* message_prototype;
- };
-};
-
typedef hash_map<pair<const MessageLite*, int>,
ExtensionInfo> ExtensionRegistry;
ExtensionRegistry* registry_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(registry_init_);
+GoogleOnceType registry_init_;
void DeleteRegistry() {
delete registry_;
@@ -110,6 +96,19 @@ const ExtensionInfo* FindRegisteredExtension(
} // namespace
+ExtensionFinder::~ExtensionFinder() {}
+
+bool GeneratedExtensionFinder::Find(int number, ExtensionInfo* output) {
+ const ExtensionInfo* extension =
+ FindRegisteredExtension(containing_type_, number);
+ if (extension == NULL) {
+ return false;
+ } else {
+ *output = *extension;
+ return true;
+ }
+}
+
void ExtensionSet::RegisterExtension(const MessageLite* containing_type,
int number, FieldType type,
bool is_repeated, bool is_packed) {
@@ -120,13 +119,18 @@ void ExtensionSet::RegisterExtension(const MessageLite* containing_type,
Register(containing_type, number, info);
}
+static bool CallNoArgValidityFunc(const void* arg, int number) {
+ return reinterpret_cast<const EnumValidityFunc*>(arg)(number);
+}
+
void ExtensionSet::RegisterEnumExtension(const MessageLite* containing_type,
int number, FieldType type,
bool is_repeated, bool is_packed,
EnumValidityFunc* is_valid) {
GOOGLE_CHECK_EQ(type, WireFormatLite::TYPE_ENUM);
ExtensionInfo info(type, is_repeated, is_packed);
- info.enum_is_valid = is_valid;
+ info.enum_is_valid = CallNoArgValidityFunc;
+ info.enum_is_valid_arg = reinterpret_cast<void*>(is_valid);
Register(containing_type, number, info);
}
@@ -211,9 +215,10 @@ LOWERCASE ExtensionSet::Get##CAMELCASE(int number, \
} \
\
void ExtensionSet::Set##CAMELCASE(int number, FieldType type, \
- LOWERCASE value) { \
+ LOWERCASE value, \
+ const FieldDescriptor* descriptor) { \
Extension* extension; \
- if (MaybeNewExtension(number, &extension)) { \
+ if (MaybeNewExtension(number, descriptor, &extension)) { \
extension->type = type; \
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \
extension->is_repeated = false; \
@@ -240,9 +245,10 @@ void ExtensionSet::SetRepeated##CAMELCASE( \
} \
\
void ExtensionSet::Add##CAMELCASE(int number, FieldType type, \
- bool packed, LOWERCASE value) { \
+ bool packed, LOWERCASE value, \
+ const FieldDescriptor* descriptor) { \
Extension* extension; \
- if (MaybeNewExtension(number, &extension)) { \
+ if (MaybeNewExtension(number, descriptor, &extension)) { \
extension->type = type; \
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \
extension->is_repeated = true; \
@@ -279,9 +285,10 @@ int ExtensionSet::GetEnum(int number, int default_value) const {
}
}
-void ExtensionSet::SetEnum(int number, FieldType type, int value) {
+void ExtensionSet::SetEnum(int number, FieldType type, int value,
+ const FieldDescriptor* descriptor) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
+ if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM);
extension->is_repeated = false;
@@ -307,9 +314,10 @@ void ExtensionSet::SetRepeatedEnum(int number, int index, int value) {
}
void ExtensionSet::AddEnum(int number, FieldType type,
- bool packed, int value) {
+ bool packed, int value,
+ const FieldDescriptor* descriptor) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
+ if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM);
extension->is_repeated = true;
@@ -337,9 +345,10 @@ const string& ExtensionSet::GetString(int number,
}
}
-string* ExtensionSet::MutableString(int number, FieldType type) {
+string* ExtensionSet::MutableString(int number, FieldType type,
+ const FieldDescriptor* descriptor) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
+ if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING);
extension->is_repeated = false;
@@ -365,9 +374,10 @@ string* ExtensionSet::MutableRepeatedString(int number, int index) {
return iter->second.repeated_string_value->Mutable(index);
}
-string* ExtensionSet::AddString(int number, FieldType type) {
+string* ExtensionSet::AddString(int number, FieldType type,
+ const FieldDescriptor* descriptor) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
+ if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING);
extension->is_repeated = true;
@@ -400,9 +410,10 @@ const MessageLite& ExtensionSet::GetMessage(
// MessageFactory* factory) const
MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
- const MessageLite& prototype) {
+ const MessageLite& prototype,
+ const FieldDescriptor* descriptor) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
+ if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
extension->is_repeated = false;
@@ -435,9 +446,10 @@ MessageLite* ExtensionSet::MutableRepeatedMessage(int number, int index) {
}
MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
- const MessageLite& prototype) {
+ const MessageLite& prototype,
+ const FieldDescriptor* descriptor) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
+ if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
extension->is_repeated = true;
@@ -563,7 +575,8 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) {
if (other_extension.is_repeated) {
Extension* extension;
- bool is_new = MaybeNewExtension(iter->first, &extension);
+ bool is_new = MaybeNewExtension(iter->first, other_extension.descriptor,
+ &extension);
if (is_new) {
// Extension did not already exist in set.
extension->type = other_extension.type;
@@ -622,7 +635,8 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \
case WireFormatLite::CPPTYPE_##UPPERCASE: \
Set##CAMELCASE(iter->first, other_extension.type, \
- other_extension.LOWERCASE##_value); \
+ other_extension.LOWERCASE##_value, \
+ other_extension.descriptor); \
break;
HANDLE_TYPE( INT32, int32, Int32);
@@ -636,11 +650,13 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) {
#undef HANDLE_TYPE
case WireFormatLite::CPPTYPE_STRING:
SetString(iter->first, other_extension.type,
- *other_extension.string_value);
+ *other_extension.string_value,
+ other_extension.descriptor);
break;
case WireFormatLite::CPPTYPE_MESSAGE:
MutableMessage(iter->first, other_extension.type,
- *other_extension.message_value)
+ *other_extension.message_value,
+ other_extension.descriptor)
->CheckTypeAndMergeFrom(*other_extension.message_value);
break;
}
@@ -678,64 +694,66 @@ bool ExtensionSet::IsInitialized() const {
}
bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
- const MessageLite* containing_type,
+ ExtensionFinder* extension_finder,
FieldSkipper* field_skipper) {
int number = WireFormatLite::GetTagFieldNumber(tag);
WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag);
- const ExtensionInfo* extension =
- FindRegisteredExtension(containing_type, number);
-
+ ExtensionInfo extension;
bool is_unknown;
- if (extension == NULL) {
+ if (!extension_finder->Find(number, &extension)) {
is_unknown = true;
- } else if (extension->is_packed) {
+ } else if (extension.is_packed) {
is_unknown = (wire_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
} else {
WireFormatLite::WireType expected_wire_type =
- WireFormatLite::WireTypeForFieldType(real_type(extension->type));
+ WireFormatLite::WireTypeForFieldType(real_type(extension.type));
is_unknown = (wire_type != expected_wire_type);
}
if (is_unknown) {
field_skipper->SkipField(input, tag);
- } else if (extension->is_packed) {
+ } else if (extension.is_packed) {
uint32 size;
if (!input->ReadVarint32(&size)) return false;
io::CodedInputStream::Limit limit = input->PushLimit(size);
- switch (extension->type) {
-#define HANDLE_TYPE(UPPERCASE, CAMELCASE, CPP_CAMELCASE, CPP_LOWERCASE) \
+ switch (extension.type) {
+#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE, CPP_LOWERCASE) \
case WireFormatLite::TYPE_##UPPERCASE: \
while (input->BytesUntilLimit() > 0) { \
CPP_LOWERCASE value; \
- if (!WireFormatLite::Read##CAMELCASE(input, &value)) return false; \
+ if (!WireFormatLite::ReadPrimitive< \
+ CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \
+ input, &value)) return false; \
Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
- true, value); \
+ true, value, extension.descriptor); \
} \
break
- HANDLE_TYPE( INT32, Int32, Int32, int32);
- HANDLE_TYPE( INT64, Int64, Int64, int64);
- HANDLE_TYPE( UINT32, UInt32, UInt32, uint32);
- HANDLE_TYPE( UINT64, UInt64, UInt64, uint64);
- HANDLE_TYPE( SINT32, SInt32, Int32, int32);
- HANDLE_TYPE( SINT64, SInt64, Int64, int64);
- HANDLE_TYPE( FIXED32, Fixed32, UInt32, uint32);
- HANDLE_TYPE( FIXED64, Fixed64, UInt64, uint64);
- HANDLE_TYPE(SFIXED32, SFixed32, Int32, int32);
- HANDLE_TYPE(SFIXED64, SFixed64, Int64, int64);
- HANDLE_TYPE( FLOAT, Float, Float, float);
- HANDLE_TYPE( DOUBLE, Double, Double, double);
- HANDLE_TYPE( BOOL, Bool, Bool, bool);
+ HANDLE_TYPE( INT32, Int32, int32);
+ HANDLE_TYPE( INT64, Int64, int64);
+ HANDLE_TYPE( UINT32, UInt32, uint32);
+ HANDLE_TYPE( UINT64, UInt64, uint64);
+ HANDLE_TYPE( SINT32, Int32, int32);
+ HANDLE_TYPE( SINT64, Int64, int64);
+ HANDLE_TYPE( FIXED32, UInt32, uint32);
+ HANDLE_TYPE( FIXED64, UInt64, uint64);
+ HANDLE_TYPE(SFIXED32, Int32, int32);
+ HANDLE_TYPE(SFIXED64, Int64, int64);
+ HANDLE_TYPE( FLOAT, Float, float);
+ HANDLE_TYPE( DOUBLE, Double, double);
+ HANDLE_TYPE( BOOL, Bool, bool);
#undef HANDLE_TYPE
case WireFormatLite::TYPE_ENUM:
while (input->BytesUntilLimit() > 0) {
int value;
- if (!WireFormatLite::ReadEnum(input, &value)) return false;
- if (extension->enum_is_valid(value)) {
- AddEnum(number, WireFormatLite::TYPE_ENUM, true, value);
+ if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+ input, &value)) return false;
+ if (extension.enum_is_valid(extension.enum_is_valid_arg, value)) {
+ AddEnum(number, WireFormatLite::TYPE_ENUM, true, value,
+ extension.descriptor);
}
}
break;
@@ -750,81 +768,89 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
input->PopLimit(limit);
} else {
- switch (extension->type) {
-#define HANDLE_TYPE(UPPERCASE, CAMELCASE, CPP_CAMELCASE, CPP_LOWERCASE) \
+ switch (extension.type) {
+#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE, CPP_LOWERCASE) \
case WireFormatLite::TYPE_##UPPERCASE: { \
CPP_LOWERCASE value; \
- if (!WireFormatLite::Read##CAMELCASE(input, &value)) return false; \
- if (extension->is_repeated) { \
+ if (!WireFormatLite::ReadPrimitive< \
+ CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \
+ input, &value)) return false; \
+ if (extension.is_repeated) { \
Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \
- false, value); \
+ false, value, extension.descriptor); \
} else { \
- Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value); \
+ Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \
+ extension.descriptor); \
} \
} break
- HANDLE_TYPE( INT32, Int32, Int32, int32);
- HANDLE_TYPE( INT64, Int64, Int64, int64);
- HANDLE_TYPE( UINT32, UInt32, UInt32, uint32);
- HANDLE_TYPE( UINT64, UInt64, UInt64, uint64);
- HANDLE_TYPE( SINT32, SInt32, Int32, int32);
- HANDLE_TYPE( SINT64, SInt64, Int64, int64);
- HANDLE_TYPE( FIXED32, Fixed32, UInt32, uint32);
- HANDLE_TYPE( FIXED64, Fixed64, UInt64, uint64);
- HANDLE_TYPE(SFIXED32, SFixed32, Int32, int32);
- HANDLE_TYPE(SFIXED64, SFixed64, Int64, int64);
- HANDLE_TYPE( FLOAT, Float, Float, float);
- HANDLE_TYPE( DOUBLE, Double, Double, double);
- HANDLE_TYPE( BOOL, Bool, Bool, bool);
+ HANDLE_TYPE( INT32, Int32, int32);
+ HANDLE_TYPE( INT64, Int64, int64);
+ HANDLE_TYPE( UINT32, UInt32, uint32);
+ HANDLE_TYPE( UINT64, UInt64, uint64);
+ HANDLE_TYPE( SINT32, Int32, int32);
+ HANDLE_TYPE( SINT64, Int64, int64);
+ HANDLE_TYPE( FIXED32, UInt32, uint32);
+ HANDLE_TYPE( FIXED64, UInt64, uint64);
+ HANDLE_TYPE(SFIXED32, Int32, int32);
+ HANDLE_TYPE(SFIXED64, Int64, int64);
+ HANDLE_TYPE( FLOAT, Float, float);
+ HANDLE_TYPE( DOUBLE, Double, double);
+ HANDLE_TYPE( BOOL, Bool, bool);
#undef HANDLE_TYPE
case WireFormatLite::TYPE_ENUM: {
int value;
- if (!WireFormatLite::ReadEnum(input, &value)) return false;
+ if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+ input, &value)) return false;
- if (!extension->enum_is_valid(value)) {
+ if (!extension.enum_is_valid(extension.enum_is_valid_arg, value)) {
// Invalid value. Treat as unknown.
field_skipper->SkipUnknownEnum(number, value);
- } else if (extension->is_repeated) {
- AddEnum(number, WireFormatLite::TYPE_ENUM, false, value);
+ } else if (extension.is_repeated) {
+ AddEnum(number, WireFormatLite::TYPE_ENUM, false, value,
+ extension.descriptor);
} else {
- SetEnum(number, WireFormatLite::TYPE_ENUM, value);
+ SetEnum(number, WireFormatLite::TYPE_ENUM, value,
+ extension.descriptor);
}
break;
}
case WireFormatLite::TYPE_STRING: {
- string* value = extension->is_repeated ?
- AddString(number, WireFormatLite::TYPE_STRING) :
- MutableString(number, WireFormatLite::TYPE_STRING);
+ string* value = extension.is_repeated ?
+ AddString(number, WireFormatLite::TYPE_STRING, extension.descriptor) :
+ MutableString(number, WireFormatLite::TYPE_STRING,
+ extension.descriptor);
if (!WireFormatLite::ReadString(input, value)) return false;
break;
}
case WireFormatLite::TYPE_BYTES: {
- string* value = extension->is_repeated ?
- AddString(number, WireFormatLite::TYPE_STRING) :
- MutableString(number, WireFormatLite::TYPE_STRING);
+ string* value = extension.is_repeated ?
+ AddString(number, WireFormatLite::TYPE_STRING, extension.descriptor) :
+ MutableString(number, WireFormatLite::TYPE_STRING,
+ extension.descriptor);
if (!WireFormatLite::ReadBytes(input, value)) return false;
break;
}
case WireFormatLite::TYPE_GROUP: {
- MessageLite* value = extension->is_repeated ?
+ MessageLite* value = extension.is_repeated ?
AddMessage(number, WireFormatLite::TYPE_GROUP,
- *extension->message_prototype) :
+ *extension.message_prototype, extension.descriptor) :
MutableMessage(number, WireFormatLite::TYPE_GROUP,
- *extension->message_prototype);
+ *extension.message_prototype, extension.descriptor);
if (!WireFormatLite::ReadGroup(number, input, value)) return false;
break;
}
case WireFormatLite::TYPE_MESSAGE: {
- MessageLite* value = extension->is_repeated ?
+ MessageLite* value = extension.is_repeated ?
AddMessage(number, WireFormatLite::TYPE_MESSAGE,
- *extension->message_prototype) :
+ *extension.message_prototype, extension.descriptor) :
MutableMessage(number, WireFormatLite::TYPE_MESSAGE,
- *extension->message_prototype);
+ *extension.message_prototype, extension.descriptor);
if (!WireFormatLite::ReadMessage(input, value)) return false;
break;
}
@@ -837,7 +863,8 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
const MessageLite* containing_type) {
FieldSkipper skipper;
- return ParseField(tag, input, containing_type, &skipper);
+ GeneratedExtensionFinder finder(containing_type);
+ return ParseField(tag, input, &finder, &skipper);
}
// Defined in extension_set_heavy.cc.
@@ -846,7 +873,7 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
// UnknownFieldSet* unknown_fields)
bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
- const MessageLite* containing_type,
+ ExtensionFinder* extension_finder,
FieldSkipper* field_skipper) {
while (true) {
uint32 tag = input->ReadTag();
@@ -854,12 +881,12 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
case 0:
return true;
case WireFormatLite::kMessageSetItemStartTag:
- if (!ParseMessageSetItem(input, containing_type, field_skipper)) {
+ if (!ParseMessageSetItem(input, extension_finder, field_skipper)) {
return false;
}
break;
default:
- if (!ParseField(tag, input, containing_type, field_skipper)) {
+ if (!ParseField(tag, input, extension_finder, field_skipper)) {
return false;
}
break;
@@ -870,7 +897,8 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
const MessageLite* containing_type) {
FieldSkipper skipper;
- return ParseMessageSet(input, containing_type, &skipper);
+ GeneratedExtensionFinder finder(containing_type);
+ return ParseMessageSet(input, &finder, &skipper);
}
// Defined in extension_set_heavy.cc.
@@ -879,7 +907,7 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
// UnknownFieldSet* unknown_fields);
bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
- const MessageLite* containing_type,
+ ExtensionFinder* extension_finder,
FieldSkipper* field_skipper) {
// TODO(kenton): It would be nice to share code between this and
// WireFormatLite::ParseAndMergeMessageSetItem(), but I think the
@@ -919,7 +947,7 @@ bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
reinterpret_cast<const uint8*>(message_data.data()),
message_data.size());
if (!ParseField(fake_tag, &sub_input,
- containing_type, field_skipper)) {
+ extension_finder, field_skipper)) {
return false;
}
message_data.clear();
@@ -939,7 +967,7 @@ bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
} else {
// Already saw type_id, so we can parse this directly.
if (!ParseField(fake_tag, input,
- containing_type, field_skipper)) {
+ extension_finder, field_skipper)) {
return false;
}
}
@@ -969,26 +997,6 @@ void ExtensionSet::SerializeWithCachedSizes(
}
}
-uint8* ExtensionSet::SerializeWithCachedSizesToArray(
- int start_field_number, int end_field_number,
- 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);
- SerializeWithCachedSizes(start_field_number,
- end_field_number,
- &output_stream);
- written_bytes = output_stream.ByteCount();
- GOOGLE_DCHECK(!output_stream.HadError());
- }
- return target + written_bytes;
-}
-
void ExtensionSet::SerializeMessageSetWithCachedSizes(
io::CodedOutputStream* output) const {
map<int, Extension>::const_iterator iter;
@@ -997,23 +1005,6 @@ void ExtensionSet::SerializeMessageSetWithCachedSizes(
}
}
-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;
@@ -1039,10 +1030,13 @@ int ExtensionSet::MessageSetByteSize() const {
// Defined in extension_set_heavy.cc.
// int ExtensionSet::SpaceUsedExcludingSelf() const
-bool ExtensionSet::MaybeNewExtension(int number, Extension** result) {
+bool ExtensionSet::MaybeNewExtension(int number,
+ const FieldDescriptor* descriptor,
+ Extension** result) {
pair<map<int, Extension>::iterator, bool> insert_result =
extensions_.insert(make_pair(number, Extension()));
*result = &insert_result.first->second;
+ (*result)->descriptor = descriptor;
return insert_result.second;
}
@@ -1206,20 +1200,20 @@ void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes(
if (is_cleared) return;
// Start group.
- output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag);
+ output->WriteTag(WireFormatLite::kMessageSetItemStartTag);
// Write type ID.
- output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag);
- output->WriteVarint32(number);
-
+ WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber,
+ number,
+ output);
// Write message.
- output->WriteVarint32(WireFormatLite::kMessageSetMessageTag);
-
- output->WriteVarint32(message_value->GetCachedSize());
- message_value->SerializeWithCachedSizes(output);
+ WireFormatLite::WriteMessageMaybeToArray(
+ WireFormatLite::kMessageSetMessageNumber,
+ *message_value,
+ output);
// End group.
- output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag);
+ output->WriteTag(WireFormatLite::kMessageSetItemEndTag);
}
int ExtensionSet::Extension::ByteSize(int number) const {
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index e5ac277e..b1a55338 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -53,6 +53,7 @@ namespace protobuf {
class FieldDescriptor; // descriptor.h
class DescriptorPool; // descriptor.h
class MessageLite; // message_lite.h
+ class Message; // message.h
class MessageFactory; // message.h
class UnknownFieldSet; // unknown_field_set.h
namespace io {
@@ -76,6 +77,84 @@ namespace internal {
// ExtensionSet::Extension small.
typedef uint8 FieldType;
+// A function which, given an integer value, returns true if the number
+// matches one of the defined values for the corresponding enum type. This
+// is used with RegisterEnumExtension, below.
+typedef bool EnumValidityFunc(int number);
+
+// Version of the above which takes an argument. This is needed to deal with
+// extensions that are not compiled in.
+typedef bool EnumValidityFuncWithArg(const void* arg, int number);
+
+// Information about a registered extension.
+struct ExtensionInfo {
+ inline ExtensionInfo() {}
+ inline ExtensionInfo(FieldType type, bool is_repeated, bool is_packed)
+ : type(type), is_repeated(is_repeated), is_packed(is_packed),
+ descriptor(NULL) {}
+
+ FieldType type;
+ bool is_repeated;
+ bool is_packed;
+
+ union {
+ struct {
+ EnumValidityFuncWithArg* enum_is_valid;
+ const void* enum_is_valid_arg;
+ };
+ const MessageLite* message_prototype;
+ };
+
+ // The descriptor for this extension, if one exists and is known. May be
+ // NULL. Must not be NULL if the descriptor for the extension does not
+ // live in the same pool as the descriptor for the containing type.
+ const FieldDescriptor* descriptor;
+};
+
+// Abstract interface for an object which looks up extension definitions. Used
+// when parsing.
+class LIBPROTOBUF_EXPORT ExtensionFinder {
+ public:
+ virtual ~ExtensionFinder();
+
+ // Find the extension with the given containing type and number.
+ virtual bool Find(int number, ExtensionInfo* output) = 0;
+};
+
+// Implementation of ExtensionFinder which finds extensions defined in .proto
+// files which have been compiled into the binary.
+class LIBPROTOBUF_EXPORT GeneratedExtensionFinder : public ExtensionFinder {
+ public:
+ GeneratedExtensionFinder(const MessageLite* containing_type)
+ : containing_type_(containing_type) {}
+ virtual ~GeneratedExtensionFinder() {}
+
+ // Returns true and fills in *output if found, otherwise returns false.
+ virtual bool Find(int number, ExtensionInfo* output);
+
+ private:
+ const MessageLite* containing_type_;
+};
+
+// Implementation of ExtensionFinder which finds extensions in a given
+// DescriptorPool, using the given MessageFactory to construct sub-objects.
+// This class is implemented in extension_set_heavy.cc.
+class LIBPROTOBUF_EXPORT DescriptorPoolExtensionFinder : public ExtensionFinder {
+ public:
+ DescriptorPoolExtensionFinder(const DescriptorPool* pool,
+ MessageFactory* factory,
+ const Descriptor* containing_type)
+ : pool_(pool), factory_(factory), containing_type_(containing_type) {}
+ virtual ~DescriptorPoolExtensionFinder() {}
+
+ virtual bool Find(int number, ExtensionInfo* output);
+
+ private:
+ const DescriptorPool* pool_;
+ MessageFactory* factory_;
+ const Descriptor* containing_type_;
+};
+
// This is an internal helper class intended for use within the protocol buffer
// library and generated classes. Clients should not use it directly. Instead,
// use the generated accessors such as GetExtension() of the class being
@@ -92,11 +171,6 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
ExtensionSet();
~ExtensionSet();
- // A function which, given an integer value, returns true if the number
- // matches one of the defined values for the corresponding enum type. This
- // is used with RegisterEnumExtension, below.
- typedef bool EnumValidityFunc(int number);
-
// These are called at startup by protocol-compiler-generated code to
// register known extensions. The registrations are used by ParseField()
// to look up extensions for parsed field numbers. Note that dynamic parsing
@@ -117,11 +191,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// =================================================================
// Add all fields which are currently present to the given vector. This
- // is useful to implement Reflection::ListFields(). The FieldDescriptors
- // are looked up by number from the given pool.
- //
- // TODO(kenton): Looking up each field by number is somewhat unfortunate.
- // Is there a better way?
+ // is useful to implement Reflection::ListFields().
void AppendToList(const Descriptor* containing_type,
const DescriptorPool* pool,
vector<const FieldDescriptor*>* output) const;
@@ -176,21 +246,25 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
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);
- void SetUInt32(int number, FieldType type, uint32 value);
- void SetUInt64(int number, FieldType type, uint64 value);
- void SetFloat (int number, FieldType type, float value);
- void SetDouble(int number, FieldType type, double value);
- void SetBool (int number, FieldType type, bool value);
- void SetEnum (int number, FieldType type, int value);
- void SetString(int number, FieldType type, const string& value);
- string * MutableString (int number, FieldType type);
- MessageLite* MutableMessage(int number, FieldType type,
- const MessageLite& prototype);
+ // |descriptor| may be NULL so long as it is known that the descriptor for
+ // the extension lives in the same pool as the descriptor for the containing
+ // type.
+#define desc const FieldDescriptor* descriptor // avoid line wrapping
+ void SetInt32 (int number, FieldType type, int32 value, desc);
+ void SetInt64 (int number, FieldType type, int64 value, desc);
+ void SetUInt32(int number, FieldType type, uint32 value, desc);
+ void SetUInt64(int number, FieldType type, uint64 value, desc);
+ void SetFloat (int number, FieldType type, float value, desc);
+ void SetDouble(int number, FieldType type, double value, desc);
+ void SetBool (int number, FieldType type, bool value, desc);
+ void SetEnum (int number, FieldType type, int value, desc);
+ void SetString(int number, FieldType type, const string& value, desc);
+ string * MutableString (int number, FieldType type, desc);
MessageLite* MutableMessage(int number, FieldType type,
- const Descriptor* message_type,
+ const MessageLite& prototype, desc);
+ MessageLite* MutableMessage(const FieldDescriptor* decsriptor,
MessageFactory* factory);
+#undef desc
// repeated fields -------------------------------------------------
@@ -217,21 +291,22 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
string * MutableRepeatedString (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);
- void AddUInt32(int number, FieldType type, bool packed, uint32 value);
- void AddUInt64(int number, FieldType type, bool packed, uint64 value);
- void AddFloat (int number, FieldType type, bool packed, float value);
- void AddDouble(int number, FieldType type, bool packed, double value);
- void AddBool (int number, FieldType type, bool packed, bool value);
- 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);
+#define desc const FieldDescriptor* descriptor // avoid line wrapping
+ void AddInt32 (int number, FieldType type, bool packed, int32 value, desc);
+ void AddInt64 (int number, FieldType type, bool packed, int64 value, desc);
+ void AddUInt32(int number, FieldType type, bool packed, uint32 value, desc);
+ void AddUInt64(int number, FieldType type, bool packed, uint64 value, desc);
+ void AddFloat (int number, FieldType type, bool packed, float value, desc);
+ void AddDouble(int number, FieldType type, bool packed, double value, desc);
+ void AddBool (int number, FieldType type, bool packed, bool value, desc);
+ void AddEnum (int number, FieldType type, bool packed, int value, desc);
+ void AddString(int number, FieldType type, const string& value, desc);
+ string * AddString (int number, FieldType type, desc);
MessageLite* AddMessage(int number, FieldType type,
- const MessageLite& prototype);
- MessageLite* AddMessage(int number, FieldType type,
- const Descriptor* message_type,
+ const MessageLite& prototype, desc);
+ MessageLite* AddMessage(const FieldDescriptor* descriptor,
MessageFactory* factory);
+#undef desc
void RemoveLast(int number);
void SwapElements(int number, int index1, int index2);
@@ -257,7 +332,7 @@ 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 MessageLite* containing_type,
+ ExtensionFinder* extension_finder,
FieldSkipper* field_skipper);
// Specific versions for lite or full messages (constructs the appropriate
@@ -265,13 +340,13 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
bool ParseField(uint32 tag, io::CodedInputStream* input,
const MessageLite* containing_type);
bool ParseField(uint32 tag, io::CodedInputStream* input,
- const MessageLite* containing_type,
+ const Message* 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,
+ ExtensionFinder* extension_finder,
FieldSkipper* field_skipper);
// Specific versions for lite or full messages (constructs the appropriate
@@ -279,7 +354,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
bool ParseMessageSet(io::CodedInputStream* input,
const MessageLite* containing_type);
bool ParseMessageSet(io::CodedInputStream* input,
- const MessageLite* containing_type,
+ const Message* containing_type,
UnknownFieldSet* unknown_fields);
// Write all extension fields with field numbers in the range
@@ -359,6 +434,11 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// For repeated types, this indicates if the [packed=true] option is set.
bool is_packed;
+ // The descriptor for this extension, if one exists and is known. May be
+ // NULL. Must not be NULL if the descriptor for the extension does not
+ // live in the same pool as the descriptor for the containing type.
+ const FieldDescriptor* descriptor;
+
// For packed fields, the size of the packed data is recorded here when
// ByteSize() is called then used during serialization.
// TODO(kenton): Use atomic<int> when C++ supports it.
@@ -368,9 +448,15 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
void SerializeFieldWithCachedSizes(
int number,
io::CodedOutputStream* output) const;
+ uint8* SerializeFieldWithCachedSizesToArray(
+ int number,
+ uint8* target) const;
void SerializeMessageSetItemWithCachedSizes(
int number,
io::CodedOutputStream* output) const;
+ uint8* SerializeMessageSetItemWithCachedSizesToArray(
+ int number,
+ uint8* target) const;
int ByteSize(int number) const;
int MessageSetItemByteSize(int number) const;
void Clear();
@@ -381,14 +467,16 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// Gets the extension with the given number, creating it if it does not
// already exist. Returns true if the extension did not already exist.
- bool MaybeNewExtension(int number, Extension** result);
+ bool MaybeNewExtension(int number, const FieldDescriptor* descriptor,
+ 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,
+ ExtensionFinder* extension_finder,
FieldSkipper* field_skipper);
+
// Hack: RepeatedPtrFieldBase declares ExtensionSet as a friend. This
// friendship should automatically extend to ExtensionSet::Extension, but
// unfortunately some older compilers (e.g. GCC 3.4.4) do not implement this
@@ -412,16 +500,18 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// These are just for convenience...
inline void ExtensionSet::SetString(int number, FieldType type,
- const string& value) {
- MutableString(number, type)->assign(value);
+ const string& value,
+ const FieldDescriptor* descriptor) {
+ MutableString(number, type, descriptor)->assign(value);
}
inline void ExtensionSet::SetRepeatedString(int number, int index,
const string& value) {
MutableRepeatedString(number, index)->assign(value);
}
inline void ExtensionSet::AddString(int number, FieldType type,
- const string& value) {
- AddString(number, type)->assign(value);
+ const string& value,
+ const FieldDescriptor* descriptor) {
+ AddString(number, type, descriptor)->assign(value);
}
// ===================================================================
@@ -502,7 +592,7 @@ template<> inline TYPE PrimitiveTypeTraits<TYPE>::Get( \
} \
template<> inline void PrimitiveTypeTraits<TYPE>::Set( \
int number, FieldType field_type, TYPE value, ExtensionSet* set) { \
- set->Set##METHOD(number, field_type, value); \
+ set->Set##METHOD(number, field_type, value, NULL); \
} \
\
template<> inline TYPE RepeatedPrimitiveTypeTraits<TYPE>::Get( \
@@ -516,7 +606,7 @@ template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Set( \
template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add( \
int number, FieldType field_type, bool is_packed, \
TYPE value, ExtensionSet* set) { \
- set->Add##METHOD(number, field_type, is_packed, value); \
+ set->Add##METHOD(number, field_type, is_packed, value, NULL); \
}
PROTOBUF_DEFINE_PRIMITIVE_TYPE( int32, Int32)
@@ -544,11 +634,11 @@ class LIBPROTOBUF_EXPORT StringTypeTraits {
}
static inline void Set(int number, FieldType field_type,
const string& value, ExtensionSet* set) {
- set->SetString(number, field_type, value);
+ set->SetString(number, field_type, value, NULL);
}
static inline string* Mutable(int number, FieldType field_type,
ExtensionSet* set) {
- return set->MutableString(number, field_type);
+ return set->MutableString(number, field_type, NULL);
}
};
@@ -571,11 +661,11 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
static inline void Add(int number, FieldType field_type,
bool /*is_packed*/, const string& value,
ExtensionSet* set) {
- set->AddString(number, field_type, value);
+ set->AddString(number, field_type, value, NULL);
}
static inline string* Add(int number, FieldType field_type,
ExtensionSet* set) {
- return set->AddString(number, field_type);
+ return set->AddString(number, field_type, NULL);
}
};
@@ -596,7 +686,7 @@ class EnumTypeTraits {
static inline void Set(int number, FieldType field_type,
ConstType value, ExtensionSet* set) {
GOOGLE_DCHECK(IsValid(value));
- set->SetEnum(number, field_type, value);
+ set->SetEnum(number, field_type, value, NULL);
}
};
@@ -616,7 +706,7 @@ class RepeatedEnumTypeTraits {
static inline void Add(int number, FieldType field_type,
bool is_packed, ConstType value, ExtensionSet* set) {
GOOGLE_DCHECK(IsValid(value));
- set->AddEnum(number, field_type, is_packed, value);
+ set->AddEnum(number, field_type, is_packed, value, NULL);
}
};
@@ -640,7 +730,7 @@ class MessageTypeTraits {
static inline MutableType Mutable(int number, FieldType field_type,
ExtensionSet* set) {
return static_cast<Type*>(
- set->MutableMessage(number, field_type, Type::default_instance()));
+ set->MutableMessage(number, field_type, Type::default_instance(), NULL));
}
};
@@ -659,7 +749,7 @@ class RepeatedMessageTypeTraits {
static inline MutableType Add(int number, FieldType field_type,
ExtensionSet* set) {
return static_cast<Type*>(
- set->AddMessage(number, field_type, Type::default_instance()));
+ set->AddMessage(number, field_type, Type::default_instance(), NULL));
}
};
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
index 8555f6f8..426ec5f4 100644
--- a/src/google/protobuf/extension_set_heavy.cc
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -40,6 +40,7 @@
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite_inl.h>
namespace google {
namespace protobuf {
@@ -58,12 +59,26 @@ void ExtensionSet::AppendToList(const Descriptor* containing_type,
}
if (has) {
- output->push_back(
- pool->FindExtensionByNumber(containing_type, iter->first));
+ // TODO(kenton): Looking up each field by number is somewhat unfortunate.
+ // Is there a better way? The problem is that descriptors are lazily-
+ // initialized, so they might not even be constructed until
+ // AppendToList() is called.
+
+ if (iter->second.descriptor == NULL) {
+ output->push_back(pool->FindExtensionByNumber(
+ containing_type, iter->first));
+ } else {
+ output->push_back(iter->second.descriptor);
+ }
}
}
}
+inline FieldDescriptor::Type real_type(FieldType type) {
+ GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE);
+ return static_cast<FieldDescriptor::Type>(type);
+}
+
inline FieldDescriptor::CppType cpp_type(FieldType type) {
return FieldDescriptor::TypeToCppType(
static_cast<FieldDescriptor::Type>(type));
@@ -88,16 +103,16 @@ const MessageLite& ExtensionSet::GetMessage(int number,
}
}
-MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
- const Descriptor* message_type,
+MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor,
MessageFactory* factory) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
- extension->type = type;
+ if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
+ extension->type = descriptor->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);
+ const MessageLite* prototype =
+ factory->GetPrototype(descriptor->message_type());
GOOGLE_CHECK(prototype != NULL);
extension->message_value = prototype->New();
} else {
@@ -107,12 +122,11 @@ MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
return extension->message_value;
}
-MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
- const Descriptor* message_type,
+MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
MessageFactory* factory) {
Extension* extension;
- if (MaybeNewExtension(number, &extension)) {
- extension->type = type;
+ if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
+ extension->type = descriptor->type();
GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
extension->is_repeated = true;
extension->repeated_message_value =
@@ -128,7 +142,7 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
if (result == NULL) {
const MessageLite* prototype;
if (extension->repeated_message_value->size() == 0) {
- prototype = factory->GetPrototype(message_type);
+ prototype = factory->GetPrototype(descriptor->message_type());
GOOGLE_CHECK(prototype != NULL);
} else {
prototype = &extension->repeated_message_value->Get(0);
@@ -139,18 +153,64 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
return result;
}
+static bool ValidateEnumUsingDescriptor(const void* arg, int number) {
+ return reinterpret_cast<const EnumDescriptor*>(arg)
+ ->FindValueByNumber(number) != NULL;
+}
+
+bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) {
+ const FieldDescriptor* extension =
+ pool_->FindExtensionByNumber(containing_type_, number);
+ if (extension == NULL) {
+ return false;
+ } else {
+ output->type = extension->type();
+ output->is_repeated = extension->is_repeated();
+ output->is_packed = extension->options().packed();
+ output->descriptor = extension;
+ if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ output->message_prototype =
+ factory_->GetPrototype(extension->message_type());
+ GOOGLE_CHECK(output->message_prototype != NULL)
+ << "Extension factory's GetPrototype() returned NULL for extension: "
+ << extension->full_name();
+ } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ output->enum_is_valid = ValidateEnumUsingDescriptor;
+ output->enum_is_valid_arg = extension->enum_type();
+ }
+
+ return true;
+ }
+}
+
bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
- const MessageLite* containing_type,
+ const Message* containing_type,
UnknownFieldSet* unknown_fields) {
UnknownFieldSetFieldSkipper skipper(unknown_fields);
- return ParseField(tag, input, containing_type, &skipper);
+ if (input->GetExtensionPool() == NULL) {
+ GeneratedExtensionFinder finder(containing_type);
+ return ParseField(tag, input, &finder, &skipper);
+ } else {
+ DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
+ input->GetExtensionFactory(),
+ containing_type->GetDescriptor());
+ return ParseField(tag, input, &finder, &skipper);
+ }
}
bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
- const MessageLite* containing_type,
+ const Message* containing_type,
UnknownFieldSet* unknown_fields) {
UnknownFieldSetFieldSkipper skipper(unknown_fields);
- return ParseMessageSet(input, containing_type, &skipper);
+ if (input->GetExtensionPool() == NULL) {
+ GeneratedExtensionFinder finder(containing_type);
+ return ParseMessageSet(input, &finder, &skipper);
+ } else {
+ DescriptorPoolExtensionFinder finder(input->GetExtensionPool(),
+ input->GetExtensionFactory(),
+ containing_type->GetDescriptor());
+ return ParseMessageSet(input, &finder, &skipper);
+ }
}
int ExtensionSet::SpaceUsedExcludingSelf() const {
@@ -175,7 +235,7 @@ int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
if (is_repeated) {
switch (cpp_type(type)) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
- case WireFormatLite::CPPTYPE_##UPPERCASE: \
+ case FieldDescriptor::CPPTYPE_##UPPERCASE: \
total_size += sizeof(*repeated_##LOWERCASE##_value) + \
repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\
break
@@ -189,8 +249,9 @@ int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
HANDLE_TYPE( BOOL, bool);
HANDLE_TYPE( ENUM, enum);
HANDLE_TYPE( STRING, string);
+#undef HANDLE_TYPE
- case WireFormatLite::CPPTYPE_MESSAGE:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
// repeated_message_value is actually a RepeatedPtrField<MessageLite>,
// but MessageLite has no SpaceUsed(), so we must directly call
// RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type
@@ -201,11 +262,11 @@ int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
}
} else {
switch (cpp_type(type)) {
- case WireFormatLite::CPPTYPE_STRING:
+ case FieldDescriptor::CPPTYPE_STRING:
total_size += sizeof(*string_value) +
StringSpaceUsedExcludingSelf(*string_value);
break;
- case WireFormatLite::CPPTYPE_MESSAGE:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
total_size += down_cast<Message*>(message_value)->SpaceUsed();
break;
default:
@@ -216,6 +277,162 @@ int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
return total_size;
}
+// The Serialize*ToArray methods are only needed in the heavy library, as
+// the lite library only generates SerializeWithCachedSizes.
+uint8* ExtensionSet::SerializeWithCachedSizesToArray(
+ int start_field_number, int end_field_number,
+ uint8* target) const {
+ map<int, Extension>::const_iterator iter;
+ for (iter = extensions_.lower_bound(start_field_number);
+ iter != extensions_.end() && iter->first < end_field_number;
+ ++iter) {
+ target = iter->second.SerializeFieldWithCachedSizesToArray(iter->first,
+ target);
+ }
+ return target;
+}
+
+uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray(
+ uint8* target) const {
+ map<int, Extension>::const_iterator iter;
+ for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
+ target = iter->second.SerializeMessageSetItemWithCachedSizesToArray(
+ iter->first, target);
+ }
+ return target;
+}
+
+uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray(
+ int number, uint8* target) const {
+ if (is_repeated) {
+ if (is_packed) {
+ if (cached_size == 0) return target;
+
+ target = WireFormatLite::WriteTagToArray(number,
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target);
+ target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target);
+
+ switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
+ case FieldDescriptor::TYPE_##UPPERCASE: \
+ for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
+ target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \
+ repeated_##LOWERCASE##_value->Get(i), target); \
+ } \
+ break
+
+ HANDLE_TYPE( INT32, Int32, int32);
+ HANDLE_TYPE( INT64, Int64, int64);
+ HANDLE_TYPE( UINT32, UInt32, uint32);
+ HANDLE_TYPE( UINT64, UInt64, uint64);
+ HANDLE_TYPE( SINT32, SInt32, int32);
+ HANDLE_TYPE( SINT64, SInt64, int64);
+ HANDLE_TYPE( FIXED32, Fixed32, uint32);
+ HANDLE_TYPE( FIXED64, Fixed64, uint64);
+ HANDLE_TYPE(SFIXED32, SFixed32, int32);
+ HANDLE_TYPE(SFIXED64, SFixed64, int64);
+ HANDLE_TYPE( FLOAT, Float, float);
+ HANDLE_TYPE( DOUBLE, Double, double);
+ HANDLE_TYPE( BOOL, Bool, bool);
+ HANDLE_TYPE( ENUM, Enum, enum);
+#undef HANDLE_TYPE
+
+ 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: \
+ for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
+ target = WireFormatLite::Write##CAMELCASE##ToArray(number, \
+ repeated_##LOWERCASE##_value->Get(i), target); \
+ } \
+ break
+
+ HANDLE_TYPE( INT32, Int32, int32);
+ HANDLE_TYPE( INT64, Int64, int64);
+ HANDLE_TYPE( UINT32, UInt32, uint32);
+ HANDLE_TYPE( UINT64, UInt64, uint64);
+ HANDLE_TYPE( SINT32, SInt32, int32);
+ HANDLE_TYPE( SINT64, SInt64, int64);
+ HANDLE_TYPE( FIXED32, Fixed32, uint32);
+ HANDLE_TYPE( FIXED64, Fixed64, uint64);
+ HANDLE_TYPE(SFIXED32, SFixed32, int32);
+ HANDLE_TYPE(SFIXED64, SFixed64, int64);
+ HANDLE_TYPE( FLOAT, Float, float);
+ HANDLE_TYPE( DOUBLE, Double, double);
+ HANDLE_TYPE( BOOL, Bool, bool);
+ HANDLE_TYPE( STRING, String, string);
+ HANDLE_TYPE( BYTES, Bytes, string);
+ HANDLE_TYPE( ENUM, Enum, enum);
+ HANDLE_TYPE( GROUP, Group, message);
+ HANDLE_TYPE( MESSAGE, Message, message);
+#undef HANDLE_TYPE
+ }
+ }
+ } else if (!is_cleared) {
+ switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \
+ case FieldDescriptor::TYPE_##UPPERCASE: \
+ target = WireFormatLite::Write##CAMELCASE##ToArray( \
+ number, VALUE, target); \
+ break
+
+ HANDLE_TYPE( INT32, Int32, int32_value);
+ HANDLE_TYPE( INT64, Int64, int64_value);
+ HANDLE_TYPE( UINT32, UInt32, uint32_value);
+ HANDLE_TYPE( UINT64, UInt64, uint64_value);
+ HANDLE_TYPE( SINT32, SInt32, int32_value);
+ HANDLE_TYPE( SINT64, SInt64, int64_value);
+ HANDLE_TYPE( FIXED32, Fixed32, uint32_value);
+ HANDLE_TYPE( FIXED64, Fixed64, uint64_value);
+ HANDLE_TYPE(SFIXED32, SFixed32, int32_value);
+ HANDLE_TYPE(SFIXED64, SFixed64, int64_value);
+ HANDLE_TYPE( FLOAT, Float, float_value);
+ HANDLE_TYPE( DOUBLE, Double, double_value);
+ HANDLE_TYPE( BOOL, Bool, bool_value);
+ HANDLE_TYPE( STRING, String, *string_value);
+ HANDLE_TYPE( BYTES, Bytes, *string_value);
+ HANDLE_TYPE( ENUM, Enum, enum_value);
+ HANDLE_TYPE( GROUP, Group, *message_value);
+ HANDLE_TYPE( MESSAGE, Message, *message_value);
+#undef HANDLE_TYPE
+ }
+ }
+ return target;
+}
+
+uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray(
+ int number,
+ uint8* target) const {
+ if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) {
+ // Not a valid MessageSet extension, but serialize it the normal way.
+ GOOGLE_LOG(WARNING) << "Invalid message set extension.";
+ return SerializeFieldWithCachedSizesToArray(number, target);
+ }
+
+ if (is_cleared) return target;
+
+ // Start group.
+ target = io::CodedOutputStream::WriteTagToArray(
+ WireFormatLite::kMessageSetItemStartTag, target);
+ // Write type ID.
+ target = WireFormatLite::WriteUInt32ToArray(
+ WireFormatLite::kMessageSetTypeIdNumber, number, target);
+ // Write message.
+ target = WireFormatLite::WriteMessageToArray(
+ WireFormatLite::kMessageSetMessageNumber, *message_value, target);
+ // End group.
+ target = io::CodedOutputStream::WriteTagToArray(
+ WireFormatLite::kMessageSetItemEndTag, target);
+ return target;
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc
index 327aee02..000f846c 100644
--- a/src/google/protobuf/extension_set_unittest.cc
+++ b/src/google/protobuf/extension_set_unittest.cc
@@ -35,10 +35,15 @@
#include <google/protobuf/extension_set.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/test_util.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/wire_format.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
#include <google/protobuf/stubs/stl_util-inl.h>
@@ -477,6 +482,160 @@ TEST(ExtensionSetTest, InvalidEnumDeath) {
#endif // GTEST_HAS_DEATH_TEST
+TEST(ExtensionSetTest, DynamicExtensions) {
+ // Test adding a dynamic extension to a compiled-in message object.
+
+ FileDescriptorProto dynamic_proto;
+ dynamic_proto.set_name("dynamic_extensions_test.proto");
+ dynamic_proto.add_dependency(
+ unittest::TestAllExtensions::descriptor()->file()->name());
+ dynamic_proto.set_package("dynamic_extensions");
+
+ // Copy the fields and nested types from TestDynamicExtensions into our new
+ // proto, converting the fields into extensions.
+ const Descriptor* template_descriptor =
+ unittest::TestDynamicExtensions::descriptor();
+ DescriptorProto template_descriptor_proto;
+ template_descriptor->CopyTo(&template_descriptor_proto);
+ dynamic_proto.mutable_message_type()->MergeFrom(
+ template_descriptor_proto.nested_type());
+ dynamic_proto.mutable_enum_type()->MergeFrom(
+ template_descriptor_proto.enum_type());
+ dynamic_proto.mutable_extension()->MergeFrom(
+ template_descriptor_proto.field());
+
+ // For each extension that we added...
+ for (int i = 0; i < dynamic_proto.extension_size(); i++) {
+ // Set its extendee to TestAllExtensions.
+ FieldDescriptorProto* extension = dynamic_proto.mutable_extension(i);
+ extension->set_extendee(
+ unittest::TestAllExtensions::descriptor()->full_name());
+
+ // If the field refers to one of the types nested in TestDynamicExtensions,
+ // make it refer to the type in our dynamic proto instead.
+ string prefix = "." + template_descriptor->full_name() + ".";
+ if (extension->has_type_name()) {
+ string* type_name = extension->mutable_type_name();
+ if (HasPrefixString(*type_name, prefix)) {
+ type_name->replace(0, prefix.size(), ".dynamic_extensions.");
+ }
+ }
+ }
+
+ // Now build the file, using the generated pool as an underlay.
+ DescriptorPool dynamic_pool(DescriptorPool::generated_pool());
+ const FileDescriptor* file = dynamic_pool.BuildFile(dynamic_proto);
+ ASSERT_TRUE(file != NULL);
+ DynamicMessageFactory dynamic_factory(&dynamic_pool);
+ dynamic_factory.SetDelegateToGeneratedFactory(true);
+
+ // Construct a message that we can parse with the extensions we defined.
+ // Since the extensions were based off of the fields of TestDynamicExtensions,
+ // we can use that message to create this test message.
+ string data;
+ {
+ unittest::TestDynamicExtensions message;
+ message.set_scalar_extension(123);
+ message.set_enum_extension(unittest::FOREIGN_BAR);
+ message.set_dynamic_enum_extension(
+ unittest::TestDynamicExtensions::DYNAMIC_BAZ);
+ message.mutable_message_extension()->set_c(456);
+ message.mutable_dynamic_message_extension()->set_dynamic_field(789);
+ message.add_repeated_extension("foo");
+ message.add_repeated_extension("bar");
+ message.add_packed_extension(12);
+ message.add_packed_extension(-34);
+ message.add_packed_extension(56);
+ message.add_packed_extension(-78);
+
+ // Also add some unknown fields.
+
+ // An unknown enum value (for a known field).
+ message.mutable_unknown_fields()->AddVarint(
+ unittest::TestDynamicExtensions::kDynamicEnumExtensionFieldNumber,
+ 12345);
+ // A regular unknown field.
+ message.mutable_unknown_fields()->AddLengthDelimited(54321, "unknown");
+
+ message.SerializeToString(&data);
+ }
+
+ // Now we can parse this using our dynamic extension definitions...
+ unittest::TestAllExtensions message;
+ {
+ io::ArrayInputStream raw_input(data.data(), data.size());
+ io::CodedInputStream input(&raw_input);
+ input.SetExtensionRegistry(&dynamic_pool, &dynamic_factory);
+ ASSERT_TRUE(message.ParseFromCodedStream(&input));
+ ASSERT_TRUE(input.ConsumedEntireMessage());
+ }
+
+ // Can we print it?
+ EXPECT_EQ(
+ "[dynamic_extensions.scalar_extension]: 123\n"
+ "[dynamic_extensions.enum_extension]: FOREIGN_BAR\n"
+ "[dynamic_extensions.dynamic_enum_extension]: DYNAMIC_BAZ\n"
+ "[dynamic_extensions.message_extension] {\n"
+ " c: 456\n"
+ "}\n"
+ "[dynamic_extensions.dynamic_message_extension] {\n"
+ " dynamic_field: 789\n"
+ "}\n"
+ "[dynamic_extensions.repeated_extension]: \"foo\"\n"
+ "[dynamic_extensions.repeated_extension]: \"bar\"\n"
+ "[dynamic_extensions.packed_extension]: 12\n"
+ "[dynamic_extensions.packed_extension]: -34\n"
+ "[dynamic_extensions.packed_extension]: 56\n"
+ "[dynamic_extensions.packed_extension]: -78\n"
+ "2002: 12345\n"
+ "54321: \"unknown\"\n",
+ message.DebugString());
+
+ // Can we serialize it?
+ // (Don't use EXPECT_EQ because we don't want to dump raw binary data to the
+ // terminal on failure.)
+ EXPECT_TRUE(message.SerializeAsString() == data);
+
+ // What if we parse using the reflection-based parser?
+ {
+ unittest::TestAllExtensions message2;
+ io::ArrayInputStream raw_input(data.data(), data.size());
+ io::CodedInputStream input(&raw_input);
+ input.SetExtensionRegistry(&dynamic_pool, &dynamic_factory);
+ ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &message2));
+ ASSERT_TRUE(input.ConsumedEntireMessage());
+ EXPECT_EQ(message.DebugString(), message2.DebugString());
+ }
+
+ // Are the embedded generated types actually using the generated objects?
+ {
+ const FieldDescriptor* message_extension =
+ file->FindExtensionByName("message_extension");
+ ASSERT_TRUE(message_extension != NULL);
+ const Message& sub_message =
+ message.GetReflection()->GetMessage(message, message_extension);
+ const unittest::ForeignMessage* typed_sub_message =
+ dynamic_cast<const unittest::ForeignMessage*>(&sub_message);
+ ASSERT_TRUE(typed_sub_message != NULL);
+ EXPECT_EQ(456, typed_sub_message->c());
+ }
+
+ // What does GetMessage() return for the embedded dynamic type if it isn't
+ // present?
+ {
+ const FieldDescriptor* dynamic_message_extension =
+ file->FindExtensionByName("dynamic_message_extension");
+ ASSERT_TRUE(dynamic_message_extension != NULL);
+ const Message& parent = unittest::TestAllExtensions::default_instance();
+ const Message& sub_message =
+ parent.GetReflection()->GetMessage(parent, dynamic_message_extension,
+ &dynamic_factory);
+ const Message* prototype =
+ dynamic_factory.GetPrototype(dynamic_message_extension->message_type());
+ EXPECT_EQ(prototype, &sub_message);
+ }
+}
+
} // namespace
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index e04b93cc..0f065ff2 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -239,8 +239,13 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING:
- total_size += GetRaw<RepeatedPtrField<string> >(message, field)
- .SpaceUsedExcludingSelf();
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ total_size += GetRaw<RepeatedPtrField<string> >(message, field)
+ .SpaceUsedExcludingSelf();
+ break;
+ }
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
@@ -265,18 +270,24 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
break;
case FieldDescriptor::CPPTYPE_STRING: {
- const string* ptr = GetField<const string*>(message, field);
-
- // Initially, the string points to the default value stored in
- // the prototype. Only count the string if it has been changed
- // from the default value.
- const string* default_ptr = DefaultRaw<const string*>(field);
-
- if (ptr != default_ptr) {
- // string fields are represented by just a pointer, so also
- // include sizeof(string) as well.
- total_size += sizeof(*ptr) + StringSpaceUsedExcludingSelf(*ptr);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING: {
+ const string* ptr = GetField<const string*>(message, field);
+
+ // Initially, the string points to the default value stored in
+ // the prototype. Only count the string if it has been changed
+ // from the default value.
+ const string* default_ptr = DefaultRaw<const string*>(field);
+
+ if (ptr != default_ptr) {
+ // string fields are represented by just a pointer, so also
+ // include sizeof(string) as well.
+ total_size += sizeof(*ptr) + StringSpaceUsedExcludingSelf(*ptr);
+ }
+ break;
}
+ }
break;
}
@@ -376,8 +387,13 @@ void GeneratedMessageReflection::Swap(
#undef SWAP_VALUES
case FieldDescriptor::CPPTYPE_STRING:
- std::swap(*MutableRaw<string*>(message1, field),
- *MutableRaw<string*>(message2, field));
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ std::swap(*MutableRaw<string*>(message1, field),
+ *MutableRaw<string*>(message2, field));
+ break;
+ }
break;
default:
@@ -473,15 +489,20 @@ void GeneratedMessageReflection::ClearField(
break;
case FieldDescriptor::CPPTYPE_STRING: {
- const string* default_ptr = DefaultRaw<const string*>(field);
- string** value = MutableRaw<string*>(message, field);
- if (*value != default_ptr) {
- if (field->has_default_value()) {
- (*value)->assign(field->default_value_string());
- } else {
- (*value)->clear();
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ const string* default_ptr = DefaultRaw<const string*>(field);
+ string** value = MutableRaw<string*>(message, field);
+ if (*value != default_ptr) {
+ if (field->has_default_value()) {
+ (*value)->assign(field->default_value_string());
+ } else {
+ (*value)->clear();
+ }
}
- }
+ break;
+ }
break;
}
@@ -508,7 +529,12 @@ void GeneratedMessageReflection::ClearField(
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING: {
- MutableRaw<RepeatedPtrField<string> >(message, field)->Clear();
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ MutableRaw<RepeatedPtrField<string> >(message, field)->Clear();
+ break;
+ }
break;
}
@@ -549,7 +575,12 @@ void GeneratedMessageReflection::RemoveLast(
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING:
- MutableRaw<RepeatedPtrField<string> >(message, field)->RemoveLast();
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ MutableRaw<RepeatedPtrField<string> >(message, field)->RemoveLast();
+ break;
+ }
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
@@ -658,7 +689,7 @@ void GeneratedMessageReflection::ListFields(
USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \
if (field->is_extension()) { \
return MutableExtensionSet(message)->Set##TYPENAME( \
- field->number(), field->type(), value); \
+ field->number(), field->type(), value, field); \
} else { \
SetField<TYPE>(message, field, value); \
} \
@@ -694,7 +725,8 @@ void GeneratedMessageReflection::ListFields(
USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \
if (field->is_extension()) { \
MutableExtensionSet(message)->Add##TYPENAME( \
- field->number(), field->type(), field->options().packed(), value); \
+ field->number(), field->type(), field->options().packed(), value, \
+ field); \
} else { \
AddField<TYPE>(message, field, value); \
} \
@@ -718,7 +750,14 @@ string GeneratedMessageReflection::GetString(
return GetExtensionSet(message).GetString(field->number(),
field->default_value_string());
} else {
- return *GetField<const string*>(message, field);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ return *GetField<const string*>(message, field);
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return kEmptyString; // Make compiler happy.
}
}
@@ -730,7 +769,14 @@ const string& GeneratedMessageReflection::GetStringReference(
return GetExtensionSet(message).GetString(field->number(),
field->default_value_string());
} else {
- return *GetField<const string*>(message, field);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ return *GetField<const string*>(message, field);
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return kEmptyString; // Make compiler happy.
}
}
@@ -741,13 +787,19 @@ void GeneratedMessageReflection::SetString(
USAGE_CHECK_ALL(SetString, SINGULAR, STRING);
if (field->is_extension()) {
return MutableExtensionSet(message)->SetString(field->number(),
- field->type(), value);
+ field->type(), value, field);
} else {
- string** ptr = MutableField<string*>(message, field);
- if (*ptr == DefaultRaw<const string*>(field)) {
- *ptr = new string(value);
- } else {
- (*ptr)->assign(value);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING: {
+ string** ptr = MutableField<string*>(message, field);
+ if (*ptr == DefaultRaw<const string*>(field)) {
+ *ptr = new string(value);
+ } else {
+ (*ptr)->assign(value);
+ }
+ break;
+ }
}
}
}
@@ -759,7 +811,14 @@ string GeneratedMessageReflection::GetRepeatedString(
if (field->is_extension()) {
return GetExtensionSet(message).GetRepeatedString(field->number(), index);
} else {
- return GetRepeatedPtrField<string>(message, field, index);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ return GetRepeatedPtrField<string>(message, field, index);
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return kEmptyString; // Make compiler happy.
}
}
@@ -770,7 +829,14 @@ const string& GeneratedMessageReflection::GetRepeatedStringReference(
if (field->is_extension()) {
return GetExtensionSet(message).GetRepeatedString(field->number(), index);
} else {
- return GetRepeatedPtrField<string>(message, field, index);
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ return GetRepeatedPtrField<string>(message, field, index);
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return kEmptyString; // Make compiler happy.
}
}
@@ -783,7 +849,12 @@ void GeneratedMessageReflection::SetRepeatedString(
MutableExtensionSet(message)->SetRepeatedString(
field->number(), index, value);
} else {
- *MutableRepeatedField<string>(message, field, index) = value;
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ *MutableRepeatedField<string>(message, field, index) = value;
+ break;
+ }
}
}
@@ -794,9 +865,14 @@ void GeneratedMessageReflection::AddString(
USAGE_CHECK_ALL(AddString, REPEATED, STRING);
if (field->is_extension()) {
MutableExtensionSet(message)->AddString(field->number(),
- field->type(), value);
+ field->type(), value, field);
} else {
- *AddField<string>(message, field) = value;
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ *AddField<string>(message, field) = value;
+ break;
+ }
}
}
@@ -828,7 +904,7 @@ void GeneratedMessageReflection::SetEnum(
if (field->is_extension()) {
MutableExtensionSet(message)->SetEnum(field->number(), field->type(),
- value->number());
+ value->number(), field);
} else {
SetField<int>(message, field, value->number());
}
@@ -874,7 +950,7 @@ void GeneratedMessageReflection::AddEnum(
if (field->is_extension()) {
MutableExtensionSet(message)->AddEnum(field->number(), field->type(),
field->options().packed(),
- value->number());
+ value->number(), field);
} else {
AddField<int>(message, field, value->number());
}
@@ -883,14 +959,15 @@ void GeneratedMessageReflection::AddEnum(
// -------------------------------------------------------------------
const Message& GeneratedMessageReflection::GetMessage(
- const Message& message, const FieldDescriptor* field) const {
+ const Message& message, const FieldDescriptor* field,
+ MessageFactory* factory) const {
USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
if (field->is_extension()) {
return static_cast<const Message&>(
- GetExtensionSet(message).GetMessage(field->number(),
- field->message_type(),
- message_factory_));
+ GetExtensionSet(message).GetMessage(
+ field->number(), field->message_type(),
+ factory == NULL ? message_factory_ : factory));
} else {
const Message* result = GetRaw<const Message*>(message, field);
if (result == NULL) {
@@ -901,15 +978,14 @@ const Message& GeneratedMessageReflection::GetMessage(
}
Message* GeneratedMessageReflection::MutableMessage(
- Message* message, const FieldDescriptor* field) const {
+ Message* message, const FieldDescriptor* field,
+ MessageFactory* factory) const {
USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
if (field->is_extension()) {
return static_cast<Message*>(
- MutableExtensionSet(message)->MutableMessage(field->number(),
- field->type(),
- field->message_type(),
- message_factory_));
+ MutableExtensionSet(message)->MutableMessage(field,
+ factory == NULL ? message_factory_ : factory));
} else {
Message** result = MutableField<Message*>(message, field);
if (*result == NULL) {
@@ -948,15 +1024,15 @@ Message* GeneratedMessageReflection::MutableRepeatedMessage(
}
Message* GeneratedMessageReflection::AddMessage(
- Message* message, const FieldDescriptor* field) const {
+ Message* message, const FieldDescriptor* field,
+ MessageFactory* factory) const {
USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
+ if (factory == NULL) factory = message_factory_;
+
if (field->is_extension()) {
return static_cast<Message*>(
- MutableExtensionSet(message)->AddMessage(field->number(),
- field->type(),
- field->message_type(),
- message_factory_));
+ MutableExtensionSet(message)->AddMessage(field, factory));
} else {
// We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
// know how to allocate one.
@@ -967,7 +1043,7 @@ Message* GeneratedMessageReflection::AddMessage(
// We must allocate a new object.
const Message* prototype;
if (repeated->size() == 0) {
- prototype = message_factory_->GetPrototype(field->message_type());
+ prototype = factory->GetPrototype(field->message_type());
} else {
prototype = &repeated->Get<GenericTypeHandler<Message> >(0);
}
@@ -1110,7 +1186,7 @@ inline Type* GeneratedMessageReflection::MutableField(
}
template <typename Type>
-inline Type GeneratedMessageReflection::GetRepeatedField(
+inline const Type& GeneratedMessageReflection::GetRepeatedField(
const Message& message, const FieldDescriptor* field, int index) const {
return GetRaw<RepeatedField<Type> >(message, field).Get(index);
}
@@ -1138,7 +1214,7 @@ inline Type* GeneratedMessageReflection::MutableRepeatedField(
template <typename Type>
inline void GeneratedMessageReflection::AddField(
- Message* message, const FieldDescriptor* field, Type value) const {
+ Message* message, const FieldDescriptor* field, const Type& value) const {
MutableRaw<RepeatedField<Type> >(message, field)->Add(value);
}
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index d0b5b43b..b545fa1a 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -169,7 +169,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
const EnumValueDescriptor* GetEnum(const Message& message,
const FieldDescriptor* field) const;
const Message& GetMessage(const Message& message,
- const FieldDescriptor* field) const;
+ const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const;
void SetInt32 (Message* message,
const FieldDescriptor* field, int32 value) const;
@@ -190,7 +191,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
const string& value) const;
void SetEnum (Message* message, const FieldDescriptor* field,
const EnumValueDescriptor* value) const;
- Message* MutableMessage(Message* message, const FieldDescriptor* field) const;
+ Message* MutableMessage(Message* message, const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const;
int32 GetRepeatedInt32 (const Message& message,
const FieldDescriptor* field, int index) const;
@@ -262,7 +264,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
void AddEnum(Message* message,
const FieldDescriptor* field,
const EnumValueDescriptor* value) const;
- Message* AddMessage(Message* message, const FieldDescriptor* field) const;
+ Message* AddMessage(Message* message, const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const;
const FieldDescriptor* FindKnownExtensionByName(const string& name) const;
const FieldDescriptor* FindKnownExtensionByNumber(int number) const;
@@ -314,9 +317,9 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
inline Type* MutableField(Message* message,
const FieldDescriptor* field) const;
template <typename Type>
- inline Type GetRepeatedField(const Message& message,
- const FieldDescriptor* field,
- int index) const;
+ inline const Type& GetRepeatedField(const Message& message,
+ const FieldDescriptor* field,
+ int index) const;
template <typename Type>
inline const Type& GetRepeatedPtrField(const Message& message,
const FieldDescriptor* field,
@@ -331,7 +334,7 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
int index) const;
template <typename Type>
inline void AddField(Message* message,
- const FieldDescriptor* field, Type value) const;
+ const FieldDescriptor* field, const Type& value) const;
template <typename Type>
inline Type* AddField(Message* message,
const FieldDescriptor* field) const;
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
index 9470bb08..7ac015d0 100644
--- a/src/google/protobuf/generated_message_util.cc
+++ b/src/google/protobuf/generated_message_util.cc
@@ -34,10 +34,19 @@
#include <google/protobuf/generated_message_util.h>
+#include <limits>
+
namespace google {
namespace protobuf {
namespace internal {
+double Infinity() {
+ return std::numeric_limits<double>::infinity();
+}
+double NaN() {
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index 80dd028e..f306a2f1 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -43,21 +43,33 @@
namespace google {
namespace protobuf {
+ namespace io {
+ class CodedInputStream; // coded_stream.h
+ }
+}
+
+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.
+// with option 'deprecated=true' is used in the code, or for other things in
+// generated code which are deprecated.
//
// 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
+# define PROTOBUF_DEPRECATED GOOGLE_ATTRIBUTE_DEPRECATED
#else
-# define DEPRECATED_PROTOBUF_FIELD
+# define PROTOBUF_DEPRECATED
#endif
+// Constants for special floating point values.
+double Infinity();
+double NaN();
+
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index e17a4775..6a91a13d 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -38,9 +38,9 @@
// will not cross the end of the buffer, since we can avoid a lot
// of branching in this case.
-#include <stack>
+#include <google/protobuf/io/coded_stream_inl.h>
+#include <algorithm>
#include <limits.h>
-#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stl_util-inl.h>
@@ -52,11 +52,6 @@ namespace io {
namespace {
-static const int kDefaultTotalBytesLimit = 64 << 20; // 64MB
-
-static const int kDefaultTotalBytesWarningThreshold = 32 << 20; // 32MB
-static const int kDefaultRecursionLimit = 64;
-
static const int kMaxVarintBytes = 10;
static const int kMaxVarint32Bytes = 5;
@@ -65,72 +60,28 @@ static const int kMaxVarint32Bytes = 5;
// CodedInputStream ==================================================
-CodedInputStream::CodedInputStream(ZeroCopyInputStream* input)
- : input_(input),
- buffer_(NULL),
- buffer_size_(0),
- total_bytes_read_(0),
- overflow_bytes_(0),
- last_tag_(0),
- legitimate_message_end_(false),
- aliasing_enabled_(false),
- current_limit_(INT_MAX),
- buffer_size_after_limit_(0),
- total_bytes_limit_(kDefaultTotalBytesLimit),
- 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_;
+ int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_;
if (backup_bytes > 0) {
input_->BackUp(backup_bytes);
// total_bytes_read_ doesn't include overflow_bytes_.
- total_bytes_read_ -= buffer_size_ + buffer_size_after_limit_;
- buffer_size_ = 0;
+ total_bytes_read_ -= BufferSize() + buffer_size_after_limit_;
+ buffer_end_ = buffer_;
buffer_size_after_limit_ = 0;
overflow_bytes_ = 0;
}
}
inline void CodedInputStream::RecomputeBufferLimits() {
- buffer_size_ += buffer_size_after_limit_;
+ buffer_end_ += buffer_size_after_limit_;
int closest_limit = min(current_limit_, total_bytes_limit_);
if (closest_limit < total_bytes_read_) {
// The limit position is in the current buffer. We must adjust
// the buffer size accordingly.
buffer_size_after_limit_ = total_bytes_read_ - closest_limit;
- buffer_size_ -= buffer_size_after_limit_;
+ buffer_end_ -= buffer_size_after_limit_;
} else {
buffer_size_after_limit_ = 0;
}
@@ -139,7 +90,7 @@ inline void CodedInputStream::RecomputeBufferLimits() {
CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
// Current position relative to the beginning of the stream.
int current_position = total_bytes_read_ -
- (buffer_size_ + buffer_size_after_limit_);
+ (BufferSize() + buffer_size_after_limit_);
Limit old_limit = current_limit_;
@@ -176,7 +127,7 @@ void CodedInputStream::PopLimit(Limit limit) {
int CodedInputStream::BytesUntilLimit() {
if (current_limit_ == INT_MAX) return -1;
int current_position = total_bytes_read_ -
- (buffer_size_ + buffer_size_after_limit_);
+ (BufferSize() + buffer_size_after_limit_);
return current_limit_ - current_position;
}
@@ -186,7 +137,7 @@ void CodedInputStream::SetTotalBytesLimit(
// Make sure the limit isn't already past, since this could confuse other
// code.
int current_position = total_bytes_read_ -
- (buffer_size_ + buffer_size_after_limit_);
+ (BufferSize() + buffer_size_after_limit_);
total_bytes_limit_ = max(current_position, total_bytes_limit);
total_bytes_warning_threshold_ = warning_threshold;
RecomputeBufferLimits();
@@ -203,7 +154,9 @@ void CodedInputStream::PrintTotalBytesLimitError() {
bool CodedInputStream::Skip(int count) {
if (count < 0) return false; // security: count is often user-supplied
- if (count <= buffer_size_) {
+ const int original_buffer_size = BufferSize();
+
+ if (count <= original_buffer_size) {
// Just skipping within the current buffer. Easy.
Advance(count);
return true;
@@ -211,13 +164,13 @@ bool CodedInputStream::Skip(int count) {
if (buffer_size_after_limit_ > 0) {
// We hit a limit inside this buffer. Advance to the limit and fail.
- Advance(buffer_size_);
+ Advance(original_buffer_size);
return false;
}
- count -= buffer_size_;
+ count -= original_buffer_size;
buffer_ = NULL;
- buffer_size_ = 0;
+ buffer_end_ = buffer_;
// Make sure this skip doesn't try to skip past the current limit.
int closest_limit = min(current_limit_, total_bytes_limit_);
@@ -236,20 +189,21 @@ bool CodedInputStream::Skip(int count) {
}
bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) {
- if (buffer_size_ == 0 && !Refresh()) return false;
+ if (BufferSize() == 0 && !Refresh()) return false;
*data = buffer_;
- *size = buffer_size_;
+ *size = BufferSize();
return true;
}
bool CodedInputStream::ReadRaw(void* buffer, int size) {
- while (buffer_size_ < size) {
+ int current_buffer_size;
+ while ((current_buffer_size = BufferSize()) < size) {
// Reading past end of buffer. Copy what we have, then refresh.
- memcpy(buffer, buffer_, buffer_size_);
- buffer = reinterpret_cast<uint8*>(buffer) + buffer_size_;
- size -= buffer_size_;
- Advance(buffer_size_);
+ memcpy(buffer, buffer_, current_buffer_size);
+ buffer = reinterpret_cast<uint8*>(buffer) + current_buffer_size;
+ size -= current_buffer_size;
+ Advance(current_buffer_size);
if (!Refresh()) return false;
}
@@ -261,27 +215,25 @@ bool CodedInputStream::ReadRaw(void* buffer, int size) {
bool CodedInputStream::ReadString(string* buffer, int size) {
if (size < 0) return false; // security: size is often user-supplied
+ return InternalReadStringInline(buffer, size);
+}
+bool CodedInputStream::ReadStringFallback(string* buffer, int size) {
if (!buffer->empty()) {
buffer->clear();
}
- if (size < buffer_size_) {
- STLStringResizeUninitialized(buffer, size);
- memcpy((uint8*)buffer->data(), buffer_, size);
- Advance(size);
- return true;
- }
-
- while (buffer_size_ < size) {
+ int current_buffer_size;
+ while ((current_buffer_size = BufferSize()) < size) {
// Some STL implementations "helpfully" crash on buffer->append(NULL, 0).
- if (buffer_size_ != 0) {
+ if (current_buffer_size != 0) {
// Note: string1.append(string2) is O(string2.size()) (as opposed to
// O(string1.size() + string2.size()), which would be bad).
- buffer->append(reinterpret_cast<const char*>(buffer_), buffer_size_);
+ buffer->append(reinterpret_cast<const char*>(buffer_),
+ current_buffer_size);
}
- size -= buffer_size_;
- Advance(buffer_size_);
+ size -= current_buffer_size;
+ Advance(current_buffer_size);
if (!Refresh()) return false;
}
@@ -292,11 +244,11 @@ bool CodedInputStream::ReadString(string* buffer, int size) {
}
-bool CodedInputStream::ReadLittleEndian32(uint32* value) {
+bool CodedInputStream::ReadLittleEndian32Fallback(uint32* value) {
uint8 bytes[sizeof(*value)];
const uint8* ptr;
- if (buffer_size_ >= sizeof(*value)) {
+ if (BufferSize() >= sizeof(*value)) {
// Fast path: Enough bytes in the buffer to read directly.
ptr = buffer_;
Advance(sizeof(*value));
@@ -305,19 +257,15 @@ bool CodedInputStream::ReadLittleEndian32(uint32* value) {
if (!ReadRaw(bytes, sizeof(*value))) return false;
ptr = bytes;
}
-
- *value = (static_cast<uint32>(ptr[0]) ) |
- (static_cast<uint32>(ptr[1]) << 8) |
- (static_cast<uint32>(ptr[2]) << 16) |
- (static_cast<uint32>(ptr[3]) << 24);
+ ReadLittleEndian32FromArray(ptr, value);
return true;
}
-bool CodedInputStream::ReadLittleEndian64(uint64* value) {
+bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) {
uint8 bytes[sizeof(*value)];
const uint8* ptr;
- if (buffer_size_ >= sizeof(*value)) {
+ if (BufferSize() >= sizeof(*value)) {
// Fast path: Enough bytes in the buffer to read directly.
ptr = buffer_;
Advance(sizeof(*value));
@@ -326,99 +274,152 @@ bool CodedInputStream::ReadLittleEndian64(uint64* value) {
if (!ReadRaw(bytes, sizeof(*value))) return false;
ptr = bytes;
}
+ ReadLittleEndian64FromArray(ptr, value);
+ return true;
+}
+
+namespace {
+
+inline const uint8* ReadVarint32FromArray(
+ const uint8* buffer, uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) {
+ // Fast path: We have enough bytes left in the buffer to guarantee that
+ // this read won't cross the end, so we can skip the checks.
+ const uint8* ptr = buffer;
+ uint32 b;
+ uint32 result;
+
+ b = *(ptr++); result = (b & 0x7F) ; if (!(b & 0x80)) goto done;
+ b = *(ptr++); result |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
+ b = *(ptr++); result |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
+ b = *(ptr++); result |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
+ b = *(ptr++); result |= b << 28; if (!(b & 0x80)) goto done;
+
+ // If the input is larger than 32 bits, we still need to read it all
+ // and discard the high-order bits.
+ for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) {
+ b = *(ptr++); if (!(b & 0x80)) goto done;
+ }
+
+ // We have overrun the maximum size of a varint (10 bytes). Assume
+ // the data is corrupt.
+ return NULL;
+
+ done:
+ *value = result;
+ return ptr;
+}
+
+} // namespace
- uint32 part0 = (static_cast<uint32>(ptr[0]) ) |
- (static_cast<uint32>(ptr[1]) << 8) |
- (static_cast<uint32>(ptr[2]) << 16) |
- (static_cast<uint32>(ptr[3]) << 24);
- uint32 part1 = (static_cast<uint32>(ptr[4]) ) |
- (static_cast<uint32>(ptr[5]) << 8) |
- (static_cast<uint32>(ptr[6]) << 16) |
- (static_cast<uint32>(ptr[7]) << 24);
- *value = static_cast<uint64>(part0) |
- (static_cast<uint64>(part1) << 32);
+bool CodedInputStream::ReadVarint32Slow(uint32* value) {
+ uint64 result;
+ // Directly invoke ReadVarint64Fallback, since we already tried to optimize
+ // for one-byte varints.
+ if (!ReadVarint64Fallback(&result)) return false;
+ *value = (uint32)result;
return true;
}
bool CodedInputStream::ReadVarint32Fallback(uint32* value) {
- if (buffer_size_ >= kMaxVarintBytes ||
+ if (BufferSize() >= kMaxVarintBytes ||
// Optimization: If the varint ends at exactly the end of the buffer,
// we can detect that and still use the fast path.
- (buffer_size_ != 0 && !(buffer_[buffer_size_-1] & 0x80))) {
- // Fast path: We have enough bytes left in the buffer to guarantee that
- // this read won't cross the end, so we can skip the checks.
- const uint8* ptr = buffer_;
- uint32 b;
- uint32 result;
-
- b = *(ptr++); result = (b & 0x7F) ; if (!(b & 0x80)) goto done;
- b = *(ptr++); result |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done;
- b = *(ptr++); result |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done;
- b = *(ptr++); result |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done;
- b = *(ptr++); result |= b << 28; if (!(b & 0x80)) goto done;
-
- // If the input is larger than 32 bits, we still need to read it all
- // and discard the high-order bits.
- for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) {
- b = *(ptr++); if (!(b & 0x80)) goto done;
- }
-
- // We have overrun the maximum size of a varint (10 bytes). Assume
- // the data is corrupt.
- return false;
-
- done:
- Advance(ptr - buffer_);
- *value = result;
+ (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
+ const uint8* end = ReadVarint32FromArray(buffer_, value);
+ if (end == NULL) return false;
+ buffer_ = end;
return true;
-
} else {
- // Optimization: If we're at a limit, detect that quickly. (This is
- // common when reading tags.)
- while (buffer_size_ == 0) {
- // Detect cases where we definitely hit a byte limit without calling
- // Refresh().
- if (// If we hit a limit, buffer_size_after_limit_ will be non-zero.
- buffer_size_after_limit_ > 0 &&
- // Make sure that the limit we hit is not total_bytes_limit_, since
- // in that case we still need to call Refresh() so that it prints an
- // error.
- total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) {
- // We hit a byte limit.
- legitimate_message_end_ = true;
- return false;
- }
+ // Really slow case: we will incur the cost of an extra function call here,
+ // but moving this out of line reduces the size of this function, which
+ // improves the common case. In micro benchmarks, this is worth about 10-15%
+ return ReadVarint32Slow(value);
+ }
+}
- // Call refresh.
- if (!Refresh()) {
- // Refresh failed. Make sure that it failed due to EOF, not because
- // we hit total_bytes_limit_, which, unlike normal limits, is not a
- // valid place to end a message.
- int current_position = total_bytes_read_ - buffer_size_after_limit_;
- if (current_position >= total_bytes_limit_) {
- // Hit total_bytes_limit_. But if we also hit the normal limit,
- // we're still OK.
- legitimate_message_end_ = current_limit_ == total_bytes_limit_;
- } else {
- legitimate_message_end_ = true;
- }
- return false;
+uint32 CodedInputStream::ReadTagSlow() {
+ if (buffer_ == buffer_end_) {
+ // Call refresh.
+ if (!Refresh()) {
+ // Refresh failed. Make sure that it failed due to EOF, not because
+ // we hit total_bytes_limit_, which, unlike normal limits, is not a
+ // valid place to end a message.
+ int current_position = total_bytes_read_ - buffer_size_after_limit_;
+ if (current_position >= total_bytes_limit_) {
+ // Hit total_bytes_limit_. But if we also hit the normal limit,
+ // we're still OK.
+ legitimate_message_end_ = current_limit_ == total_bytes_limit_;
+ } else {
+ legitimate_message_end_ = true;
}
+ return 0;
}
+ }
- // Slow path: Just do a 64-bit read.
- uint64 result;
- if (!ReadVarint64(&result)) return false;
- *value = (uint32)result;
- return true;
+ // For the slow path, just do a 64-bit read. Try to optimize for one-byte tags
+ // again, since we have now refreshed the buffer.
+ uint64 result;
+ if (!ReadVarint64(&result)) return 0;
+ return static_cast<uint32>(result);
+}
+
+uint32 CodedInputStream::ReadTagFallback() {
+ if (BufferSize() >= kMaxVarintBytes ||
+ // Optimization: If the varint ends at exactly the end of the buffer,
+ // we can detect that and still use the fast path.
+ (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
+ uint32 tag;
+ const uint8* end = ReadVarint32FromArray(buffer_, &tag);
+ if (end == NULL) {
+ return 0;
+ }
+ buffer_ = end;
+ return tag;
+ } else {
+ // We are commonly at a limit when attempting to read tags. Try to quickly
+ // detect this case without making another function call.
+ if (buffer_ == buffer_end_ && buffer_size_after_limit_ > 0 &&
+ // Make sure that the limit we hit is not total_bytes_limit_, since
+ // in that case we still need to call Refresh() so that it prints an
+ // error.
+ total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) {
+ // We hit a byte limit.
+ legitimate_message_end_ = true;
+ return 0;
+ }
+ return ReadTagSlow();
}
}
-bool CodedInputStream::ReadVarint64(uint64* value) {
- if (buffer_size_ >= kMaxVarintBytes ||
+bool CodedInputStream::ReadVarint64Slow(uint64* value) {
+ // Slow path: This read might cross the end of the buffer, so we
+ // need to check and refresh the buffer if and when it does.
+
+ uint64 result = 0;
+ int count = 0;
+ uint32 b;
+
+ do {
+ if (count == kMaxVarintBytes) return false;
+ while (buffer_ == buffer_end_) {
+ if (!Refresh()) return false;
+ }
+ b = *buffer_;
+ result |= static_cast<uint64>(b & 0x7F) << (7 * count);
+ Advance(1);
+ ++count;
+ } while (b & 0x80);
+
+ *value = result;
+ return true;
+}
+
+bool CodedInputStream::ReadVarint64Fallback(uint64* value) {
+ if (BufferSize() >= kMaxVarintBytes ||
// Optimization: If the varint ends at exactly the end of the buffer,
// we can detect that and still use the fast path.
- (buffer_size_ != 0 && !(buffer_[buffer_size_-1] & 0x80))) {
+ (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
// Fast path: We have enough bytes left in the buffer to guarantee that
// this read won't cross the end, so we can skip the checks.
@@ -442,7 +443,7 @@ bool CodedInputStream::ReadVarint64(uint64* value) {
// We have overrun the maximum size of a varint (10 bytes). The data
// must be corrupt.
- return false;
+ return NULL;
done:
Advance(ptr - buffer_);
@@ -450,33 +451,13 @@ bool CodedInputStream::ReadVarint64(uint64* value) {
(static_cast<uint64>(part1) << 28) |
(static_cast<uint64>(part2) << 56);
return true;
-
} else {
- // Slow path: This read might cross the end of the buffer, so we
- // need to check and refresh the buffer if and when it does.
-
- uint64 result = 0;
- int count = 0;
- uint32 b;
-
- do {
- if (count == kMaxVarintBytes) return false;
- while (buffer_size_ == 0) {
- if (!Refresh()) return false;
- }
- b = *buffer_;
- result |= static_cast<uint64>(b & 0x7F) << (7 * count);
- Advance(1);
- ++count;
- } while(b & 0x80);
-
- *value = result;
- return true;
+ return ReadVarint64Slow(value);
}
}
bool CodedInputStream::Refresh() {
- GOOGLE_DCHECK_EQ(buffer_size_, 0);
+ GOOGLE_DCHECK_EQ(0, BufferSize());
if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 ||
total_bytes_read_ == current_limit_) {
@@ -507,25 +488,27 @@ bool CodedInputStream::Refresh() {
}
const void* void_buffer;
- if (input_->Next(&void_buffer, &buffer_size_)) {
+ int buffer_size;
+ if (input_->Next(&void_buffer, &buffer_size)) {
buffer_ = reinterpret_cast<const uint8*>(void_buffer);
- GOOGLE_CHECK_GE(buffer_size_, 0);
+ buffer_end_ = buffer_ + buffer_size;
+ GOOGLE_CHECK_GE(buffer_size, 0);
- if (total_bytes_read_ <= INT_MAX - buffer_size_) {
- total_bytes_read_ += buffer_size_;
+ if (total_bytes_read_ <= INT_MAX - buffer_size) {
+ total_bytes_read_ += buffer_size;
} else {
- // Overflow. Reset buffer_size_ to not include the bytes beyond INT_MAX.
+ // Overflow. Reset buffer_end_ to not include the bytes beyond INT_MAX.
// We can't get that far anyway, because total_bytes_limit_ is guaranteed
// to be less than it. We need to keep track of the number of bytes
// we discarded, though, so that we can call input_->BackUp() to back
// up over them on destruction.
// The following line is equivalent to:
- // overflow_bytes_ = total_bytes_read_ + buffer_size_ - INT_MAX;
+ // overflow_bytes_ = total_bytes_read_ + buffer_size - INT_MAX;
// except that it avoids overflows. Signed integer overflow has
// undefined results according to the C standard.
- overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size_);
- buffer_size_ -= overflow_bytes_;
+ overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size);
+ buffer_end_ -= overflow_bytes_;
total_bytes_read_ = INT_MAX;
}
@@ -533,7 +516,7 @@ bool CodedInputStream::Refresh() {
return true;
} else {
buffer_ = NULL;
- buffer_size_ = 0;
+ buffer_end_ = NULL;
return false;
}
}
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index fa023f35..dcbb0d45 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -114,10 +114,15 @@
#include <sys/param.h>
#endif // !_MSC_VER
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/common.h> // for GOOGLE_PREDICT_TRUE macro
namespace google {
namespace protobuf {
+
+class DescriptorPool;
+class MessageFactory;
+
namespace io {
// Defined in this file.
@@ -166,6 +171,11 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// types of data not covered by the CodedInputStream interface.
bool GetDirectBufferPointer(const void** data, int* size);
+ // Like GetDirectBufferPointer, but this method is inlined, and does not
+ // attempt to Refresh() if the buffer is currently empty.
+ inline void GetDirectBufferPointerInline(const void** data,
+ int* size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+
// Read raw bytes, copying them into the given buffer.
bool ReadRaw(void* buffer, int size);
@@ -177,6 +187,10 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// could claim that a string is going to be MAX_INT bytes long in order to
// crash the server because it can't allocate this much space at once.
bool ReadString(string* buffer, int size);
+ // Like the above, with inlined optimizations. This should only be used
+ // by the protobuf implementation.
+ inline bool InternalReadStringInline(string* buffer,
+ int size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
// Read a 32-bit little-endian integer.
@@ -184,6 +198,15 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Read a 64-bit little-endian integer.
bool ReadLittleEndian64(uint64* value);
+ // These methods read from an externally provided buffer. The caller is
+ // responsible for ensuring that the buffer has sufficient space.
+ // Read a 32-bit little-endian integer.
+ static const uint8* ReadLittleEndian32FromArray(const uint8* buffer,
+ uint32* value);
+ // Read a 64-bit little-endian integer.
+ static const uint8* ReadLittleEndian64FromArray(const uint8* buffer,
+ uint64* value);
+
// Read an unsigned integer with Varint encoding, truncating to 32 bits.
// Reading a 32-bit value is equivalent to reading a 64-bit one and casting
// it to uint32, but may be more efficient.
@@ -208,6 +231,17 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// when given a constant parameter, but GCC doesn't want to inline by default.
bool ExpectTag(uint32 expected) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ // Like above, except this reads from the specified buffer. The caller is
+ // responsible for ensuring that the buffer is large enough to read a varint
+ // of the expected size. For best performance, use a compile-time constant as
+ // the expected tag parameter.
+ //
+ // Returns a pointer beyond the expected tag if it was found, or NULL if it
+ // was not.
+ static const uint8* ExpectTagFromArray(
+ const uint8* buffer,
+ uint32 expected) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+
// Usually returns true if no more bytes can be read. Always returns false
// if more bytes can be read. If ExpectAtEnd() returns true, a subsequent
// call to LastTagWas() will act as if ReadTag() had been called and returned
@@ -318,12 +352,90 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Decrements the recursion depth.
void DecrementRecursionDepth();
+ // Extension Registry ----------------------------------------------
+ // ADVANCED USAGE: 99.9% of people can ignore this section.
+ //
+ // By default, when parsing extensions, the parser looks for extension
+ // definitions in the pool which owns the outer message's Descriptor.
+ // However, you may call SetExtensionRegistry() to provide an alternative
+ // pool instead. This makes it possible, for example, to parse a message
+ // using a generated class, but represent some extensions using
+ // DynamicMessage.
+
+ // Set the pool used to look up extensions. Most users do not need to call
+ // this as the correct pool will be chosen automatically.
+ //
+ // WARNING: It is very easy to misuse this. Carefully read the requirements
+ // below. Do not use this unless you are sure you need it. Almost no one
+ // does.
+ //
+ // Let's say you are parsing a message into message object m, and you want
+ // to take advantage of SetExtensionRegistry(). You must follow these
+ // requirements:
+ //
+ // The given DescriptorPool must contain m->GetDescriptor(). It is not
+ // sufficient for it to simply contain a descriptor that has the same name
+ // and content -- it must be the *exact object*. In other words:
+ // assert(pool->FindMessageTypeByName(m->GetDescriptor()->full_name()) ==
+ // m->GetDescriptor());
+ // There are two ways to satisfy this requirement:
+ // 1) Use m->GetDescriptor()->pool() as the pool. This is generally useless
+ // because this is the pool that would be used anyway if you didn't call
+ // SetExtensionRegistry() at all.
+ // 2) Use a DescriptorPool which has m->GetDescriptor()->pool() as an
+ // "underlay". Read the documentation for DescriptorPool for more
+ // information about underlays.
+ //
+ // You must also provide a MessageFactory. This factory will be used to
+ // construct Message objects representing extensions. The factory's
+ // GetPrototype() MUST return non-NULL for any Descriptor which can be found
+ // through the provided pool.
+ //
+ // If the provided factory might return instances of protocol-compiler-
+ // generated (i.e. compiled-in) types, or if the outer message object m is
+ // a generated type, then the given factory MUST have this property: If
+ // GetPrototype() is given a Descriptor which resides in
+ // DescriptorPool::generated_pool(), the factory MUST return the same
+ // prototype which MessageFactory::generated_factory() would return. That
+ // is, given a descriptor for a generated type, the factory must return an
+ // instance of the generated class (NOT DynamicMessage). However, when
+ // given a descriptor for a type that is NOT in generated_pool, the factory
+ // is free to return any implementation.
+ //
+ // The reason for this requirement is that generated sub-objects may be
+ // accessed via the standard (non-reflection) extension accessor methods,
+ // and these methods will down-cast the object to the generated class type.
+ // If the object is not actually of that type, the results would be undefined.
+ // On the other hand, if an extension is not compiled in, then there is no
+ // way the code could end up accessing it via the standard accessors -- the
+ // only way to access the extension is via reflection. When using reflection,
+ // DynamicMessage and generated messages are indistinguishable, so it's fine
+ // if these objects are represented using DynamicMessage.
+ //
+ // Using DynamicMessageFactory on which you have called
+ // SetDelegateToGeneratedFactory(true) should be sufficient to satisfy the
+ // above requirement.
+ //
+ // If either pool or factory is NULL, both must be NULL.
+ //
+ // Note that this feature is ignored when parsing "lite" messages as they do
+ // not have descriptors.
+ void SetExtensionRegistry(DescriptorPool* pool, MessageFactory* factory);
+
+ // Get the DescriptorPool set via SetExtensionRegistry(), or NULL if no pool
+ // has been provided.
+ const DescriptorPool* GetExtensionPool();
+
+ // Get the MessageFactory set via SetExtensionRegistry(), or NULL if no
+ // factory has been provided.
+ MessageFactory* GetExtensionFactory();
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedInputStream);
ZeroCopyInputStream* input_;
const uint8* buffer_;
- int buffer_size_; // size of current buffer
+ const uint8* buffer_end_; // pointer to the end of the buffer.
int total_bytes_read_; // total bytes read from input_, including
// the current buffer
@@ -334,7 +446,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// LastTagWas() stuff.
uint32 last_tag_; // result of last ReadTag().
- // This is set true by ReadVarint32Fallback() if it is called when exactly
+ // This is set true by ReadTag{Fallback/Slow}() if it is called when exactly
// at EOF, or by ExpectAtEnd() when it returns true. This happens when we
// reach the end of a message and attempt to read another tag.
bool legitimate_message_end_;
@@ -365,6 +477,12 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Recursion depth limit, set by SetRecursionLimit().
int recursion_limit_;
+ // See SetExtensionRegistry().
+ const DescriptorPool* extension_pool_;
+ MessageFactory* extension_factory_;
+
+ // Private member functions.
+
// Advance the buffer by a given number of bytes.
void Advance(int amount);
@@ -379,10 +497,36 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
void PrintTotalBytesLimitError();
// Called when the buffer runs out to request more data. Implies an
- // Advance(buffer_size_).
+ // Advance(BufferSize()).
bool Refresh();
+ // When parsing varints, we optimize for the common case of small values, and
+ // then optimize for the case when the varint fits within the current buffer
+ // piece. The Fallback method is used when we can't use the one-byte
+ // optimization. The Slow method is yet another fallback when the buffer is
+ // not large enough. Making the slow path out-of-line speeds up the common
+ // case by 10-15%. The slow path is fairly uncommon: it only triggers when a
+ // message crosses multiple buffers.
bool ReadVarint32Fallback(uint32* value);
+ bool ReadVarint64Fallback(uint64* value);
+ bool ReadVarint32Slow(uint32* value);
+ bool ReadVarint64Slow(uint64* value);
+ bool ReadLittleEndian32Fallback(uint32* value);
+ bool ReadLittleEndian64Fallback(uint64* value);
+ // Fallback/slow methods for reading tags. These do not update last_tag_,
+ // but will set legitimate_message_end_ if we are at the end of the input
+ // stream.
+ uint32 ReadTagFallback();
+ uint32 ReadTagSlow();
+ bool ReadStringFallback(string* buffer, int size);
+
+ // Return the size of the buffer.
+ int BufferSize() const;
+
+ static const int kDefaultTotalBytesLimit = 64 << 20; // 64MB
+
+ static const int kDefaultTotalBytesWarningThreshold = 32 << 20; // 32MB
+ static const int kDefaultRecursionLimit = 64;
};
// Class which encodes and writes binary data which is composed of varint-
@@ -568,7 +712,7 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// methods optimize for that case.
inline bool CodedInputStream::ReadVarint32(uint32* value) {
- if (buffer_size_ != 0 && *buffer_ < 0x80) {
+ if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) {
*value = *buffer_;
Advance(1);
return true;
@@ -577,20 +721,93 @@ inline bool CodedInputStream::ReadVarint32(uint32* value) {
}
}
+inline bool CodedInputStream::ReadVarint64(uint64* value) {
+ if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) {
+ *value = *buffer_;
+ Advance(1);
+ return true;
+ } else {
+ return ReadVarint64Fallback(value);
+ }
+}
+
+// static
+inline const uint8* CodedInputStream::ReadLittleEndian32FromArray(
+ const uint8* buffer,
+ uint32* value) {
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
+ defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
+ memcpy(value, buffer, sizeof(*value));
+ return buffer + sizeof(*value);
+#else
+ *value = (static_cast<uint32>(buffer[0]) ) |
+ (static_cast<uint32>(buffer[1]) << 8) |
+ (static_cast<uint32>(buffer[2]) << 16) |
+ (static_cast<uint32>(buffer[3]) << 24);
+ return buffer + sizeof(*value);
+#endif
+}
+// static
+inline const uint8* CodedInputStream::ReadLittleEndian64FromArray(
+ const uint8* buffer,
+ uint64* value) {
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
+ defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
+ memcpy(value, buffer, sizeof(*value));
+ return buffer + sizeof(*value);
+#else
+ uint32 part0 = (static_cast<uint32>(buffer[0]) ) |
+ (static_cast<uint32>(buffer[1]) << 8) |
+ (static_cast<uint32>(buffer[2]) << 16) |
+ (static_cast<uint32>(buffer[3]) << 24);
+ uint32 part1 = (static_cast<uint32>(buffer[4]) ) |
+ (static_cast<uint32>(buffer[5]) << 8) |
+ (static_cast<uint32>(buffer[6]) << 16) |
+ (static_cast<uint32>(buffer[7]) << 24);
+ *value = static_cast<uint64>(part0) |
+ (static_cast<uint64>(part1) << 32);
+ return buffer + sizeof(*value);
+#endif
+}
+
+inline bool CodedInputStream::ReadLittleEndian32(uint32* value) {
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
+ defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
+ if (GOOGLE_PREDICT_TRUE(BufferSize() >= sizeof(*value))) {
+ memcpy(value, buffer_, sizeof(*value));
+ Advance(sizeof(*value));
+ return true;
+ } else {
+ return ReadLittleEndian32Fallback(value);
+ }
+#else
+ return ReadLittleEndian32Fallback(value);
+#endif
+}
+
+inline bool CodedInputStream::ReadLittleEndian64(uint64* value) {
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
+ defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
+ if (GOOGLE_PREDICT_TRUE(BufferSize() >= sizeof(*value))) {
+ memcpy(value, buffer_, sizeof(*value));
+ Advance(sizeof(*value));
+ return true;
+ } else {
+ return ReadLittleEndian64Fallback(value);
+ }
+#else
+ return ReadLittleEndian64Fallback(value);
+#endif
+}
+
inline uint32 CodedInputStream::ReadTag() {
- if (buffer_size_ != 0 && buffer_[0] < 0x80) {
+ if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && buffer_[0] < 0x80) {
last_tag_ = buffer_[0];
Advance(1);
return last_tag_;
- } else if (buffer_size_ >= 2 && buffer_[1] < 0x80) {
- last_tag_ = (buffer_[0] & 0x7f) + (buffer_[1] << 7);
- Advance(2);
- return last_tag_;
- } else if (ReadVarint32Fallback(&last_tag_)) {
- return last_tag_;
} else {
- last_tag_ = 0;
- return 0;
+ last_tag_ = ReadTagFallback();
+ return last_tag_;
}
}
@@ -604,14 +821,14 @@ inline bool CodedInputStream::ConsumedEntireMessage() {
inline bool CodedInputStream::ExpectTag(uint32 expected) {
if (expected < (1 << 7)) {
- if (buffer_size_ != 0 && buffer_[0] == expected) {
+ if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && buffer_[0] == expected) {
Advance(1);
return true;
} else {
return false;
}
} else if (expected < (1 << 14)) {
- if (buffer_size_ >= 2 &&
+ if (GOOGLE_PREDICT_TRUE(BufferSize() >= 2) &&
buffer_[0] == static_cast<uint8>(expected | 0x80) &&
buffer_[1] == static_cast<uint8>(expected >> 7)) {
Advance(2);
@@ -625,11 +842,32 @@ inline bool CodedInputStream::ExpectTag(uint32 expected) {
}
}
+inline const uint8* CodedInputStream::ExpectTagFromArray(
+ const uint8* buffer, uint32 expected) {
+ if (expected < (1 << 7)) {
+ if (buffer[0] == expected) {
+ return buffer + 1;
+ }
+ } else if (expected < (1 << 14)) {
+ if (buffer[0] == static_cast<uint8>(expected | 0x80) &&
+ buffer[1] == static_cast<uint8>(expected >> 7)) {
+ return buffer + 2;
+ }
+ }
+ return NULL;
+}
+
+inline void CodedInputStream::GetDirectBufferPointerInline(const void** data,
+ int* size) {
+ *data = buffer_;
+ *size = buffer_end_ - buffer_;
+}
+
inline bool CodedInputStream::ExpectAtEnd() {
// If we are at a limit we know no more bytes can be read. Otherwise, it's
// hard to say without calling Refresh(), and we'd rather not do that.
- if (buffer_size_ == 0 && buffer_size_after_limit_ != 0) {
+ if (buffer_ == buffer_end_ && buffer_size_after_limit_ != 0) {
last_tag_ = 0; // Pretend we called ReadTag()...
legitimate_message_end_ = true; // ... and it hit EOF.
return true;
@@ -677,11 +915,11 @@ inline uint8* CodedOutputStream::WriteVarint32SignExtendedToArray(
inline uint8* CodedOutputStream::WriteLittleEndian32ToArray(uint32 value,
uint8* target) {
-#if !defined(PROTOBUF_TEST_NOT_LITTLE_ENDIAN) && \
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
memcpy(target, &value, sizeof(value));
#else
- target[0] = static_cast<uint8>(value );
+ target[0] = static_cast<uint8>(value);
target[1] = static_cast<uint8>(value >> 8);
target[2] = static_cast<uint8>(value >> 16);
target[3] = static_cast<uint8>(value >> 24);
@@ -691,18 +929,18 @@ inline uint8* CodedOutputStream::WriteLittleEndian32ToArray(uint32 value,
inline uint8* CodedOutputStream::WriteLittleEndian64ToArray(uint64 value,
uint8* target) {
-#if !defined(PROTOBUF_TEST_NOT_LITTLE_ENDIAN) && \
+#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \
defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
memcpy(target, &value, sizeof(value));
#else
uint32 part0 = static_cast<uint32>(value);
uint32 part1 = static_cast<uint32>(value >> 32);
- target[0] = static_cast<uint8>(part0 );
+ target[0] = static_cast<uint8>(part0);
target[1] = static_cast<uint8>(part0 >> 8);
target[2] = static_cast<uint8>(part0 >> 16);
target[3] = static_cast<uint8>(part0 >> 24);
- target[4] = static_cast<uint8>(part1 );
+ target[4] = static_cast<uint8>(part1);
target[5] = static_cast<uint8>(part1 >> 8);
target[6] = static_cast<uint8>(part1 >> 16);
target[7] = static_cast<uint8>(part1 >> 24);
@@ -759,7 +997,6 @@ inline int CodedOutputStream::ByteCount() const {
inline void CodedInputStream::Advance(int amount) {
buffer_ += amount;
- buffer_size_ -= amount;
}
inline void CodedOutputStream::Advance(int amount) {
@@ -780,6 +1017,72 @@ inline void CodedInputStream::DecrementRecursionDepth() {
if (recursion_depth_ > 0) --recursion_depth_;
}
+inline void CodedInputStream::SetExtensionRegistry(DescriptorPool* pool,
+ MessageFactory* factory) {
+ extension_pool_ = pool;
+ extension_factory_ = factory;
+}
+
+inline const DescriptorPool* CodedInputStream::GetExtensionPool() {
+ return extension_pool_;
+}
+
+inline MessageFactory* CodedInputStream::GetExtensionFactory() {
+ return extension_factory_;
+}
+
+inline int CodedInputStream::BufferSize() const {
+ return buffer_end_ - buffer_;
+}
+
+inline CodedInputStream::CodedInputStream(ZeroCopyInputStream* input)
+ : input_(input),
+ buffer_(NULL),
+ buffer_end_(NULL),
+ total_bytes_read_(0),
+ overflow_bytes_(0),
+ last_tag_(0),
+ legitimate_message_end_(false),
+ aliasing_enabled_(false),
+ current_limit_(INT_MAX),
+ buffer_size_after_limit_(0),
+ total_bytes_limit_(kDefaultTotalBytesLimit),
+ total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
+ recursion_depth_(0),
+ recursion_limit_(kDefaultRecursionLimit),
+ extension_pool_(NULL),
+ extension_factory_(NULL) {
+ // Eagerly Refresh() so buffer space is immediately available.
+ Refresh();
+}
+
+inline CodedInputStream::CodedInputStream(const uint8* buffer, int size)
+ : input_(NULL),
+ buffer_(buffer),
+ buffer_end_(buffer + 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),
+ extension_pool_(NULL),
+ extension_factory_(NULL) {
+ // Note that setting current_limit_ == size is important to prevent some
+ // code paths from trying to access input_ and segfaulting.
+}
+
+inline CodedInputStream::~CodedInputStream() {
+ if (input_ != NULL) {
+ BackUpInputToCurrentPosition();
+ }
+}
+
} // namespace io
} // namespace protobuf
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index e165fb93..7d298332 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -242,6 +242,24 @@ TEST_1D(CodedStreamTest, ExpectTag, kVarintCases) {
}
}
+TEST_1D(CodedStreamTest, ExpectTagFromArray, kVarintCases) {
+ memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size);
+
+ const uint32 expected_value = static_cast<uint32>(kVarintCases_case.value);
+
+ // If the expectation succeeds, it should return a pointer past the tag.
+ if (kVarintCases_case.size <= 2) {
+ EXPECT_TRUE(NULL ==
+ CodedInputStream::ExpectTagFromArray(buffer_,
+ expected_value + 1));
+ EXPECT_TRUE(buffer_ + kVarintCases_case.size ==
+ CodedInputStream::ExpectTagFromArray(buffer_, expected_value));
+ } else {
+ EXPECT_TRUE(NULL ==
+ CodedInputStream::ExpectTagFromArray(buffer_, expected_value));
+ }
+}
+
TEST_2D(CodedStreamTest, ReadVarint64, kVarintCases, kBlockSizes) {
memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size);
ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case);
@@ -529,10 +547,32 @@ TEST_2D(CodedStreamTest, WriteLittleEndian64, kFixed64Cases, kBlockSizes) {
EXPECT_EQ(0, memcmp(buffer_, kFixed64Cases_case.bytes, sizeof(uint64)));
}
+// Tests using the static methods to read fixed-size values from raw arrays.
+
+TEST_1D(CodedStreamTest, ReadLittleEndian32FromArray, kFixed32Cases) {
+ memcpy(buffer_, kFixed32Cases_case.bytes, sizeof(kFixed32Cases_case.bytes));
+
+ uint32 value;
+ const uint8* end = CodedInputStream::ReadLittleEndian32FromArray(
+ buffer_, &value);
+ EXPECT_EQ(kFixed32Cases_case.value, value);
+ EXPECT_TRUE(end == buffer_ + sizeof(value));
+}
+
+TEST_1D(CodedStreamTest, ReadLittleEndian64FromArray, kFixed64Cases) {
+ memcpy(buffer_, kFixed64Cases_case.bytes, sizeof(kFixed64Cases_case.bytes));
+
+ uint64 value;
+ const uint8* end = CodedInputStream::ReadLittleEndian64FromArray(
+ buffer_, &value);
+ EXPECT_EQ(kFixed64Cases_case.value, value);
+ EXPECT_TRUE(end == buffer_ + sizeof(value));
+}
+
// -------------------------------------------------------------------
// Raw reads and writes
-const char kRawBytes[] = "Some bytes which will be writted and read raw.";
+const char kRawBytes[] = "Some bytes which will be written and read raw.";
TEST_1D(CodedStreamTest, ReadRaw, kBlockSizes) {
memcpy(buffer_, kRawBytes, sizeof(kRawBytes));
@@ -593,6 +633,22 @@ TEST_1D(CodedStreamTest, ReadStringImpossiblyLarge, kBlockSizes) {
}
}
+TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnStack) {
+ // Same test as above, except directly use a buffer. This used to cause
+ // crashes while the above did not.
+ uint8 buffer[8];
+ CodedInputStream coded_input(buffer, 8);
+ string str;
+ EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));
+}
+
+TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnHeap) {
+ scoped_array<uint8> buffer(new uint8[8]);
+ CodedInputStream coded_input(buffer.get(), 8);
+ string str;
+ EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));
+}
+
// -------------------------------------------------------------------
// Skip
@@ -652,6 +708,36 @@ TEST_F(CodedStreamTest, GetDirectBufferPointerInput) {
EXPECT_EQ(8, size);
}
+TEST_F(CodedStreamTest, GetDirectBufferPointerInlineInput) {
+ ArrayInputStream input(buffer_, sizeof(buffer_), 8);
+ CodedInputStream coded_input(&input);
+
+ const void* ptr;
+ int size;
+
+ coded_input.GetDirectBufferPointerInline(&ptr, &size);
+ EXPECT_EQ(buffer_, ptr);
+ EXPECT_EQ(8, size);
+
+ // Peeking again should return the same pointer.
+ coded_input.GetDirectBufferPointerInline(&ptr, &size);
+ EXPECT_EQ(buffer_, ptr);
+ EXPECT_EQ(8, size);
+
+ // Skip forward in the same buffer then peek again.
+ EXPECT_TRUE(coded_input.Skip(3));
+ coded_input.GetDirectBufferPointerInline(&ptr, &size);
+ EXPECT_EQ(buffer_ + 3, ptr);
+ EXPECT_EQ(5, size);
+
+ // Skip to end of buffer and peek -- should return false and provide an empty
+ // buffer. It does not try to Refresh().
+ EXPECT_TRUE(coded_input.Skip(5));
+ coded_input.GetDirectBufferPointerInline(&ptr, &size);
+ EXPECT_EQ(buffer_ + 8, ptr);
+ EXPECT_EQ(0, size);
+}
+
TEST_F(CodedStreamTest, GetDirectBufferPointerOutput) {
ArrayOutputStream output(buffer_, sizeof(buffer_), 8);
CodedOutputStream coded_output(&output);
diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc
index 84d277f4..e1a35ea2 100644
--- a/src/google/protobuf/io/gzip_stream.cc
+++ b/src/google/protobuf/io/gzip_stream.cc
@@ -315,6 +315,6 @@ bool GzipOutputStream::Close() {
} // namespace io
} // namespace protobuf
-} // namespace google
#endif // HAVE_ZLIB
+} // namespace google
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index 937d777e..c7d3074d 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -65,10 +65,10 @@ void Printer::Print(const map<string, string>& variables, const char* text) {
if (text[i] == '\n') {
// Saw newline. If there is more text, we may need to insert an indent
// here. So, write what we have so far, including the '\n'.
- Write(text + pos, i - pos + 1);
+ WriteRaw(text + pos, i - pos + 1);
pos = i + 1;
- // Setting this true will cause the next Write() to insert an indent
+ // Setting this true will cause the next WriteRaw() to insert an indent
// first.
at_start_of_line_ = true;
@@ -76,7 +76,7 @@ void Printer::Print(const map<string, string>& variables, const char* text) {
// Saw the start of a variable name.
// Write what we have so far.
- Write(text + pos, i - pos);
+ WriteRaw(text + pos, i - pos);
pos = i + 1;
// Find closing delimiter.
@@ -90,14 +90,14 @@ void Printer::Print(const map<string, string>& variables, const char* text) {
string varname(text + pos, endpos - pos);
if (varname.empty()) {
// Two delimiters in a row reduce to a literal delimiter character.
- Write(&variable_delimiter_, 1);
+ WriteRaw(&variable_delimiter_, 1);
} else {
// Replace with the variable's value.
map<string, string>::const_iterator iter = variables.find(varname);
if (iter == variables.end()) {
GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname;
} else {
- Write(iter->second.data(), iter->second.size());
+ WriteRaw(iter->second.data(), iter->second.size());
}
}
@@ -108,7 +108,7 @@ void Printer::Print(const map<string, string>& variables, const char* text) {
}
// Write the rest.
- Write(text + pos, size - pos);
+ WriteRaw(text + pos, size - pos);
}
void Printer::Print(const char* text) {
@@ -145,14 +145,23 @@ void Printer::Outdent() {
indent_.resize(indent_.size() - 2);
}
-void Printer::Write(const char* data, int size) {
+void Printer::PrintRaw(const string& data) {
+ WriteRaw(data.data(), data.size());
+}
+
+void Printer::PrintRaw(const char* data) {
+ if (failed_) return;
+ WriteRaw(data, strlen(data));
+}
+
+void Printer::WriteRaw(const char* data, int size) {
if (failed_) return;
if (size == 0) return;
if (at_start_of_line_) {
// Insert an indent.
at_start_of_line_ = false;
- Write(indent_.data(), indent_.size());
+ WriteRaw(indent_.data(), indent_.size());
if (failed_) return;
}
diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h
index b7c4cf39..de085389 100644
--- a/src/google/protobuf/io/printer.h
+++ b/src/google/protobuf/io/printer.h
@@ -59,8 +59,8 @@ class ZeroCopyOutputStream; // zero_copy_stream.h
// The above writes "My name is Bob." to the output stream.
//
// Printer aggressively enforces correct usage, crashing (with assert failures)
-// in the case of undefined variables. This helps greatly in debugging code
-// which uses it. This class is not intended to be used by production servers.
+// in the case of undefined variables in debug builds. This helps greatly in
+// debugging code which uses it.
class LIBPROTOBUF_EXPORT Printer {
public:
// Create a printer that writes text to the given output stream. Use the
@@ -94,15 +94,24 @@ class LIBPROTOBUF_EXPORT Printer {
// level is zero.
void Outdent();
+ // Write a string to the output buffer.
+ // This method does not look for newlines to add indentation.
+ void PrintRaw(const string& data);
+
+ // Write a zero-delimited string to output buffer.
+ // This method does not look for newlines to add indentation.
+ void PrintRaw(const char* data);
+
+ // Write some bytes to the output buffer.
+ // This method does not look for newlines to add indentation.
+ void WriteRaw(const char* data, int size);
+
// True if any write to the underlying stream failed. (We don't just
// crash in this case because this is an I/O failure, not a programming
// error.)
bool failed() const { return failed_; }
private:
- // Write some text to the output buffer.
- void Write(const char* data, int size);
-
const char variable_delimiter_;
ZeroCopyOutputStream* const output_;
diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc
index 69c7ee34..580a53da 100644
--- a/src/google/protobuf/io/printer_unittest.cc
+++ b/src/google/protobuf/io/printer_unittest.cc
@@ -76,10 +76,38 @@ TEST(Printer, BasicPrinting) {
buffer[output.ByteCount()] = '\0';
- EXPECT_STREQ(buffer,
- "Hello World! This is the same line.\n"
- "But this is a new one.\n"
- "And this is another one.");
+ EXPECT_STREQ("Hello World! This is the same line.\n"
+ "But this is a new one.\n"
+ "And this is another one.",
+ buffer);
+ }
+}
+
+TEST(Printer, WriteRaw) {
+ char buffer[8192];
+
+ for (int block_size = 1; block_size < 512; block_size *= 2) {
+ ArrayOutputStream output(buffer, sizeof(buffer), block_size);
+
+ {
+ string string_obj = "From an object\n";
+ Printer printer(&output, '$');
+ printer.WriteRaw("Hello World!", 12);
+ printer.PrintRaw(" This is the same line.\n");
+ printer.PrintRaw("But this is a new one.\nAnd this is another one.");
+ printer.WriteRaw("\n", 1);
+ printer.PrintRaw(string_obj);
+ EXPECT_FALSE(printer.failed());
+ }
+
+ buffer[output.ByteCount()] = '\0';
+
+ EXPECT_STREQ("Hello World! This is the same line.\n"
+ "But this is a new one.\n"
+ "And this is another one."
+ "\n"
+ "From an object\n",
+ buffer);
}
}
@@ -98,6 +126,7 @@ TEST(Printer, VariableSubstitution) {
vars["abcdefg"] = "1234";
printer.Print(vars, "Hello $foo$!\nbar = $bar$\n");
+ printer.PrintRaw("RawBit\n");
printer.Print(vars, "$abcdefg$\nA literal dollar sign: $$");
vars["foo"] = "blah";
@@ -108,12 +137,13 @@ TEST(Printer, VariableSubstitution) {
buffer[output.ByteCount()] = '\0';
- EXPECT_STREQ(buffer,
- "Hello World!\n"
- "bar = $foo$\n"
- "1234\n"
- "A literal dollar sign: $\n"
- "Now foo = blah.");
+ EXPECT_STREQ("Hello World!\n"
+ "bar = $foo$\n"
+ "RawBit\n"
+ "1234\n"
+ "A literal dollar sign: $\n"
+ "Now foo = blah.",
+ buffer);
}
}
@@ -125,15 +155,17 @@ TEST(Printer, InlineVariableSubstitution) {
{
Printer printer(&output, '$');
printer.Print("Hello $foo$!\n", "foo", "World");
+ printer.PrintRaw("RawBit\n");
printer.Print("$foo$ $bar$\n", "foo", "one", "bar", "two");
EXPECT_FALSE(printer.failed());
}
buffer[output.ByteCount()] = '\0';
- EXPECT_STREQ(buffer,
- "Hello World!\n"
- "one two\n");
+ EXPECT_STREQ("Hello World!\n"
+ "RawBit\n"
+ "one two\n",
+ buffer);
}
TEST(Printer, Indenting) {
@@ -156,6 +188,8 @@ TEST(Printer, Indenting) {
printer.Indent();
printer.Print(" And this is still the same line.\n"
"But this is indented.\n");
+ printer.PrintRaw("RawBit has indent at start\n");
+ printer.PrintRaw("but not after a raw newline\n");
printer.Print(vars, "Note that a newline in a variable will break "
"indenting, as we see$newline$here.\n");
printer.Indent();
@@ -169,16 +203,19 @@ TEST(Printer, Indenting) {
buffer[output.ByteCount()] = '\0';
- EXPECT_STREQ(buffer,
+ EXPECT_STREQ(
"This is not indented.\n"
" This is indented\n"
" And so is this\n"
"But this is not. And this is still the same line.\n"
" But this is indented.\n"
- " Note that a newline in a variable will break indenting, as we see\n"
+ " RawBit has indent at start\n"
+ "but not after a raw newline\n"
+ "Note that a newline in a variable will break indenting, as we see\n"
"here.\n"
" And this is double-indented\n"
- "Back to normal.");
+ "Back to normal.",
+ buffer);
}
}
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
index 0bda451b..75cbfed5 100644
--- a/src/google/protobuf/io/tokenizer.cc
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -119,7 +119,7 @@ namespace {
CHARACTER_CLASS(Whitespace, c == ' ' || c == '\n' || c == '\t' ||
c == '\r' || c == '\v');
-CHARACTER_CLASS(Unprintable, c < ' ' && c != '\0');
+CHARACTER_CLASS(Unprintable, c < ' ' && c > '\0');
CHARACTER_CLASS(Digit, '0' <= c && c <= '9');
CHARACTER_CLASS(OctalDigit, '0' <= c && c <= '7');
diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h
index 98386e0b..d115161f 100644
--- a/src/google/protobuf/io/tokenizer.h
+++ b/src/google/protobuf/io/tokenizer.h
@@ -63,6 +63,11 @@ class LIBPROTOBUF_EXPORT ErrorCollector {
// 1 to each before printing them.
virtual void AddError(int line, int column, const string& message) = 0;
+ // Indicates that there was a warning in the input at the given line and
+ // column numbers. The numbers are zero-based, so you may want to add
+ // 1 to each before printing them.
+ virtual void AddWarning(int line, int column, const string& message) { }
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector);
};
diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc
index eac1455d..3598e188 100644
--- a/src/google/protobuf/io/tokenizer_unittest.cc
+++ b/src/google/protobuf/io/tokenizer_unittest.cc
@@ -397,6 +397,12 @@ MultiTokenCase kMultiTokenCases[] = {
{ Tokenizer::TYPE_IDENTIFIER, "baz", 1, 0 },
{ Tokenizer::TYPE_END , "" , 1, 3 },
}},
+
+ // Bytes with the high-order bit set should not be seen as control characters.
+ { "\300", {
+ { Tokenizer::TYPE_SYMBOL, "\300", 0, 0 },
+ { Tokenizer::TYPE_END , "" , 0, 1 },
+ }},
};
TEST_2D(TokenizerTest, MultipleTokens, kMultiTokenCases, kBlockSizes) {
diff --git a/src/google/protobuf/io/zero_copy_stream_impl.h b/src/google/protobuf/io/zero_copy_stream_impl.h
index 64e96cd4..9fedb005 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl.h
@@ -133,10 +133,11 @@ class LIBPROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream {
// A ZeroCopyOutputStream which writes to a file descriptor.
//
-// FileInputStream is preferred over using an ofstream with OstreamOutputStream.
-// The latter will introduce an extra layer of buffering, harming performance.
-// Also, it's conceivable that FileInputStream could someday be enhanced
-// to use zero-copy file descriptors on OSs which support them.
+// FileOutputStream is preferred over using an ofstream with
+// OstreamOutputStream. The latter will introduce an extra layer of buffering,
+// harming performance. Also, it's conceivable that FileOutputStream could
+// someday be enhanced to use zero-copy file descriptors on OSs which
+// support them.
class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream {
public:
// Creates a stream that writes to the given Unix file descriptor.
diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
index f919b7ac..8229ee6d 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -403,7 +403,8 @@ TEST_F(IoTest, CompressionOptions) {
string golden;
File::ReadFileToStringOrDie(
- TestSourceDir() + "/google/protobuf/testdata/golden_message", &golden);
+ TestSourceDir() + "/google/protobuf/testdata/golden_message",
+ &golden);
GzipOutputStream::Options options;
string gzip_compressed = Compress(golden, options);
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 4e5b662c..d43507cd 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -212,7 +212,7 @@ class GeneratedMessageFactory : public MessageFactory {
};
GeneratedMessageFactory* generated_message_factory_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(generated_message_factory_once_init_);
+GoogleOnceType generated_message_factory_once_init_;
void ShutdownGeneratedMessageFactory() {
delete generated_message_factory_;
@@ -227,7 +227,7 @@ GeneratedMessageFactory::GeneratedMessageFactory() {}
GeneratedMessageFactory::~GeneratedMessageFactory() {}
GeneratedMessageFactory* GeneratedMessageFactory::singleton() {
- GoogleOnceInit(&generated_message_factory_once_init_,
+ ::google::protobuf::GoogleOnceInit(&generated_message_factory_once_init_,
&InitGeneratedMessageFactory);
return generated_message_factory_;
}
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 54b596d5..c0062f98 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -148,6 +148,7 @@ namespace protobuf {
// Defined in this file.
class Message;
class Reflection;
+class MessageFactory;
// Defined in other files.
class Descriptor; // descriptor.h
@@ -238,13 +239,15 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite {
// Reflection object's SpaceUsed() method.
virtual int SpaceUsed() const;
- // Debugging -------------------------------------------------------
+ // Debugging & Testing----------------------------------------------
// Generates a human readable form of this message, useful for debugging
// and other purposes.
string DebugString() const;
// Like DebugString(), but with less whitespace.
string ShortDebugString() const;
+ // Like DebugString(), but do not escape UTF-8 byte sequences.
+ string Utf8DebugString() const;
// Convenience function useful in GDB. Prints DebugString() to stdout.
void PrintDebugString() const;
@@ -327,6 +330,7 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite {
// GetReflection() wrappers.
virtual Metadata GetMetadata() const = 0;
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message);
};
@@ -453,8 +457,10 @@ class LIBPROTOBUF_EXPORT Reflection {
const FieldDescriptor* field) const = 0;
virtual const EnumValueDescriptor* GetEnum(
const Message& message, const FieldDescriptor* field) const = 0;
+ // See MutableMessage() for the meaning of the "factory" parameter.
virtual const Message& GetMessage(const Message& message,
- const FieldDescriptor* field) const = 0;
+ const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const = 0;
// Get a string value without copying, if possible.
//
@@ -499,9 +505,19 @@ class LIBPROTOBUF_EXPORT Reflection {
virtual void SetEnum (Message* message,
const FieldDescriptor* field,
const EnumValueDescriptor* value) const = 0;
- // Get a mutable pointer to a field with a message type.
+ // Get a mutable pointer to a field with a message type. If a MessageFactory
+ // is provided, it will be used to construct instances of the sub-message;
+ // otherwise, the default factory is used. If the field is an extension that
+ // does not live in the same pool as the containing message's descriptor (e.g.
+ // it lives in an overlay pool), then a MessageFactory must be provided.
+ // If you have no idea what that meant, then you probably don't need to worry
+ // about it (don't provide a MessageFactory). WARNING: If the
+ // FieldDescriptor is for a compiled-in extension, then
+ // factory->GetPrototype(field->message_type() MUST return an instance of the
+ // compiled-in class for this type, NOT DynamicMessage.
virtual Message* MutableMessage(Message* message,
- const FieldDescriptor* field) const = 0;
+ const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const = 0;
// Repeated field getters ------------------------------------------
@@ -603,8 +619,10 @@ class LIBPROTOBUF_EXPORT Reflection {
virtual void AddEnum (Message* message,
const FieldDescriptor* field,
const EnumValueDescriptor* value) const = 0;
+ // See MutableMessage() for comments on the "factory" parameter.
virtual Message* AddMessage(Message* message,
- const FieldDescriptor* field) const = 0;
+ const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const = 0;
// Extensions ------------------------------------------------------
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index a53740ad..7c8f37dc 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -33,9 +33,8 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-
#include <google/protobuf/message_lite.h>
-
+#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
@@ -52,6 +51,24 @@ string MessageLite::InitializationErrorString() const {
namespace {
+// When serializing, we first compute the byte size, then serialize the message.
+// If serialization produces a different number of bytes than expected, we
+// call this function, which crashes. The problem could be due to a bug in the
+// protobuf implementation but is more likely caused by concurrent modification
+// of the message. This function attempts to distinguish between the two and
+// provide a useful error message.
+void ByteSizeConsistencyError(int byte_size_before_serialization,
+ int byte_size_after_serialization,
+ int bytes_produced_by_serialization) {
+ GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization)
+ << "Protocol message was modified concurrently during serialization.";
+ GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization)
+ << "Byte size calculation and serialization were inconsistent. This "
+ "may indicate a bug in protocol buffers or it may be caused by "
+ "concurrent modification of the message.";
+ GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal.";
+}
+
string InitializationErrorMessage(const char* action,
const MessageLite& message) {
// Note: We want to avoid depending on strutil in the lite library, otherwise
@@ -215,9 +232,29 @@ bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const {
bool MessageLite::SerializePartialToCodedStream(
io::CodedOutputStream* output) const {
- ByteSize(); // Force size to be cached.
- SerializeWithCachedSizes(output);
- return !output->HadError();
+ const int size = ByteSize(); // Force size to be cached.
+ uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size);
+ if (buffer != NULL) {
+ uint8* end = SerializeWithCachedSizesToArray(buffer);
+ if (end - buffer != size) {
+ ByteSizeConsistencyError(size, ByteSize(), end - buffer);
+ }
+ return true;
+ } else {
+ int original_byte_count = output->ByteCount();
+ SerializeWithCachedSizes(output);
+ if (output->HadError()) {
+ return false;
+ }
+ int final_byte_count = output->ByteCount();
+
+ if (final_byte_count - original_byte_count != size) {
+ ByteSizeConsistencyError(size, ByteSize(),
+ final_byte_count - original_byte_count);
+ }
+
+ return true;
+ }
}
bool MessageLite::SerializeToZeroCopyStream(
@@ -243,7 +280,9 @@ bool MessageLite::AppendPartialToString(string* output) const {
STLStringResizeUninitialized(output, old_size + byte_size);
uint8* start = reinterpret_cast<uint8*>(string_as_array(output) + old_size);
uint8* end = SerializeWithCachedSizesToArray(start);
- GOOGLE_CHECK_EQ(end - start, byte_size);
+ if (end - start != byte_size) {
+ ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
+ }
return true;
}
@@ -265,9 +304,11 @@ bool MessageLite::SerializeToArray(void* data, int size) const {
bool MessageLite::SerializePartialToArray(void* data, int size) const {
int byte_size = ByteSize();
if (size < byte_size) return false;
- uint8* end =
- SerializeWithCachedSizesToArray(reinterpret_cast<uint8*>(data));
- GOOGLE_CHECK_EQ(end, reinterpret_cast<uint8*>(data) + byte_size);
+ uint8* start = reinterpret_cast<uint8*>(data);
+ uint8* end = SerializeWithCachedSizesToArray(start);
+ if (end - start != byte_size) {
+ ByteSizeConsistencyError(byte_size, ByteSize(), end - start);
+ }
return true;
}
diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc
index 3230c04c..f7beb110 100644
--- a/src/google/protobuf/repeated_field.cc
+++ b/src/google/protobuf/repeated_field.cc
@@ -39,6 +39,18 @@ namespace google {
namespace protobuf {
namespace internal {
+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;
+ }
+}
+
void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) {
void** swap_elements = elements_;
int swap_current_size = current_size_;
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 1696e2a3..5954db55 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -51,8 +51,8 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message_lite.h>
-
namespace google {
+
namespace protobuf {
class Message;
@@ -76,10 +76,11 @@ class RepeatedField {
int size() const;
- Element Get(int index) const;
+ const Element& Get(int index) const;
Element* Mutable(int index);
- void Set(int index, Element value);
- void Add(Element value);
+ void Set(int index, const Element& value);
+ void Add(const Element& value);
+ Element* Add();
// Remove the last element in the array.
// We don't provide a way to remove any element other than the last
// because it invites inefficient use, such as O(n^2) filtering loops
@@ -94,6 +95,13 @@ class RepeatedField {
// array is grown, it will always be at least doubled in size.
void Reserve(int new_size);
+ // Resize the RepeatedField to a new, smaller size. This is O(1).
+ void Truncate(int new_size);
+
+ void AddAlreadyReserved(const Element& value);
+ Element* AddAlreadyReserved();
+ int Capacity() const;
+
// Gets the underlying array. This pointer is possibly invalidated by
// any add or remove operation.
Element* mutable_data();
@@ -128,10 +136,19 @@ class RepeatedField {
int total_size_;
Element initial_space_[kInitialSize];
+
+ // Move the contents of |from| into |to|, possibly clobbering |from| in the
+ // process. For primitive types this is just a memcpy(), but it could be
+ // specialized for non-primitive types to, say, swap each element instead.
+ void MoveArray(Element to[], Element from[], int size);
+
+ // Copy the elements of |from| into |to|.
+ void CopyArray(Element to[], const Element from[], int size);
};
namespace internal {
template <typename It> class RepeatedPtrIterator;
+template <typename It> class RepeatedPtrOverPtrsIterator;
} // namespace internal
namespace internal {
@@ -189,8 +206,11 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
void Reserve(int new_size);
+ int Capacity() const;
+
// Used for constructing iterators.
void* const* raw_data() const;
+ void** raw_mutable_data() const;
template <typename TypeHandler>
typename TypeHandler::Type** mutable_data();
@@ -204,6 +224,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
int SpaceUsedExcludingSelf() const;
+
// Advanced memory management --------------------------------------
// Like Add(), but if there are no cleared objects to use, returns NULL.
@@ -215,7 +236,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
typename TypeHandler::Type* ReleaseLast();
- int ClearedCount();
+ int ClearedCount() const;
template <typename TypeHandler>
void AddCleared(typename TypeHandler::Type* value);
template <typename TypeHandler>
@@ -279,13 +300,14 @@ class LIBPROTOBUF_EXPORT StringTypeHandlerBase {
static void Merge(const string& from, string* to) { *to = from; }
};
-class StringTypeHandler : public StringTypeHandlerBase {
+class LIBPROTOBUF_EXPORT StringTypeHandler : public StringTypeHandlerBase {
public:
static int SpaceUsed(const string& value) {
return sizeof(value) + StringSpaceUsedExcludingSelf(value);
}
};
+
} // namespace internal
// RepeatedPtrField is like RepeatedField, but used for repeated strings or
@@ -311,6 +333,8 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
// array is grown, it will always be at least doubled in size.
void Reserve(int new_size);
+ int Capacity() const;
+
// Gets the underlying array. This pointer is possibly invalidated by
// any add or remove operation.
Element** mutable_data();
@@ -331,6 +355,12 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
iterator end();
const_iterator end() const;
+ // Custom STL-like iterator that iterates over and returns the underlying
+ // pointers to Element rather than Element itself.
+ typedef internal::RepeatedPtrOverPtrsIterator<Element> pointer_iterator;
+ pointer_iterator pointer_begin();
+ pointer_iterator pointer_end();
+
// Returns (an estimate of) the number of bytes used by the repeated field,
// excluding sizeof(*this).
int SpaceUsedExcludingSelf() const;
@@ -363,7 +393,7 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
// Get the number of cleared objects that are currently being kept
// around for reuse.
- int ClearedCount();
+ int ClearedCount() const;
// Add an element to the pool of cleared objects, passing ownership to
// the RepeatedPtrField. The element must be cleared prior to calling
// this method.
@@ -373,16 +403,16 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
// Requires: ClearedCount() > 0
Element* ReleaseCleared();
- private:
+ protected:
+ // Note: RepeatedPtrField SHOULD NOT be subclassed by users. We only
+ // subclass it in one place as a hack for compatibility with proto1. The
+ // subclass needs to know about TypeHandler in order to call protected
+ // methods on RepeatedPtrFieldBase.
class TypeHandler;
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrField);
- // prototype_ is used for RepeatedPtrField<Message> and
- // RepeatedPtrField<MessageLite> 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_;
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrField);
};
// implementation ====================================================
@@ -406,9 +436,25 @@ inline int RepeatedField<Element>::size() const {
return current_size_;
}
+template <typename Element>
+inline int RepeatedField<Element>::Capacity() const {
+ return total_size_;
+}
+
+template<typename Element>
+inline void RepeatedField<Element>::AddAlreadyReserved(const Element& value) {
+ GOOGLE_DCHECK_LT(size(), Capacity());
+ elements_[current_size_++] = value;
+}
+
+template<typename Element>
+inline Element* RepeatedField<Element>::AddAlreadyReserved() {
+ GOOGLE_DCHECK_LT(size(), Capacity());
+ return &elements_[current_size_++];
+}
template <typename Element>
-inline Element RepeatedField<Element>::Get(int index) const {
+inline const Element& RepeatedField<Element>::Get(int index) const {
GOOGLE_DCHECK_LT(index, size());
return elements_[index];
}
@@ -420,18 +466,24 @@ inline Element* RepeatedField<Element>::Mutable(int index) {
}
template <typename Element>
-inline void RepeatedField<Element>::Set(int index, Element value) {
+inline void RepeatedField<Element>::Set(int index, const Element& value) {
GOOGLE_DCHECK_LT(index, size());
elements_[index] = value;
}
template <typename Element>
-inline void RepeatedField<Element>::Add(Element value) {
+inline void RepeatedField<Element>::Add(const Element& value) {
if (current_size_ == total_size_) Reserve(total_size_ + 1);
elements_[current_size_++] = value;
}
template <typename Element>
+inline Element* RepeatedField<Element>::Add() {
+ if (current_size_ == total_size_) Reserve(total_size_ + 1);
+ return &elements_[current_size_++];
+}
+
+template <typename Element>
inline void RepeatedField<Element>::RemoveLast() {
GOOGLE_DCHECK_GT(current_size_, 0);
--current_size_;
@@ -443,10 +495,9 @@ inline void RepeatedField<Element>::Clear() {
}
template <typename Element>
-void RepeatedField<Element>::MergeFrom(const RepeatedField& other) {
+inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) {
Reserve(current_size_ + other.current_size_);
- memcpy(elements_ + current_size_, other.elements_,
- sizeof(Element) * other.current_size_);
+ CopyArray(elements_ + current_size_, other.elements_, other.current_size_);
current_size_ += other.current_size_;
}
@@ -469,17 +520,17 @@ void RepeatedField<Element>::Swap(RepeatedField* other) {
// 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_));
+ MoveArray(swap_initial_space, initial_space_, kInitialSize);
elements_ = other->elements_;
current_size_ = other->current_size_;
total_size_ = other->total_size_;
- memcpy(initial_space_, other->initial_space_, sizeof(initial_space_));
+ MoveArray(initial_space_, other->initial_space_, kInitialSize);
other->elements_ = swap_elements;
other->current_size_ = swap_current_size;
other->total_size_ = swap_total_size;
- memcpy(other->initial_space_, swap_initial_space, sizeof(swap_initial_space));
+ MoveArray(other->initial_space_, swap_initial_space, kInitialSize);
if (elements_ == other->initial_space_) {
elements_ = initial_space_;
@@ -520,19 +571,40 @@ inline int RepeatedField<Element>::SpaceUsedExcludingSelf() const {
return (elements_ != initial_space_) ? total_size_ * sizeof(elements_[0]) : 0;
}
+// Avoid inlining of Reserve(): new, memcpy, and delete[] lead to a significant
+// amount of code bloat.
template <typename Element>
-inline void RepeatedField<Element>::Reserve(int new_size) {
+void RepeatedField<Element>::Reserve(int new_size) {
if (total_size_ >= new_size) return;
Element* old_elements = elements_;
total_size_ = max(total_size_ * 2, new_size);
elements_ = new Element[total_size_];
- memcpy(elements_, old_elements, current_size_ * sizeof(elements_[0]));
+ MoveArray(elements_, old_elements, current_size_);
if (old_elements != initial_space_) {
delete [] old_elements;
}
}
+template <typename Element>
+inline void RepeatedField<Element>::Truncate(int new_size) {
+ GOOGLE_DCHECK_LE(new_size, current_size_);
+ current_size_ = new_size;
+}
+
+template <typename Element>
+inline void RepeatedField<Element>::MoveArray(
+ Element to[], Element from[], int size) {
+ memcpy(to, from, size * sizeof(Element));
+}
+
+template <typename Element>
+inline void RepeatedField<Element>::CopyArray(
+ Element to[], const Element from[], int size) {
+ memcpy(to, from, size * sizeof(Element));
+}
+
+
// -------------------------------------------------------------------
namespace internal {
@@ -600,17 +672,25 @@ void RepeatedPtrFieldBase::Clear() {
}
template <typename TypeHandler>
-void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) {
+inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) {
Reserve(current_size_ + other.current_size_);
for (int i = 0; i < other.current_size_; i++) {
TypeHandler::Merge(other.Get<TypeHandler>(i), Add<TypeHandler>());
}
}
+inline int RepeatedPtrFieldBase::Capacity() const {
+ return total_size_;
+}
+
inline void* const* RepeatedPtrFieldBase::raw_data() const {
return elements_;
}
+inline void** RepeatedPtrFieldBase::raw_mutable_data() const {
+ return elements_;
+}
+
template <typename TypeHandler>
inline typename TypeHandler::Type** RepeatedPtrFieldBase::mutable_data() {
// TODO(kenton): Breaks C++ aliasing rules. We should probably remove this
@@ -650,15 +730,29 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::AddFromCleared() {
}
template <typename TypeHandler>
-inline void RepeatedPtrFieldBase::AddAllocated(
+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.
- if (current_size_ < allocated_size_) {
+ // Make room for the new pointer.
+ if (current_size_ == total_size_) {
+ // The array is completely full with no cleared objects, so grow it.
+ Reserve(total_size_ + 1);
+ ++allocated_size_;
+ } else if (allocated_size_ == total_size_) {
+ // There is no more space in the pointer array because it contains some
+ // cleared objects awaiting reuse. We don't want to grow the array in this
+ // case because otherwise a loop calling AddAllocated() followed by Clear()
+ // would leak memory.
+ TypeHandler::Delete(cast<TypeHandler>(elements_[current_size_]));
+ } else if (current_size_ < allocated_size_) {
+ // We have some cleared objects. We don't care about their order, so we
+ // can just move the first one to the end to make space.
elements_[allocated_size_] = elements_[current_size_];
+ ++allocated_size_;
+ } else {
+ // There are no cleared objects.
+ ++allocated_size_;
}
- ++allocated_size_;
+
elements_[current_size_++] = value;
}
@@ -677,7 +771,7 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseLast() {
}
-inline int RepeatedPtrFieldBase::ClearedCount() {
+inline int RepeatedPtrFieldBase::ClearedCount() const {
return allocated_size_ - current_size_;
}
@@ -694,18 +788,6 @@ inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseCleared() {
return cast<TypeHandler>(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
// -------------------------------------------------------------------
@@ -720,9 +802,7 @@ class RepeatedPtrField<string>::TypeHandler
template <typename Element>
-inline RepeatedPtrField<Element>::RepeatedPtrField()
- : prototype_(NULL) {
-}
+inline RepeatedPtrField<Element>::RepeatedPtrField() {}
template <typename Element>
RepeatedPtrField<Element>::~RepeatedPtrField() {
@@ -802,7 +882,7 @@ inline Element* RepeatedPtrField<Element>::ReleaseLast() {
template <typename Element>
-inline int RepeatedPtrField<Element>::ClearedCount() {
+inline int RepeatedPtrField<Element>::ClearedCount() const {
return RepeatedPtrFieldBase::ClearedCount();
}
@@ -821,6 +901,11 @@ inline void RepeatedPtrField<Element>::Reserve(int new_size) {
return RepeatedPtrFieldBase::Reserve(new_size);
}
+template <typename Element>
+inline int RepeatedPtrField<Element>::Capacity() const {
+ return RepeatedPtrFieldBase::Capacity();
+}
+
// -------------------------------------------------------------------
namespace internal {
@@ -921,6 +1006,84 @@ class RepeatedPtrIterator
void* const* it_;
};
+// Provide an iterator that operates on pointers to the underlying objects
+// rather than the objects themselves as RepeatedPtrIterator does.
+// Consider using this when working with stl algorithms that change
+// the array.
+template<typename Element>
+class RepeatedPtrOverPtrsIterator
+ : public std::iterator<std::random_access_iterator_tag, Element*> {
+ public:
+ typedef RepeatedPtrOverPtrsIterator<Element> iterator;
+ typedef std::iterator<
+ 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.
+ typedef typename superclass::reference reference;
+ typedef typename superclass::pointer pointer;
+ typedef typename superclass::difference_type difference_type;
+
+ RepeatedPtrOverPtrsIterator() : it_(NULL) {}
+ explicit RepeatedPtrOverPtrsIterator(void** it) : it_(it) {}
+
+ // dereferenceable
+ reference operator*() const { return *reinterpret_cast<Element**>(it_); }
+ pointer operator->() const { return &(operator*()); }
+
+ // {inc,dec}rementable
+ iterator& operator++() { ++it_; return *this; }
+ iterator operator++(int) { return iterator(it_++); }
+ iterator& operator--() { --it_; return *this; }
+ iterator operator--(int) { return iterator(it_--); }
+
+ // equality_comparable
+ bool operator==(const iterator& x) const { return it_ == x.it_; }
+ bool operator!=(const iterator& x) const { return it_ != x.it_; }
+
+ // less_than_comparable
+ bool operator<(const iterator& x) const { return it_ < x.it_; }
+ bool operator<=(const iterator& x) const { return it_ <= x.it_; }
+ bool operator>(const iterator& x) const { return it_ > x.it_; }
+ bool operator>=(const iterator& x) const { return it_ >= x.it_; }
+
+ // addable, subtractable
+ iterator& operator+=(difference_type d) {
+ it_ += d;
+ return *this;
+ }
+ friend iterator operator+(iterator it, difference_type d) {
+ it += d;
+ return it;
+ }
+ friend iterator operator+(difference_type d, iterator it) {
+ it += d;
+ return it;
+ }
+ iterator& operator-=(difference_type d) {
+ it_ -= d;
+ return *this;
+ }
+ friend iterator operator-(iterator it, difference_type d) {
+ it -= d;
+ return it;
+ }
+
+ // indexable
+ reference operator[](difference_type d) const { return *(*this + d); }
+
+ // random access iterator
+ difference_type operator-(const iterator& x) const { return it_ - x.it_; }
+
+ private:
+ template<typename OtherElement>
+ friend class RepeatedPtrIterator;
+
+ // The internal iterator.
+ void** it_;
+};
+
+
} // namespace internal
template <typename Element>
@@ -944,6 +1107,18 @@ RepeatedPtrField<Element>::end() const {
return iterator(raw_data() + size());
}
+template <typename Element>
+inline typename RepeatedPtrField<Element>::pointer_iterator
+RepeatedPtrField<Element>::pointer_begin() {
+ return pointer_iterator(raw_mutable_data());
+}
+template <typename Element>
+inline typename RepeatedPtrField<Element>::pointer_iterator
+RepeatedPtrField<Element>::pointer_end() {
+ return pointer_iterator(raw_mutable_data() + size());
+}
+
+
// Iterators and helper functions that follow the spirit of the STL
// std::back_insert_iterator and std::back_inserter but are tailor-made
// for RepeatedField and RepatedPtrField. Typical usage would be:
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index 2d87ba88..798b05ee 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -37,6 +37,7 @@
#include <algorithm>
#include <list>
+#include <vector>
#include <google/protobuf/repeated_field.h>
@@ -241,6 +242,29 @@ TEST(RepeatedField, MutableDataIsMutable) {
EXPECT_EQ(2, field.Get(0));
}
+TEST(RepeatedField, Truncate) {
+ RepeatedField<int> field;
+
+ field.Add(12);
+ field.Add(34);
+ field.Add(56);
+ field.Add(78);
+ EXPECT_EQ(4, field.size());
+
+ field.Truncate(3);
+ EXPECT_EQ(3, field.size());
+
+ field.Add(90);
+ EXPECT_EQ(4, field.size());
+ EXPECT_EQ(90, field.Get(3));
+
+ // Truncations that don't change the size are allowed, but growing is not
+ // allowed.
+ field.Truncate(field.size());
+ EXPECT_DEBUG_DEATH(field.Truncate(field.size() + 1), "new_size");
+}
+
+
// ===================================================================
// RepeatedPtrField tests. These pretty much just mirror the RepeatedField
// tests above.
@@ -443,6 +467,52 @@ TEST(RepeatedPtrField, ClearedElements) {
EXPECT_EQ(field.ClearedCount(), 0);
}
+// Test all code paths in AddAllocated().
+TEST(RepeatedPtrField, AddAlocated) {
+ RepeatedPtrField<string> field;
+ while (field.size() < field.Capacity()) {
+ field.Add()->assign("filler");
+ }
+
+ int index = field.size();
+
+ // First branch: Field is at capacity with no cleared objects.
+ string* foo = new string("foo");
+ field.AddAllocated(foo);
+ EXPECT_EQ(index + 1, field.size());
+ EXPECT_EQ(0, field.ClearedCount());
+ EXPECT_EQ(foo, &field.Get(index));
+
+ // Last branch: Field is not at capacity and there are no cleared objects.
+ string* bar = new string("bar");
+ field.AddAllocated(bar);
+ ++index;
+ EXPECT_EQ(index + 1, field.size());
+ EXPECT_EQ(0, field.ClearedCount());
+ EXPECT_EQ(bar, &field.Get(index));
+
+ // Third branch: Field is not at capacity and there are no cleared objects.
+ field.RemoveLast();
+ string* baz = new string("baz");
+ field.AddAllocated(baz);
+ EXPECT_EQ(index + 1, field.size());
+ EXPECT_EQ(1, field.ClearedCount());
+ EXPECT_EQ(baz, &field.Get(index));
+
+ // Second branch: Field is at capacity but has some cleared objects.
+ while (field.size() < field.Capacity()) {
+ field.Add()->assign("filler2");
+ }
+ field.RemoveLast();
+ index = field.size();
+ string* qux = new string("qux");
+ field.AddAllocated(qux);
+ EXPECT_EQ(index + 1, field.size());
+ // We should have discarded the cleared object.
+ EXPECT_EQ(0, field.ClearedCount());
+ EXPECT_EQ(qux, &field.Get(index));
+}
+
TEST(RepeatedPtrField, MergeFrom) {
RepeatedPtrField<string> source, destination;
@@ -614,6 +684,7 @@ TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) {
string v = "f";
RepeatedPtrField<string>::const_iterator it =
lower_bound(proto_array_.begin(), proto_array_.end(), v);
+
EXPECT_EQ(*it, "n");
EXPECT_TRUE(it == proto_array_.begin() + 3);
}
@@ -624,6 +695,149 @@ TEST_F(RepeatedPtrFieldIteratorTest, Mutation) {
EXPECT_EQ("qux", proto_array_.Get(0));
}
+// -------------------------------------------------------------------
+
+class RepeatedPtrFieldPtrsIteratorTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ proto_array_.Add()->assign("foo");
+ proto_array_.Add()->assign("bar");
+ proto_array_.Add()->assign("baz");
+ }
+
+ RepeatedPtrField<string> proto_array_;
+};
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) {
+ RepeatedPtrField<string>::pointer_iterator iter =
+ proto_array_.pointer_begin();
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) {
+ RepeatedPtrField<string>::pointer_iterator iter =
+ proto_array_.pointer_begin();
+ EXPECT_EQ("foo", **iter);
+ ++iter;
+ EXPECT_EQ("bar", **(iter++));
+ EXPECT_EQ("baz", **iter);
+ ++iter;
+ EXPECT_TRUE(proto_array_.pointer_end() == iter);
+ EXPECT_EQ("baz", **(--proto_array_.pointer_end()));
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) {
+ RepeatedPtrField<string>::pointer_iterator iter =
+ proto_array_.pointer_begin();
+ RepeatedPtrField<string>::pointer_iterator iter2 = iter;
+ ++iter2;
+ ++iter2;
+ EXPECT_TRUE(iter + 2 == iter2);
+ EXPECT_TRUE(iter == iter2 - 2);
+ EXPECT_EQ("baz", *iter[2]);
+ EXPECT_EQ("baz", **(iter + 2));
+ EXPECT_EQ(3, proto_array_.end() - proto_array_.begin());
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) {
+ RepeatedPtrField<string>::pointer_iterator iter =
+ proto_array_.pointer_begin();
+ RepeatedPtrField<string>::pointer_iterator iter2 = iter + 1;
+ EXPECT_TRUE(iter == iter);
+ EXPECT_TRUE(iter != iter2);
+ EXPECT_TRUE(iter < iter2);
+ EXPECT_TRUE(iter <= iter2);
+ EXPECT_TRUE(iter <= iter);
+ EXPECT_TRUE(iter2 > iter);
+ EXPECT_TRUE(iter2 >= iter);
+ EXPECT_TRUE(iter >= iter);
+}
+
+// Uninitialized iterator does not point to any of the RepeatedPtrOverPtrs.
+// Dereferencing an uninitialized iterator crashes the process.
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) {
+ RepeatedPtrField<string>::pointer_iterator iter;
+ EXPECT_TRUE(iter != proto_array_.pointer_begin());
+ EXPECT_TRUE(iter != proto_array_.pointer_begin() + 1);
+ EXPECT_TRUE(iter != proto_array_.pointer_begin() + 2);
+ EXPECT_TRUE(iter != proto_array_.pointer_begin() + 3);
+ EXPECT_TRUE(iter != proto_array_.pointer_end());
+}
+
+
+// This comparison functor is required by the tests for RepeatedPtrOverPtrs.
+// They operate on strings and need to compare strings as strings in
+// any stl algorithm, even though the iterator returns a pointer to a string
+// - i.e. *iter has type string*.
+struct StringLessThan {
+ bool operator()(const string* z, const string& y) {
+ return *z < y;
+ }
+ bool operator()(const string* z, const string* y) {
+ return *z < *y;
+ }
+};
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) {
+ proto_array_.Clear();
+ proto_array_.Add()->assign("a");
+ proto_array_.Add()->assign("c");
+ proto_array_.Add()->assign("d");
+ proto_array_.Add()->assign("n");
+ proto_array_.Add()->assign("p");
+ proto_array_.Add()->assign("x");
+ proto_array_.Add()->assign("y");
+
+ RepeatedPtrField<string>::pointer_iterator iter =
+ proto_array_.pointer_begin();
+ string v = "f";
+ RepeatedPtrField<string>::pointer_iterator it =
+ lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(),
+ v, StringLessThan());
+
+ GOOGLE_CHECK(*it != NULL);
+
+ EXPECT_EQ(**it, "n");
+ EXPECT_TRUE(it == proto_array_.pointer_begin() + 3);
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrMutation) {
+ RepeatedPtrField<string>::pointer_iterator iter =
+ proto_array_.pointer_begin();
+ **iter = "qux";
+ EXPECT_EQ("qux", proto_array_.Get(0));
+
+ EXPECT_EQ("bar", proto_array_.Get(1));
+ EXPECT_EQ("baz", proto_array_.Get(2));
+ ++iter;
+ delete *iter;
+ *iter = new string("a");
+ ++iter;
+ delete *iter;
+ *iter = new string("b");
+ EXPECT_EQ("a", proto_array_.Get(1));
+ EXPECT_EQ("b", proto_array_.Get(2));
+}
+
+TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) {
+ proto_array_.Add()->assign("c");
+ proto_array_.Add()->assign("d");
+ proto_array_.Add()->assign("n");
+ proto_array_.Add()->assign("p");
+ proto_array_.Add()->assign("a");
+ proto_array_.Add()->assign("y");
+ proto_array_.Add()->assign("x");
+ EXPECT_EQ("foo", proto_array_.Get(0));
+ EXPECT_EQ("n", proto_array_.Get(5));
+ EXPECT_EQ("x", proto_array_.Get(9));
+ sort(proto_array_.pointer_begin(),
+ proto_array_.pointer_end(),
+ StringLessThan());
+ EXPECT_EQ("a", proto_array_.Get(0));
+ EXPECT_EQ("baz", proto_array_.Get(2));
+ EXPECT_EQ("y", proto_array_.Get(9));
+}
+
+
// -----------------------------------------------------------------------------
// Unit-tests for the insert iterators
// google::protobuf::RepeatedFieldBackInserter,
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index 3f002373..848ec3ab 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -171,7 +171,13 @@ static const int64 kint64min = -kint64max - 1;
static const uint32 kuint32max = 0xFFFFFFFFu;
static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
-#undef GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+// -------------------------------------------------------------------
+// Annotations: Some parts of the code have been annotated in ways that might
+// be useful to some compilers or tools, but are not supported universally.
+// You can #define these annotations yourself if the default implementation
+// is not right for you.
+
+#ifndef GOOGLE_ATTRIBUTE_ALWAYS_INLINE
#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
// For functions we want to force inline.
// Introduced in gcc 3.1.
@@ -180,14 +186,35 @@ static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
// Other compilers will have to figure it out for themselves.
#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE
#endif
+#endif
-#undef GOOGLE_ATTRIBUTE_DEPRECATED
+#ifndef 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
+#endif
+
+#ifndef GOOGLE_PREDICT_TRUE
+#ifdef __GNUC__
+// Provided at least since GCC 3.0.
+#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
+#else
+#define GOOGLE_PREDICT_TRUE
+#endif
+#endif
+
+// Delimits a block of code which may write to memory which is simultaneously
+// written by other threads, but which has been determined to be thread-safe
+// (e.g. because it is an idempotent write).
+#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN
+#define GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN()
+#endif
+#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_END
+#define GOOGLE_SAFE_CONCURRENT_WRITES_END()
+#endif
// ===================================================================
// from google3/base/basictypes.h
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
index 76d9d21e..bb658ba8 100644
--- a/src/google/protobuf/stubs/strutil.cc
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -425,8 +425,8 @@ string UnescapeCEscapeString(const string& src) {
//
// Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped.
// ----------------------------------------------------------------------
-static int CEscapeInternal(const char* src, int src_len, char* dest,
- int dest_len, bool use_hex) {
+int CEscapeInternal(const char* src, int src_len, char* dest,
+ int dest_len, bool use_hex, bool utf8_safe) {
const char* src_end = src + src_len;
int used = 0;
bool last_hex_escape = false; // true if last output char was \xNN
@@ -447,7 +447,9 @@ static int CEscapeInternal(const char* src, int src_len, char* dest,
// Note that if we emit \xNN and the src character after that is a hex
// digit then that digit must be escaped too to prevent it being
// interpreted as part of the character code by C.
- if (!isprint(*src) || (last_hex_escape && isxdigit(*src))) {
+ if ((!utf8_safe || static_cast<uint8>(*src) < 0x80) &&
+ (!isprint(*src) ||
+ (last_hex_escape && isxdigit(*src)))) {
if (dest_len - used < 4) // need space for 4 letter escape
return -1;
sprintf(dest + used, (use_hex ? "\\x%02x" : "\\%03o"),
@@ -469,7 +471,7 @@ static int CEscapeInternal(const char* src, int src_len, char* dest,
}
int CEscapeString(const char* src, int src_len, char* dest, int dest_len) {
- return CEscapeInternal(src, src_len, dest, dest_len, false);
+ return CEscapeInternal(src, src_len, dest, dest_len, false, false);
}
// ----------------------------------------------------------------------
@@ -486,11 +488,33 @@ string CEscape(const string& src) {
const int dest_length = src.size() * 4 + 1; // Maximum possible expansion
scoped_array<char> dest(new char[dest_length]);
const int len = CEscapeInternal(src.data(), src.size(),
- dest.get(), dest_length, false);
+ dest.get(), dest_length, false, false);
GOOGLE_DCHECK_GE(len, 0);
return string(dest.get(), len);
}
+namespace strings {
+
+string Utf8SafeCEscape(const string& src) {
+ const int dest_length = src.size() * 4 + 1; // Maximum possible expansion
+ scoped_array<char> dest(new char[dest_length]);
+ const int len = CEscapeInternal(src.data(), src.size(),
+ dest.get(), dest_length, false, true);
+ GOOGLE_DCHECK_GE(len, 0);
+ return string(dest.get(), len);
+}
+
+string CHexEscape(const string& src) {
+ const int dest_length = src.size() * 4 + 1; // Maximum possible expansion
+ scoped_array<char> dest(new char[dest_length]);
+ const int len = CEscapeInternal(src.data(), src.size(),
+ dest.get(), dest_length, true, false);
+ GOOGLE_DCHECK_GE(len, 0);
+ return string(dest.get(), len);
+}
+
+} // namespace strings
+
// ----------------------------------------------------------------------
// strto32_adaptor()
// strtou32_adaptor()
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
index c04c1230..777694b7 100644
--- a/src/google/protobuf/stubs/strutil.h
+++ b/src/google/protobuf/stubs/strutil.h
@@ -265,6 +265,14 @@ LIBPROTOBUF_EXPORT int CEscapeString(const char* src, int src_len,
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT string CEscape(const string& src);
+namespace strings {
+// Like CEscape() but does not escape bytes with the upper bit set.
+LIBPROTOBUF_EXPORT string Utf8SafeCEscape(const string& src);
+
+// Like CEscape() but uses hex (\x) escapes instead of octals.
+LIBPROTOBUF_EXPORT string CHexEscape(const string& src);
+} // namespace strings
+
// ----------------------------------------------------------------------
// strto32()
// strtou32()
diff --git a/src/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc
index 0637c0a5..af8b3909 100644
--- a/src/google/protobuf/test_util.cc
+++ b/src/google/protobuf/test_util.cc
@@ -229,11 +229,11 @@ void TestUtil::ModifyRepeatedFields(unittest::TestAllTypes* message) {
message->GetReflection()->SetRepeatedString(
message,
message->GetDescriptor()->FindFieldByName("repeated_string_piece"),
- 1, "424");
+ 1, "524");
message->GetReflection()->SetRepeatedString(
message,
message->GetDescriptor()->FindFieldByName("repeated_cord"),
- 1, "425");
+ 1, "525");
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
}
@@ -692,6 +692,40 @@ void TestUtil::SetPackedFields(unittest::TestPackedTypes* message) {
message->add_packed_enum (unittest::FOREIGN_BAZ);
}
+void TestUtil::SetUnpackedFields(unittest::TestUnpackedTypes* message) {
+ // The values applied here must match those of SetPackedFields.
+
+ message->add_unpacked_int32 (601);
+ message->add_unpacked_int64 (602);
+ message->add_unpacked_uint32 (603);
+ message->add_unpacked_uint64 (604);
+ message->add_unpacked_sint32 (605);
+ message->add_unpacked_sint64 (606);
+ message->add_unpacked_fixed32 (607);
+ message->add_unpacked_fixed64 (608);
+ message->add_unpacked_sfixed32(609);
+ message->add_unpacked_sfixed64(610);
+ message->add_unpacked_float (611);
+ message->add_unpacked_double (612);
+ message->add_unpacked_bool (true);
+ message->add_unpacked_enum (unittest::FOREIGN_BAR);
+ // add a second one of each field
+ message->add_unpacked_int32 (701);
+ message->add_unpacked_int64 (702);
+ message->add_unpacked_uint32 (703);
+ message->add_unpacked_uint64 (704);
+ message->add_unpacked_sint32 (705);
+ message->add_unpacked_sint64 (706);
+ message->add_unpacked_fixed32 (707);
+ message->add_unpacked_fixed64 (708);
+ message->add_unpacked_sfixed32(709);
+ message->add_unpacked_sfixed64(710);
+ message->add_unpacked_float (711);
+ message->add_unpacked_double (712);
+ message->add_unpacked_bool (false);
+ message->add_unpacked_enum (unittest::FOREIGN_BAZ);
+}
+
// -------------------------------------------------------------------
void TestUtil::ModifyPackedFields(unittest::TestPackedTypes* message) {
@@ -760,6 +794,56 @@ void TestUtil::ExpectPackedFieldsSet(const unittest::TestPackedTypes& message) {
EXPECT_EQ(unittest::FOREIGN_BAZ, message.packed_enum(1));
}
+void TestUtil::ExpectUnpackedFieldsSet(
+ const unittest::TestUnpackedTypes& message) {
+ // The values expected here must match those of ExpectPackedFieldsSet.
+
+ ASSERT_EQ(2, message.unpacked_int32_size ());
+ ASSERT_EQ(2, message.unpacked_int64_size ());
+ ASSERT_EQ(2, message.unpacked_uint32_size ());
+ ASSERT_EQ(2, message.unpacked_uint64_size ());
+ ASSERT_EQ(2, message.unpacked_sint32_size ());
+ ASSERT_EQ(2, message.unpacked_sint64_size ());
+ ASSERT_EQ(2, message.unpacked_fixed32_size ());
+ ASSERT_EQ(2, message.unpacked_fixed64_size ());
+ ASSERT_EQ(2, message.unpacked_sfixed32_size());
+ ASSERT_EQ(2, message.unpacked_sfixed64_size());
+ ASSERT_EQ(2, message.unpacked_float_size ());
+ ASSERT_EQ(2, message.unpacked_double_size ());
+ ASSERT_EQ(2, message.unpacked_bool_size ());
+ ASSERT_EQ(2, message.unpacked_enum_size ());
+
+ EXPECT_EQ(601 , message.unpacked_int32 (0));
+ EXPECT_EQ(602 , message.unpacked_int64 (0));
+ EXPECT_EQ(603 , message.unpacked_uint32 (0));
+ EXPECT_EQ(604 , message.unpacked_uint64 (0));
+ EXPECT_EQ(605 , message.unpacked_sint32 (0));
+ EXPECT_EQ(606 , message.unpacked_sint64 (0));
+ EXPECT_EQ(607 , message.unpacked_fixed32 (0));
+ EXPECT_EQ(608 , message.unpacked_fixed64 (0));
+ EXPECT_EQ(609 , message.unpacked_sfixed32(0));
+ EXPECT_EQ(610 , message.unpacked_sfixed64(0));
+ EXPECT_EQ(611 , message.unpacked_float (0));
+ EXPECT_EQ(612 , message.unpacked_double (0));
+ EXPECT_EQ(true , message.unpacked_bool (0));
+ EXPECT_EQ(unittest::FOREIGN_BAR, message.unpacked_enum(0));
+
+ EXPECT_EQ(701 , message.unpacked_int32 (1));
+ EXPECT_EQ(702 , message.unpacked_int64 (1));
+ EXPECT_EQ(703 , message.unpacked_uint32 (1));
+ EXPECT_EQ(704 , message.unpacked_uint64 (1));
+ EXPECT_EQ(705 , message.unpacked_sint32 (1));
+ EXPECT_EQ(706 , message.unpacked_sint64 (1));
+ EXPECT_EQ(707 , message.unpacked_fixed32 (1));
+ EXPECT_EQ(708 , message.unpacked_fixed64 (1));
+ EXPECT_EQ(709 , message.unpacked_sfixed32(1));
+ EXPECT_EQ(710 , message.unpacked_sfixed64(1));
+ EXPECT_EQ(711 , message.unpacked_float (1));
+ EXPECT_EQ(712 , message.unpacked_double (1));
+ EXPECT_EQ(false, message.unpacked_bool (1));
+ EXPECT_EQ(unittest::FOREIGN_BAZ, message.unpacked_enum(1));
+}
+
// -------------------------------------------------------------------
void TestUtil::ExpectPackedClear(
diff --git a/src/google/protobuf/test_util.h b/src/google/protobuf/test_util.h
index 5a6ec88f..25165f3a 100644
--- a/src/google/protobuf/test_util.h
+++ b/src/google/protobuf/test_util.h
@@ -54,6 +54,7 @@ class TestUtil {
static void SetAllFieldsAndExtensions(unittest::TestFieldOrderings* message);
static void SetPackedFields(unittest::TestPackedTypes* message);
static void SetPackedExtensions(unittest::TestPackedExtensions* message);
+ static void SetUnpackedFields(unittest::TestUnpackedTypes* message);
// Use the repeated versions of the set_*() accessors to modify all the
// repeated fields of the messsage (which should already have been
@@ -72,6 +73,8 @@ class TestUtil {
static void ExpectPackedFieldsSet(const unittest::TestPackedTypes& message);
static void ExpectPackedExtensionsSet(
const unittest::TestPackedExtensions& message);
+ static void ExpectUnpackedFieldsSet(
+ const unittest::TestUnpackedTypes& message);
// Expect that the message is modified as would be expected from
// Modify*Fields().
diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc
index f813e8ee..e224781d 100644
--- a/src/google/protobuf/testing/file.cc
+++ b/src/google/protobuf/testing/file.cc
@@ -84,10 +84,13 @@ void File::ReadFileToStringOrDie(const string& name, string* output) {
void File::WriteStringToFileOrDie(const string& contents, const string& name) {
FILE* file = fopen(name.c_str(), "wb");
- GOOGLE_CHECK(file != NULL);
+ GOOGLE_CHECK(file != NULL)
+ << "fopen(" << name << ", \"wb\"): " << strerror(errno);
GOOGLE_CHECK_EQ(fwrite(contents.data(), 1, contents.size(), file),
- contents.size());
- GOOGLE_CHECK(fclose(file) == 0);
+ contents.size())
+ << "fwrite(" << name << "): " << strerror(errno);
+ GOOGLE_CHECK(fclose(file) == 0)
+ << "fclose(" << name << "): " << strerror(errno);
}
bool File::CreateDir(const string& name, int mode) {
@@ -97,8 +100,10 @@ bool File::CreateDir(const string& name, int mode) {
bool File::RecursivelyCreateDir(const string& path, int mode) {
if (CreateDir(path, mode)) return true;
+ if (Exists(path)) return false;
+
// Try creating the parent.
- string::size_type slashpos = path.find_first_of('/');
+ string::size_type slashpos = path.find_last_of('/');
if (slashpos == string::npos) {
// No parent given.
return false;
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index cf754024..137cbcee 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -54,21 +54,19 @@ namespace protobuf {
string Message::DebugString() const {
string debug_string;
- io::StringOutputStream output_stream(&debug_string);
- TextFormat::Print(*this, &output_stream);
+ TextFormat::PrintToString(*this, &debug_string);
return debug_string;
}
string Message::ShortDebugString() const {
string debug_string;
- io::StringOutputStream output_stream(&debug_string);
TextFormat::Printer printer;
printer.SetSingleLineMode(true);
- printer.Print(*this, &output_stream);
+ printer.PrintToString(*this, &debug_string);
// Single line mode currently might have an extra space at the end.
if (debug_string.size() > 0 &&
debug_string[debug_string.size() - 1] == ' ') {
@@ -78,10 +76,22 @@ string Message::ShortDebugString() const {
return debug_string;
}
+string Message::Utf8DebugString() const {
+ string debug_string;
+
+ TextFormat::Printer printer;
+ printer.SetUseUtf8StringEscaping(true);
+
+ printer.PrintToString(*this, &debug_string);
+
+ return debug_string;
+}
+
void Message::PrintDebugString() const {
printf("%s", DebugString().c_str());
}
+
// ===========================================================================
// Internal class for parsing an ASCII representation of a Protocol Message.
// This class makes use of the Protocol Message compiler's tokenizer found
@@ -170,6 +180,23 @@ class TextFormat::Parser::ParserImpl {
}
}
+ void ReportWarning(int line, int col, const string& message) {
+ if (error_collector_ == NULL) {
+ if (line >= 0) {
+ GOOGLE_LOG(WARNING) << "Warning parsing text-format "
+ << root_message_type_->full_name()
+ << ": " << (line + 1) << ":"
+ << (col + 1) << ": " << message;
+ } else {
+ GOOGLE_LOG(WARNING) << "Warning parsing text-format "
+ << root_message_type_->full_name()
+ << ": " << message;
+ }
+ } else {
+ error_collector_->AddWarning(line, col, message);
+ }
+ }
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserImpl);
@@ -180,6 +207,13 @@ class TextFormat::Parser::ParserImpl {
message);
}
+ // Reports a warning with the given message with information indicating
+ // the position (as derived from the current token).
+ void ReportWarning(const string& message) {
+ ReportWarning(tokenizer_.current().line, tokenizer_.current().column,
+ message);
+ }
+
// Consumes the specified message with the given starting delimeter.
// This method checks to see that the end delimeter at the conclusion of
// the consumption matches the starting delimeter passed in here.
@@ -270,6 +304,11 @@ class TextFormat::Parser::ParserImpl {
DO(ConsumeFieldValue(message, reflection, field));
}
+ if (field->options().deprecated()) {
+ ReportWarning("text format contains deprecated field \""
+ + field_name + "\"");
+ }
+
return true;
}
@@ -583,6 +622,10 @@ class TextFormat::Parser::ParserImpl {
parser_->ReportError(line, column, message);
}
+ virtual void AddWarning(int line, int column, const string& message) {
+ parser_->ReportWarning(line, column, message);
+ }
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserErrorCollector);
TextFormat::Parser::ParserImpl* parser_;
@@ -644,12 +687,16 @@ class TextFormat::Printer::TextGenerator {
// Print text to the output stream.
void Print(const string& str) {
- Print(str.c_str());
+ Print(str.data(), str.size());
}
// Print text to the output stream.
void Print(const char* text) {
- int size = strlen(text);
+ Print(text, strlen(text));
+ }
+
+ // Print text to the output stream.
+ void Print(const char* text, int size) {
int pos = 0; // The number of bytes we've written so far.
for (int i = 0; i < size; i++) {
@@ -799,7 +846,9 @@ bool TextFormat::Parser::ParseFieldValueFromString(
TextFormat::Printer::Printer()
: initial_indent_level_(0),
- single_line_mode_(false) {}
+ single_line_mode_(false),
+ use_short_repeated_primitives_(false),
+ utf8_string_escaping_(false) {}
TextFormat::Printer::~Printer() {}
@@ -876,6 +925,14 @@ void TextFormat::Printer::PrintField(const Message& message,
const Reflection* reflection,
const FieldDescriptor* field,
TextGenerator& generator) {
+ if (use_short_repeated_primitives_ &&
+ field->is_repeated() &&
+ field->cpp_type() != FieldDescriptor::CPPTYPE_STRING &&
+ field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+ PrintShortRepeatedField(message, reflection, field, generator);
+ return;
+ }
+
int count = 0;
if (field->is_repeated()) {
@@ -885,26 +942,7 @@ void TextFormat::Printer::PrintField(const Message& message,
}
for (int j = 0; j < count; ++j) {
- if (field->is_extension()) {
- generator.Print("[");
- // We special-case MessageSet elements for compatibility with proto1.
- if (field->containing_type()->options().message_set_wire_format()
- && field->type() == FieldDescriptor::TYPE_MESSAGE
- && field->is_optional()
- && field->extension_scope() == field->message_type()) {
- generator.Print(field->message_type()->full_name());
- } else {
- generator.Print(field->full_name());
- }
- generator.Print("]");
- } else {
- if (field->type() == FieldDescriptor::TYPE_GROUP) {
- // Groups must be serialized with their original capitalization.
- generator.Print(field->message_type()->name());
- } else {
- generator.Print(field->name());
- }
- }
+ PrintFieldName(message, reflection, field, generator);
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (single_line_mode_) {
@@ -926,16 +964,64 @@ void TextFormat::Printer::PrintField(const Message& message,
PrintFieldValue(message, reflection, field, field_index, generator);
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- if (!single_line_mode_) {
+ if (single_line_mode_) {
+ generator.Print("} ");
+ } else {
generator.Outdent();
+ generator.Print("}\n");
+ }
+ } else {
+ if (single_line_mode_) {
+ generator.Print(" ");
+ } else {
+ generator.Print("\n");
}
- generator.Print("}");
}
+ }
+}
- if (single_line_mode_) {
- generator.Print(" ");
+void TextFormat::Printer::PrintShortRepeatedField(const Message& message,
+ const Reflection* reflection,
+ const FieldDescriptor* field,
+ TextGenerator& generator) {
+ // Print primitive repeated field in short form.
+ PrintFieldName(message, reflection, field, generator);
+
+ int size = reflection->FieldSize(message, field);
+ generator.Print(": [");
+ for (int i = 0; i < size; i++) {
+ if (i > 0) generator.Print(", ");
+ PrintFieldValue(message, reflection, field, i, generator);
+ }
+ if (single_line_mode_) {
+ generator.Print("] ");
+ } else {
+ generator.Print("]\n");
+ }
+}
+
+void TextFormat::Printer::PrintFieldName(const Message& message,
+ const Reflection* reflection,
+ const FieldDescriptor* field,
+ TextGenerator& generator) {
+ if (field->is_extension()) {
+ generator.Print("[");
+ // We special-case MessageSet elements for compatibility with proto1.
+ if (field->containing_type()->options().message_set_wire_format()
+ && field->type() == FieldDescriptor::TYPE_MESSAGE
+ && field->is_optional()
+ && field->extension_scope() == field->message_type()) {
+ generator.Print(field->message_type()->full_name());
+ } else {
+ generator.Print(field->full_name());
+ }
+ generator.Print("]");
+ } else {
+ if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ // Groups must be serialized with their original capitalization.
+ generator.Print(field->message_type()->name());
} else {
- generator.Print("\n");
+ generator.Print(field->name());
}
}
}
@@ -973,7 +1059,11 @@ void TextFormat::Printer::PrintFieldValue(
reflection->GetStringReference(message, field, &scratch);
generator.Print("\"");
- generator.Print(CEscape(value));
+ if (utf8_string_escaping_) {
+ generator.Print(strings::Utf8SafeCEscape(value));
+ } else {
+ generator.Print(CEscape(value));
+ }
generator.Print("\"");
break;
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index 39a039d9..e78e1042 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -117,6 +117,24 @@ class LIBPROTOBUF_EXPORT TextFormat {
single_line_mode_ = single_line_mode;
}
+ // Set true to print repeated primitives in a format like:
+ // field_name: [1, 2, 3, 4]
+ // instead of printing each value on its own line. Short format applies
+ // only to primitive values -- i.e. everything except strings and
+ // sub-messages/groups. Note that at present this format is not recognized
+ // by the parser.
+ void SetUseShortRepeatedPrimitives(bool use_short_repeated_primitives) {
+ use_short_repeated_primitives_ = use_short_repeated_primitives;
+ }
+
+ // Set true to output UTF-8 instead of ASCII. The only difference
+ // is that bytes >= 0x80 in string fields will not be escaped,
+ // because they are assumed to be part of UTF-8 multi-byte
+ // sequences.
+ void SetUseUtf8StringEscaping(bool as_utf8) {
+ utf8_string_escaping_ = as_utf8;
+ }
+
private:
// Forward declaration of an internal class used to print the text
// output to the OutputStream (see text_format.cc for implementation).
@@ -133,6 +151,19 @@ class LIBPROTOBUF_EXPORT TextFormat {
const FieldDescriptor* field,
TextGenerator& generator);
+ // Print a repeated primitive field in short form.
+ void PrintShortRepeatedField(const Message& message,
+ const Reflection* reflection,
+ const FieldDescriptor* field,
+ TextGenerator& generator);
+
+ // Print the name of a field -- i.e. everything that comes before the
+ // ':' for a single name/value pair.
+ void PrintFieldName(const Message& message,
+ const Reflection* reflection,
+ const FieldDescriptor* field,
+ TextGenerator& generator);
+
// Outputs a textual representation of the value of the field supplied on
// the message supplied or the default value if not set.
void PrintFieldValue(const Message& message,
@@ -150,6 +181,10 @@ class LIBPROTOBUF_EXPORT TextFormat {
int initial_indent_level_;
bool single_line_mode_;
+
+ bool use_short_repeated_primitives_;
+
+ bool utf8_string_escaping_;
};
// Parses a text-format protocol message from the given input stream to
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 7c31e80f..ddf8ff7f 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -138,12 +138,53 @@ TEST_F(TextFormatTest, ShortDebugString) {
proto_.ShortDebugString());
}
+TEST_F(TextFormatTest, ShortPrimitiveRepeateds) {
+ proto_.set_optional_int32(123);
+ proto_.add_repeated_int32(456);
+ proto_.add_repeated_int32(789);
+ proto_.add_repeated_string("foo");
+ proto_.add_repeated_string("bar");
+ proto_.add_repeated_nested_message()->set_bb(2);
+ proto_.add_repeated_nested_message()->set_bb(3);
+ proto_.add_repeated_nested_enum(unittest::TestAllTypes::FOO);
+ proto_.add_repeated_nested_enum(unittest::TestAllTypes::BAR);
+
+ TextFormat::Printer printer;
+ printer.SetUseShortRepeatedPrimitives(true);
+ string text;
+ printer.PrintToString(proto_, &text);
+
+ EXPECT_EQ("optional_int32: 123\n"
+ "repeated_int32: [456, 789]\n"
+ "repeated_string: \"foo\"\n"
+ "repeated_string: \"bar\"\n"
+ "repeated_nested_message {\n bb: 2\n}\n"
+ "repeated_nested_message {\n bb: 3\n}\n"
+ "repeated_nested_enum: [FOO, BAR]\n",
+ text);
+
+ // Try in single-line mode.
+ printer.SetSingleLineMode(true);
+ printer.PrintToString(proto_, &text);
+
+ EXPECT_EQ("optional_int32: 123 "
+ "repeated_int32: [456, 789] "
+ "repeated_string: \"foo\" "
+ "repeated_string: \"bar\" "
+ "repeated_nested_message { bb: 2 } "
+ "repeated_nested_message { bb: 3 } "
+ "repeated_nested_enum: [FOO, BAR] ",
+ text);
+}
+
+
TEST_F(TextFormatTest, StringEscape) {
// Set the string value to test.
proto_.set_optional_string(kEscapeTestString);
// Get the DebugString from the proto.
string debug_string = proto_.DebugString();
+ string utf8_debug_string = proto_.Utf8DebugString();
// Hardcode a correct value to test against.
string correct_string = "optional_string: "
@@ -152,12 +193,36 @@ TEST_F(TextFormatTest, StringEscape) {
// Compare.
EXPECT_EQ(correct_string, debug_string);
+ // UTF-8 string is the same as non-UTF-8 because
+ // the protocol buffer contains no UTF-8 text.
+ EXPECT_EQ(correct_string, utf8_debug_string);
string expected_short_debug_string = "optional_string: "
+ kEscapeTestStringEscaped;
EXPECT_EQ(expected_short_debug_string, proto_.ShortDebugString());
}
+TEST_F(TextFormatTest, Utf8DebugString) {
+ // Set the string value to test.
+ proto_.set_optional_string("\350\260\267\346\255\214");
+
+ // Get the DebugString from the proto.
+ string debug_string = proto_.DebugString();
+ string utf8_debug_string = proto_.Utf8DebugString();
+
+ // Hardcode a correct value to test against.
+ string correct_utf8_string = "optional_string: "
+ "\"\350\260\267\346\255\214\""
+ "\n";
+ string correct_string = "optional_string: "
+ "\"\\350\\260\\267\\346\\255\\214\""
+ "\n";
+
+ // Compare.
+ EXPECT_EQ(correct_utf8_string, utf8_debug_string);
+ EXPECT_EQ(correct_string, debug_string);
+}
+
TEST_F(TextFormatTest, PrintUnknownFields) {
// Test printing of unknown fields in a message.
@@ -603,10 +668,15 @@ class TextFormatParserTest : public testing::Test {
void ExpectFailure(const string& input, const string& message, int line,
int col, Message* proto) {
+ ExpectMessage(input, message, line, col, proto, false);
+ }
+
+ void ExpectMessage(const string& input, const string& message, int line,
+ int col, Message* proto, bool expected_result) {
TextFormat::Parser parser;
MockErrorCollector error_collector;
parser.RecordErrorsTo(&error_collector);
- EXPECT_FALSE(parser.ParseFromString(input, proto));
+ EXPECT_EQ(parser.ParseFromString(input, proto), expected_result);
EXPECT_EQ(SimpleItoa(line) + ":" + SimpleItoa(col) + ": " + message + "\n",
error_collector.text_);
}
@@ -625,6 +695,10 @@ class TextFormatParserTest : public testing::Test {
strings::SubstituteAndAppend(&text_, "$0:$1: $2\n",
line + 1, column + 1, message);
}
+
+ void AddWarning(int line, int column, const string& message) {
+ AddError(line, column, "WARNING:" + message);
+ }
};
};
@@ -945,6 +1019,12 @@ TEST_F(TextFormatParserTest, FailsOnTokenizationError) {
errors[0]);
}
+TEST_F(TextFormatParserTest, ParseDeprecatedField) {
+ unittest::TestDeprecatedFields message;
+ ExpectMessage("deprecated_int32: 42",
+ "WARNING:text format contains deprecated field "
+ "\"deprecated_int32\"", 1, 21, &message, true);
+}
class TextFormatMessageSetTest : public testing::Test {
protected:
@@ -991,5 +1071,4 @@ TEST_F(TextFormatMessageSetTest, Deserialize) {
} // namespace text_format_unittest
} // namespace protobuf
-
} // namespace google
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index 03811de8..d51fa1e7 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -155,6 +155,10 @@ message TestAllTypes {
optional string default_cord = 85 [ctype=CORD,default="123"];
}
+message TestDeprecatedFields {
+ optional int32 deprecated_int32 = 1 [deprecated=true];
+}
+
// Define these after TestAllTypes to make sure the compiler can handle
// that.
message ForeignMessage {
@@ -348,6 +352,12 @@ message TestEmptyMessageWithExtensions {
extensions 1 to max;
}
+message TestMultipleExtensionRanges {
+ extensions 42;
+ extensions 4143 to 4243;
+ extensions 65536 to max;
+}
+
// Test that really large tag numbers don't break anything.
message TestReallyLargeTagNumber {
// The largest possible tag number is 2^28 - 1, since the wire format uses
@@ -372,13 +382,14 @@ message TestMutualRecursionB {
}
// Test that groups have disjoint field numbers from their siblings and
-// parents. This is NOT possible in proto1; only proto2. When outputting
-// proto1, the dup fields should be dropped.
-message TestDupFieldNumber {
- optional int32 a = 1;
- optional group Foo = 2 { optional int32 a = 1; }
- optional group Bar = 3 { optional int32 a = 1; }
-}
+// parents. This is NOT possible in proto1; only proto2. When attempting
+// to compile with proto1, this will emit an error; so we only include it
+// in protobuf_unittest_proto.
+message TestDupFieldNumber { // NO_PROTO1
+ optional int32 a = 1; // NO_PROTO1
+ optional group Foo = 2 { optional int32 a = 1; } // NO_PROTO1
+ optional group Bar = 3 { optional int32 a = 1; } // NO_PROTO1
+} // NO_PROTO1
// Needed for a Python test.
@@ -468,6 +479,14 @@ message TestExtremeDefaultValues {
// Using exponents
optional float large_float = 12 [default = 2E8];
optional float small_negative_float = 13 [default = -8e-28];
+
+ // Text for nonfinite floating-point values.
+ optional double inf_double = 14 [default = inf];
+ optional double neg_inf_double = 15 [default = -inf];
+ optional double nan_double = 16 [default = nan];
+ optional float inf_float = 17 [default = inf];
+ optional float neg_inf_float = 18 [default = -inf];
+ optional float nan_float = 19 [default = nan];
}
// Test String and Bytes: string is for valid UTF-8 strings
@@ -498,6 +517,25 @@ message TestPackedTypes {
repeated ForeignEnum packed_enum = 103 [packed = true];
}
+// A message with the same fields as TestPackedTypes, but without packing. Used
+// to test packed <-> unpacked wire compatibility.
+message TestUnpackedTypes {
+ repeated int32 unpacked_int32 = 90 [packed = false];
+ repeated int64 unpacked_int64 = 91 [packed = false];
+ repeated uint32 unpacked_uint32 = 92 [packed = false];
+ repeated uint64 unpacked_uint64 = 93 [packed = false];
+ repeated sint32 unpacked_sint32 = 94 [packed = false];
+ repeated sint64 unpacked_sint64 = 95 [packed = false];
+ repeated fixed32 unpacked_fixed32 = 96 [packed = false];
+ repeated fixed64 unpacked_fixed64 = 97 [packed = false];
+ repeated sfixed32 unpacked_sfixed32 = 98 [packed = false];
+ repeated sfixed64 unpacked_sfixed64 = 99 [packed = false];
+ repeated float unpacked_float = 100 [packed = false];
+ repeated double unpacked_double = 101 [packed = false];
+ repeated bool unpacked_bool = 102 [packed = false];
+ repeated ForeignEnum unpacked_enum = 103 [packed = false];
+}
+
message TestPackedExtensions {
extensions 1 to max;
}
@@ -519,6 +557,47 @@ extend TestPackedExtensions {
repeated ForeignEnum packed_enum_extension = 103 [packed = true];
}
+// Used by ExtensionSetTest/DynamicExtensions. The test actually builds
+// a set of extensions to TestAllExtensions dynamically, based on the fields
+// of this message type.
+message TestDynamicExtensions {
+ enum DynamicEnumType {
+ DYNAMIC_FOO = 2200;
+ DYNAMIC_BAR = 2201;
+ DYNAMIC_BAZ = 2202;
+ }
+ message DynamicMessageType {
+ optional int32 dynamic_field = 2100;
+ }
+
+ optional fixed32 scalar_extension = 2000;
+ optional ForeignEnum enum_extension = 2001;
+ optional DynamicEnumType dynamic_enum_extension = 2002;
+
+ optional ForeignMessage message_extension = 2003;
+ optional DynamicMessageType dynamic_message_extension = 2004;
+
+ repeated string repeated_extension = 2005;
+ repeated sint32 packed_extension = 2006 [packed = true];
+}
+
+message TestRepeatedScalarDifferentTagSizes {
+ // Parsing repeated fixed size values used to fail. This message needs to be
+ // used in order to get a tag of the right size; all of the repeated fields
+ // in TestAllTypes didn't trigger the check.
+ repeated fixed32 repeated_fixed32 = 12;
+ // Check for a varint type, just for good measure.
+ repeated int32 repeated_int32 = 13;
+
+ // These have two-byte tags.
+ repeated fixed64 repeated_fixed64 = 2046;
+ repeated int64 repeated_int64 = 2047;
+
+ // Three byte tags.
+ repeated float repeated_float = 262142;
+ repeated uint64 repeated_uint64 = 262143;
+}
+
// Test that RPC services work.
message FooRequest {}
message FooResponse {}
diff --git a/src/google/protobuf/unittest_enormous_descriptor.proto b/src/google/protobuf/unittest_enormous_descriptor.proto
index 6ad2dab3..bc0b7c16 100644
--- a/src/google/protobuf/unittest_enormous_descriptor.proto
+++ b/src/google/protobuf/unittest_enormous_descriptor.proto
@@ -35,6 +35,7 @@
// A proto file that has an extremely large descriptor. Used to test that
// descriptors over 64k don't break the string literal length limit in Java.
+
package google.protobuf;
option java_package = "com.google.protobuf";
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index 318ffafe..e1f8b838 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -32,6 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/stubs/stl_util-inl.h>
#include <google/protobuf/io/coded_stream.h>
@@ -50,13 +51,12 @@ UnknownFieldSet::~UnknownFieldSet() {
delete fields_;
}
-void UnknownFieldSet::Clear() {
- if (fields_ != NULL) {
- for (int i = 0; i < fields_->size(); i++) {
- (*fields_)[i].Delete();
- }
- fields_->clear();
+void UnknownFieldSet::ClearFallback() {
+ GOOGLE_DCHECK(fields_ != NULL);
+ for (int i = 0; i < fields_->size(); i++) {
+ (*fields_)[i].Delete();
}
+ fields_->clear();
}
void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index d6ca70fc..84c2e2b6 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -66,7 +66,7 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
~UnknownFieldSet();
// Remove all fields.
- void Clear();
+ inline void Clear();
// Is this set empty?
inline bool empty() const;
@@ -119,6 +119,8 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
}
private:
+ void ClearFallback();
+
vector<UnknownField>* fields_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet);
@@ -180,6 +182,12 @@ class LIBPROTOBUF_EXPORT UnknownField {
// ===================================================================
// inline implementations
+inline void UnknownFieldSet::Clear() {
+ if (fields_ != NULL) {
+ ClearFallback();
+ }
+}
+
inline bool UnknownFieldSet::empty() const {
return fields_ == NULL || fields_->empty();
}
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index 5aa67727..831a5794 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -391,7 +391,12 @@ bool WireFormat::ParseAndMergePartial(io::CodedInputStream* input,
// If that failed, check if the field is an extension.
if (field == NULL && descriptor->IsExtensionNumber(field_number)) {
- field = message_reflection->FindKnownExtensionByNumber(field_number);
+ if (input->GetExtensionPool() == NULL) {
+ field = message_reflection->FindKnownExtensionByNumber(field_number);
+ } else {
+ field = input->GetExtensionPool()
+ ->FindExtensionByNumber(descriptor, field_number);
+ }
}
// If that failed, but we're a MessageSet, and this is the tag for a
@@ -419,52 +424,67 @@ bool WireFormat::ParseAndMergeField(
io::CodedInputStream* input) {
const Reflection* message_reflection = message->GetReflection();
- if (field == NULL ||
- 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,
- message_reflection->MutableUnknownFields(message));
+ enum { UNKNOWN, NORMAL_FORMAT, PACKED_FORMAT } value_format;
+
+ if (field == NULL) {
+ value_format = UNKNOWN;
+ } else if (WireFormatLite::GetTagWireType(tag) ==
+ WireTypeForFieldType(field->type())) {
+ value_format = NORMAL_FORMAT;
+ } else if (field->is_packable() &&
+ WireFormatLite::GetTagWireType(tag) ==
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ value_format = PACKED_FORMAT;
+ } else {
+ // 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.
+ value_format = UNKNOWN;
}
- if (field->options().packed()) {
+ if (value_format == UNKNOWN) {
+ return SkipField(input, tag,
+ message_reflection->MutableUnknownFields(message));
+ } else if (value_format == PACKED_FORMAT) {
uint32 length;
if (!input->ReadVarint32(&length)) return false;
io::CodedInputStream::Limit limit = input->PushLimit(length);
switch (field->type()) {
-#define HANDLE_PACKED_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD) \
+#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: { \
while (input->BytesUntilLimit() > 0) { \
CPPTYPE value; \
- if (!WireFormatLite::Read##TYPE_METHOD(input, &value)) return false; \
+ if (!WireFormatLite::ReadPrimitive< \
+ CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)) \
+ return false; \
message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
} \
break; \
}
- HANDLE_PACKED_TYPE( INT32, Int32, int32, Int32)
- HANDLE_PACKED_TYPE( INT64, Int64, int64, Int64)
- HANDLE_PACKED_TYPE(SINT32, SInt32, int32, Int32)
- HANDLE_PACKED_TYPE(SINT64, SInt64, int64, Int64)
- HANDLE_PACKED_TYPE(UINT32, UInt32, uint32, UInt32)
- HANDLE_PACKED_TYPE(UINT64, UInt64, uint64, UInt64)
+ HANDLE_PACKED_TYPE( INT32, int32, Int32)
+ HANDLE_PACKED_TYPE( INT64, int64, Int64)
+ HANDLE_PACKED_TYPE(SINT32, int32, Int32)
+ HANDLE_PACKED_TYPE(SINT64, int64, Int64)
+ HANDLE_PACKED_TYPE(UINT32, uint32, UInt32)
+ HANDLE_PACKED_TYPE(UINT64, uint64, UInt64)
- HANDLE_PACKED_TYPE( FIXED32, Fixed32, uint32, UInt32)
- HANDLE_PACKED_TYPE( FIXED64, Fixed64, uint64, UInt64)
- HANDLE_PACKED_TYPE(SFIXED32, SFixed32, int32, Int32)
- HANDLE_PACKED_TYPE(SFIXED64, SFixed64, int64, Int64)
+ HANDLE_PACKED_TYPE( FIXED32, uint32, UInt32)
+ HANDLE_PACKED_TYPE( FIXED64, uint64, UInt64)
+ HANDLE_PACKED_TYPE(SFIXED32, int32, Int32)
+ HANDLE_PACKED_TYPE(SFIXED64, int64, Int64)
- HANDLE_PACKED_TYPE(FLOAT , Float , float , Float )
- HANDLE_PACKED_TYPE(DOUBLE, Double, double, Double)
+ HANDLE_PACKED_TYPE(FLOAT , float , Float )
+ HANDLE_PACKED_TYPE(DOUBLE, double, Double)
- HANDLE_PACKED_TYPE(BOOL, Bool, bool, Bool)
+ HANDLE_PACKED_TYPE(BOOL, bool, Bool)
#undef HANDLE_PACKED_TYPE
case FieldDescriptor::TYPE_ENUM: {
while (input->BytesUntilLimit() > 0) {
int value;
- if (!WireFormatLite::ReadEnum(input, &value)) return false;
+ if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+ input, &value)) return false;
const EnumValueDescriptor* enum_value =
field->enum_type()->FindValueByNumber(value);
if (enum_value != NULL) {
@@ -487,11 +507,14 @@ bool WireFormat::ParseAndMergeField(
input->PopLimit(limit);
} else {
+ // Non-packed value (value_format == NORMAL_FORMAT)
switch (field->type()) {
-#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE, CPPTYPE_METHOD) \
+#define HANDLE_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: { \
CPPTYPE value; \
- if (!WireFormatLite::Read##TYPE_METHOD(input, &value)) return false; \
+ if (!WireFormatLite::ReadPrimitive< \
+ CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)) \
+ return false; \
if (field->is_repeated()) { \
message_reflection->Add##CPPTYPE_METHOD(message, field, value); \
} else { \
@@ -500,31 +523,28 @@ bool WireFormat::ParseAndMergeField(
break; \
}
- HANDLE_TYPE( INT32, Int32, int32, Int32)
- HANDLE_TYPE( INT64, Int64, int64, Int64)
- HANDLE_TYPE(SINT32, SInt32, int32, Int32)
- HANDLE_TYPE(SINT64, SInt64, int64, Int64)
- HANDLE_TYPE(UINT32, UInt32, uint32, UInt32)
- HANDLE_TYPE(UINT64, UInt64, uint64, UInt64)
-
- HANDLE_TYPE( FIXED32, Fixed32, uint32, UInt32)
- HANDLE_TYPE( FIXED64, Fixed64, uint64, UInt64)
- HANDLE_TYPE(SFIXED32, SFixed32, int32, Int32)
- HANDLE_TYPE(SFIXED64, SFixed64, int64, Int64)
-
- HANDLE_TYPE(FLOAT , Float , float , Float )
- HANDLE_TYPE(DOUBLE, Double, double, Double)
+ HANDLE_TYPE( INT32, int32, Int32)
+ HANDLE_TYPE( INT64, int64, Int64)
+ HANDLE_TYPE(SINT32, int32, Int32)
+ HANDLE_TYPE(SINT64, int64, Int64)
+ HANDLE_TYPE(UINT32, uint32, UInt32)
+ HANDLE_TYPE(UINT64, uint64, UInt64)
- HANDLE_TYPE(BOOL, Bool, bool, Bool)
+ HANDLE_TYPE( FIXED32, uint32, UInt32)
+ HANDLE_TYPE( FIXED64, uint64, UInt64)
+ HANDLE_TYPE(SFIXED32, int32, Int32)
+ HANDLE_TYPE(SFIXED64, int64, Int64)
- HANDLE_TYPE(STRING, String, string, String)
- HANDLE_TYPE(BYTES, Bytes, string, String)
+ HANDLE_TYPE(FLOAT , float , Float )
+ HANDLE_TYPE(DOUBLE, double, Double)
+ HANDLE_TYPE(BOOL, bool, Bool)
#undef HANDLE_TYPE
case FieldDescriptor::TYPE_ENUM: {
int value;
- if (!WireFormatLite::ReadEnum(input, &value)) return false;
+ if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+ input, &value)) return false;
const EnumValueDescriptor* enum_value =
field->enum_type()->FindValueByNumber(value);
if (enum_value != NULL) {
@@ -544,13 +564,38 @@ bool WireFormat::ParseAndMergeField(
break;
}
+ // Handle strings separately so that we can optimize the ctype=CORD case.
+ case FieldDescriptor::TYPE_STRING: {
+ string value;
+ if (!WireFormatLite::ReadString(input, &value)) return false;
+ VerifyUTF8String(value.data(), value.length(), PARSE);
+ if (field->is_repeated()) {
+ message_reflection->AddString(message, field, value);
+ } else {
+ message_reflection->SetString(message, field, value);
+ }
+ break;
+ }
+
+ case FieldDescriptor::TYPE_BYTES: {
+ string value;
+ if (!WireFormatLite::ReadBytes(input, &value)) return false;
+ if (field->is_repeated()) {
+ message_reflection->AddString(message, field, value);
+ } else {
+ message_reflection->SetString(message, field, value);
+ }
+ break;
+ }
case FieldDescriptor::TYPE_GROUP: {
Message* sub_message;
if (field->is_repeated()) {
- sub_message = message_reflection->AddMessage(message, field);
+ sub_message = message_reflection->AddMessage(
+ message, field, input->GetExtensionFactory());
} else {
- sub_message = message_reflection->MutableMessage(message, field);
+ sub_message = message_reflection->MutableMessage(
+ message, field, input->GetExtensionFactory());
}
if (!WireFormatLite::ReadGroup(WireFormatLite::GetTagFieldNumber(tag),
@@ -562,9 +607,11 @@ bool WireFormat::ParseAndMergeField(
case FieldDescriptor::TYPE_MESSAGE: {
Message* sub_message;
if (field->is_repeated()) {
- sub_message = message_reflection->AddMessage(message, field);
+ sub_message = message_reflection->AddMessage(
+ message, field, input->GetExtensionFactory());
} else {
- sub_message = message_reflection->MutableMessage(message, field);
+ sub_message = message_reflection->MutableMessage(
+ message, field, input->GetExtensionFactory());
}
if (!WireFormatLite::ReadMessage(input, sub_message)) return false;
@@ -782,23 +829,23 @@ void WireFormat::SerializeFieldWithCachedSizes(
// Handle strings separately so that we can get string references
// instead of copying.
case FieldDescriptor::TYPE_STRING: {
- string scratch;
- const string& value = field->is_repeated() ?
- message_reflection->GetRepeatedStringReference(
- message, field, j, &scratch) :
- message_reflection->GetStringReference(message, field, &scratch);
- VerifyUTF8String(value.data(), value.length(), SERIALIZE);
- WireFormatLite::WriteString(field->number(), value, output);
+ string scratch;
+ const string& value = field->is_repeated() ?
+ message_reflection->GetRepeatedStringReference(
+ message, field, j, &scratch) :
+ message_reflection->GetStringReference(message, field, &scratch);
+ VerifyUTF8String(value.data(), value.length(), SERIALIZE);
+ WireFormatLite::WriteString(field->number(), value, output);
break;
}
case FieldDescriptor::TYPE_BYTES: {
- string scratch;
- const string& value = field->is_repeated() ?
- message_reflection->GetRepeatedStringReference(
- message, field, j, &scratch) :
- message_reflection->GetStringReference(message, field, &scratch);
- WireFormatLite::WriteBytes(field->number(), value, output);
+ string scratch;
+ const string& value = field->is_repeated() ?
+ message_reflection->GetRepeatedStringReference(
+ message, field, j, &scratch) :
+ message_reflection->GetStringReference(message, field, &scratch);
+ WireFormatLite::WriteBytes(field->number(), value, output);
break;
}
}
@@ -961,14 +1008,14 @@ int WireFormat::FieldDataOnlyByteSize(
// instead of copying.
case FieldDescriptor::TYPE_STRING:
case FieldDescriptor::TYPE_BYTES: {
- for (int j = 0; j < count; j++) {
- string scratch;
- const string& value = field->is_repeated() ?
- message_reflection->GetRepeatedStringReference(
- message, field, j, &scratch) :
- message_reflection->GetStringReference(message, field, &scratch);
- data_size += WireFormatLite::StringSize(value);
- }
+ for (int j = 0; j < count; j++) {
+ string scratch;
+ const string& value = field->is_repeated() ?
+ message_reflection->GetRepeatedStringReference(
+ message, field, j, &scratch) :
+ message_reflection->GetStringReference(message, field, &scratch);
+ data_size += WireFormatLite::StringSize(value);
+ }
break;
}
}
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index 5d09803a..d347d116 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -32,14 +32,13 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <google/protobuf/wire_format_lite_inl.h>
+
#include <stack>
#include <string>
#include <vector>
-
-#include <google/protobuf/wire_format_lite_inl.h>
-
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/coded_stream_inl.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
@@ -187,6 +186,174 @@ void FieldSkipper::SkipUnknownEnum(
// Nothing.
}
+bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input,
+ bool (*is_valid)(int),
+ RepeatedField<int>* values) {
+ uint32 length;
+ if (!input->ReadVarint32(&length)) return false;
+ io::CodedInputStream::Limit limit = input->PushLimit(length);
+ while (input->BytesUntilLimit() > 0) {
+ int value;
+ if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, WireFormatLite::TYPE_ENUM>(input, &value)) {
+ return false;
+ }
+ if (is_valid(value)) {
+ values->Add(value);
+ }
+ }
+ input->PopLimit(limit);
+ return true;
+}
+
+void WireFormatLite::WriteInt32(int field_number, int32 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteInt32NoTag(value, output);
+}
+void WireFormatLite::WriteInt64(int field_number, int64 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteInt64NoTag(value, output);
+}
+void WireFormatLite::WriteUInt32(int field_number, uint32 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteUInt32NoTag(value, output);
+}
+void WireFormatLite::WriteUInt64(int field_number, uint64 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteUInt64NoTag(value, output);
+}
+void WireFormatLite::WriteSInt32(int field_number, int32 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteSInt32NoTag(value, output);
+}
+void WireFormatLite::WriteSInt64(int field_number, int64 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteSInt64NoTag(value, output);
+}
+void WireFormatLite::WriteFixed32(int field_number, uint32 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_FIXED32, output);
+ WriteFixed32NoTag(value, output);
+}
+void WireFormatLite::WriteFixed64(int field_number, uint64 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_FIXED64, output);
+ WriteFixed64NoTag(value, output);
+}
+void WireFormatLite::WriteSFixed32(int field_number, int32 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_FIXED32, output);
+ WriteSFixed32NoTag(value, output);
+}
+void WireFormatLite::WriteSFixed64(int field_number, int64 value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_FIXED64, output);
+ WriteSFixed64NoTag(value, output);
+}
+void WireFormatLite::WriteFloat(int field_number, float value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_FIXED32, output);
+ WriteFloatNoTag(value, output);
+}
+void WireFormatLite::WriteDouble(int field_number, double value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_FIXED64, output);
+ WriteDoubleNoTag(value, output);
+}
+void WireFormatLite::WriteBool(int field_number, bool value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteBoolNoTag(value, output);
+}
+void WireFormatLite::WriteEnum(int field_number, int value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteEnumNoTag(value, output);
+}
+
+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);
+}
+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);
+}
+
+
+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);
+}
+
+void WireFormatLite::WriteMessage(int field_number,
+ const MessageLite& value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+ const int size = value.GetCachedSize();
+ output->WriteVarint32(size);
+ value.SerializeWithCachedSizes(output);
+}
+
+void WireFormatLite::WriteGroupMaybeToArray(int field_number,
+ const MessageLite& value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_START_GROUP, output);
+ const int size = value.GetCachedSize();
+ uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
+ if (target != NULL) {
+ uint8* end = value.SerializeWithCachedSizesToArray(target);
+ GOOGLE_DCHECK_EQ(end - target, size);
+ } else {
+ value.SerializeWithCachedSizes(output);
+ }
+ WriteTag(field_number, WIRETYPE_END_GROUP, output);
+}
+
+void WireFormatLite::WriteMessageMaybeToArray(int field_number,
+ const MessageLite& value,
+ io::CodedOutputStream* output) {
+ WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+ const int size = value.GetCachedSize();
+ output->WriteVarint32(size);
+ uint8* target = output->GetDirectBufferForNBytesAndAdvance(size);
+ if (target != NULL) {
+ uint8* end = value.SerializeWithCachedSizesToArray(target);
+ GOOGLE_DCHECK_EQ(end - target, size);
+ } else {
+ value.SerializeWithCachedSizes(output);
+ }
+}
+
+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->InternalReadStringInline(value, length)) return false;
+ return true;
+}
+bool WireFormatLite::ReadBytes(io::CodedInputStream* input,
+ string* value) {
+ uint32 length;
+ if (!input->ReadVarint32(&length)) return false;
+ return input->InternalReadStringInline(value, length);
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
index 9b7a4010..e3d5b2d8 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -46,15 +46,18 @@
namespace google {
namespace protobuf {
+ template <typename T> class RepeatedField; // repeated_field.h
namespace io {
- class CodedInputStream; // coded_stream.h
- class CodedOutputStream; // coded_stream.h
+ class CodedInputStream; // coded_stream.h
+ class CodedOutputStream; // coded_stream.h
}
}
namespace protobuf {
namespace internal {
+class StringPieceField;
+
// 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.
@@ -183,14 +186,21 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
// required string message = 3;
// }
// }
+ static const int kMessageSetItemNumber = 1;
+ static const int kMessageSetTypeIdNumber = 2;
+ static const int kMessageSetMessageNumber = 3;
static const int kMessageSetItemStartTag =
- GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(1, WireFormatLite::WIRETYPE_START_GROUP);
+ GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetItemNumber,
+ WireFormatLite::WIRETYPE_START_GROUP);
static const int kMessageSetItemEndTag =
- GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(1, WireFormatLite::WIRETYPE_END_GROUP);
+ GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetItemNumber,
+ WireFormatLite::WIRETYPE_END_GROUP);
static const int kMessageSetTypeIdTag =
- GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(2, WireFormatLite::WIRETYPE_VARINT);
+ GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetTypeIdNumber,
+ WireFormatLite::WIRETYPE_VARINT);
static const int kMessageSetMessageTag =
- GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(3, WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetMessageNumber,
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
// Byte size of all tags of a MessageSet::Item combined.
static const int kMessageSetItemTagsSize;
@@ -227,23 +237,59 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
// 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);
+
+ // For primitive fields, we just use a templatized routine parameterized by
+ // the represented type and the FieldType. These are specialized with the
+ // appropriate definition for each declared type.
+ template <typename CType, enum FieldType DeclaredType>
+ static inline bool ReadPrimitive(input, CType* value) INL;
+
+ // Reads repeated primitive values, with optimizations for repeats.
+ // tag_size and tag should both be compile-time constants provided by the
+ // protocol compiler.
+ template <typename CType, enum FieldType DeclaredType>
+ static inline bool ReadRepeatedPrimitive(int tag_size,
+ uint32 tag,
+ input,
+ RepeatedField<CType>* value) INL;
+
+ // Identical to ReadRepeatedPrimitive, except will not inline the
+ // implementation.
+ template <typename CType, enum FieldType DeclaredType>
+ static bool ReadRepeatedPrimitiveNoInline(int tag_size,
+ uint32 tag,
+ input,
+ RepeatedField<CType>* value);
+
+ // Reads a primitive value directly from the provided buffer. It returns a
+ // pointer past the segment of data that was read.
+ //
+ // This is only implemented for the types with fixed wire size, e.g.
+ // float, double, and the (s)fixed* types.
+ template <typename CType, enum FieldType DeclaredType>
+ static inline const uint8* ReadPrimitiveFromArray(const uint8* buffer,
+ CType* value) INL;
+
+ // Reads a primitive packed field.
+ //
+ // This is only implemented for packable types.
+ template <typename CType, enum FieldType DeclaredType>
+ static inline bool ReadPackedPrimitive(input,
+ RepeatedField<CType>* value) INL;
+
+ // Identical to ReadPackedPrimitive, except will not inline the
+ // implementation.
+ template <typename CType, enum FieldType DeclaredType>
+ static bool ReadPackedPrimitiveNoInline(input, RepeatedField<CType>* value);
+
+ // Read a packed enum field. Values for which is_valid() returns false are
+ // dropped.
+ static bool ReadPackedEnumNoInline(input,
+ bool (*is_valid)(int),
+ RepeatedField<int>* value);
+
+ static bool ReadString(input, string* value);
+ static bool ReadBytes (input, string* value);
static inline bool ReadGroup (field_number, input, MessageLite* value);
static inline bool ReadMessage(input, MessageLite* value);
@@ -279,38 +325,44 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
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;
+ static void WriteInt32 (field_number, int32 value, output);
+ static void WriteInt64 (field_number, int64 value, output);
+ static void WriteUInt32 (field_number, uint32 value, output);
+ static void WriteUInt64 (field_number, uint64 value, output);
+ static void WriteSInt32 (field_number, int32 value, output);
+ static void WriteSInt64 (field_number, int64 value, output);
+ static void WriteFixed32 (field_number, uint32 value, output);
+ static void WriteFixed64 (field_number, uint64 value, output);
+ static void WriteSFixed32(field_number, int32 value, output);
+ static void WriteSFixed64(field_number, int64 value, output);
+ static void WriteFloat (field_number, float value, output);
+ static void WriteDouble (field_number, double value, output);
+ static void WriteBool (field_number, bool value, output);
+ static void WriteEnum (field_number, int value, output);
+
+ static void WriteString(field_number, const string& value, output);
+ static void WriteBytes (field_number, const string& value, output);
+
+ static void WriteGroup(
+ field_number, const MessageLite& value, output);
+ static void WriteMessage(
+ field_number, const MessageLite& value, output);
+ // Like above, but these will check if the output stream has enough
+ // space to write directly to a flat array.
+ static void WriteGroupMaybeToArray(
+ field_number, const MessageLite& value, output);
+ static void WriteMessageMaybeToArray(
+ field_number, const MessageLite& value, output);
// 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<typename MessageType>
static inline void WriteGroupNoVirtual(
- field_number, const MessageType& value, output) INL;
+ field_number, const MessageType& value, output);
template<typename MessageType>
static inline void WriteMessageNoVirtual(
- field_number, const MessageType& value, output) INL;
+ field_number, const MessageType& value, output);
#undef output
#define output uint8* target
@@ -426,6 +478,16 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
static inline int MessageSizeNoVirtual(const MessageType& value);
private:
+ // A helper method for the repeated primitive reader. This method has
+ // optimizations for primitive types that have fixed size on the wire, and
+ // can be read using potentially faster paths.
+ template <typename CType, enum FieldType DeclaredType>
+ static inline bool ReadRepeatedFixedSizePrimitive(
+ int tag_size,
+ uint32 tag,
+ google::protobuf::io::CodedInputStream* input,
+ RepeatedField<CType>* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+
static const CppType kFieldTypeToCppTypeMap[];
static const WireFormatLite::WireType kWireTypeForFieldType[];
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index eb9155e9..d7b2c302 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -39,7 +39,9 @@
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message_lite.h>
+#include <google/protobuf/repeated_field.h>
#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/io/coded_stream.h>
@@ -47,106 +49,295 @@ namespace google {
namespace protobuf {
namespace internal {
-inline bool WireFormatLite::ReadInt32(io::CodedInputStream* input,
- int32* value) {
+// Implementation details of ReadPrimitive.
+
+template <>
+inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_INT32>(
+ io::CodedInputStream* input,
+ int32* value) {
uint32 temp;
if (!input->ReadVarint32(&temp)) return false;
*value = static_cast<int32>(temp);
return true;
}
-inline bool WireFormatLite::ReadInt64(io::CodedInputStream* input,
- int64* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_INT64>(
+ io::CodedInputStream* input,
+ int64* value) {
uint64 temp;
if (!input->ReadVarint64(&temp)) return false;
*value = static_cast<int64>(temp);
return true;
}
-inline bool WireFormatLite::ReadUInt32(io::CodedInputStream* input,
- uint32* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_UINT32>(
+ io::CodedInputStream* input,
+ uint32* value) {
return input->ReadVarint32(value);
}
-inline bool WireFormatLite::ReadUInt64(io::CodedInputStream* input,
- uint64* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<uint64, WireFormatLite::TYPE_UINT64>(
+ io::CodedInputStream* input,
+ uint64* value) {
return input->ReadVarint64(value);
}
-inline bool WireFormatLite::ReadSInt32(io::CodedInputStream* input,
- int32* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SINT32>(
+ 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) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_SINT64>(
+ 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) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<uint32, WireFormatLite::TYPE_FIXED32>(
+ io::CodedInputStream* input,
+ uint32* value) {
return input->ReadLittleEndian32(value);
}
-inline bool WireFormatLite::ReadFixed64(io::CodedInputStream* input,
- uint64* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<uint64, WireFormatLite::TYPE_FIXED64>(
+ io::CodedInputStream* input,
+ uint64* value) {
return input->ReadLittleEndian64(value);
}
-inline bool WireFormatLite::ReadSFixed32(io::CodedInputStream* input,
- int32* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<int32, WireFormatLite::TYPE_SFIXED32>(
+ io::CodedInputStream* input,
+ int32* value) {
uint32 temp;
if (!input->ReadLittleEndian32(&temp)) return false;
*value = static_cast<int32>(temp);
return true;
}
-inline bool WireFormatLite::ReadSFixed64(io::CodedInputStream* input,
- int64* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<int64, WireFormatLite::TYPE_SFIXED64>(
+ io::CodedInputStream* input,
+ int64* value) {
uint64 temp;
if (!input->ReadLittleEndian64(&temp)) return false;
*value = static_cast<int64>(temp);
return true;
}
-inline bool WireFormatLite::ReadFloat(io::CodedInputStream* input,
- float* value) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<float, WireFormatLite::TYPE_FLOAT>(
+ 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) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<double, WireFormatLite::TYPE_DOUBLE>(
+ 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) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<bool, WireFormatLite::TYPE_BOOL>(
+ 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) {
+template <>
+inline bool WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+ io::CodedInputStream* input,
+ int* value) {
uint32 temp;
if (!input->ReadVarint32(&temp)) return false;
*value = static_cast<int>(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;
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+ uint32, WireFormatLite::TYPE_FIXED32>(
+ const uint8* buffer,
+ uint32* value) {
+ return io::CodedInputStream::ReadLittleEndian32FromArray(buffer, value);
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+ uint64, WireFormatLite::TYPE_FIXED64>(
+ const uint8* buffer,
+ uint64* value) {
+ return io::CodedInputStream::ReadLittleEndian64FromArray(buffer, value);
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+ int32, WireFormatLite::TYPE_SFIXED32>(
+ const uint8* buffer,
+ int32* value) {
+ uint32 temp;
+ buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp);
+ *value = static_cast<int32>(temp);
+ return buffer;
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+ int64, WireFormatLite::TYPE_SFIXED64>(
+ const uint8* buffer,
+ int64* value) {
+ uint64 temp;
+ buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp);
+ *value = static_cast<int64>(temp);
+ return buffer;
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+ float, WireFormatLite::TYPE_FLOAT>(
+ const uint8* buffer,
+ float* value) {
+ uint32 temp;
+ buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp);
+ *value = DecodeFloat(temp);
+ return buffer;
+}
+template <>
+inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
+ double, WireFormatLite::TYPE_DOUBLE>(
+ const uint8* buffer,
+ double* value) {
+ uint64 temp;
+ buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp);
+ *value = DecodeDouble(temp);
+ return buffer;
+}
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+inline bool WireFormatLite::ReadRepeatedPrimitive(int tag_size,
+ uint32 tag,
+ io::CodedInputStream* input,
+ RepeatedField<CType>* values) {
+ CType value;
+ if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
+ values->Add(value);
+ int elements_already_reserved = values->Capacity() - values->size();
+ while (elements_already_reserved > 0 && input->ExpectTag(tag)) {
+ if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
+ values->AddAlreadyReserved(value);
+ elements_already_reserved--;
+ }
+ return true;
+}
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+inline bool WireFormatLite::ReadRepeatedFixedSizePrimitive(
+ int tag_size,
+ uint32 tag,
+ io::CodedInputStream* input,
+ RepeatedField<CType>* values) {
+ GOOGLE_DCHECK_EQ(UInt32Size(tag), tag_size);
+ CType value;
+ if (!ReadPrimitive<CType, DeclaredType>(input, &value))
+ return false;
+ values->Add(value);
+
+ // For fixed size values, repeated values can be read more quickly by
+ // reading directly from a raw array.
+ //
+ // We can get a tight loop by only reading as many elements as can be
+ // added to the RepeatedField without having to do any resizing. Additionally,
+ // we only try to read as many elements as are available from the current
+ // buffer space. Doing so avoids having to perform boundary checks when
+ // reading the value: the maximum number of elements that can be read is
+ // known outside of the loop.
+ const void* void_pointer;
+ int size;
+ input->GetDirectBufferPointerInline(&void_pointer, &size);
+ if (size > 0) {
+ const uint8* buffer = reinterpret_cast<const uint8*>(void_pointer);
+ // The number of bytes each type occupies on the wire.
+ const int per_value_size = tag_size + sizeof(value);
+
+ int elements_available = min(values->Capacity() - values->size(),
+ size / per_value_size);
+ int num_read = 0;
+ while (num_read < elements_available &&
+ (buffer = io::CodedInputStream::ExpectTagFromArray(
+ buffer, tag)) != NULL) {
+ buffer = ReadPrimitiveFromArray<CType, DeclaredType>(buffer, &value);
+ values->AddAlreadyReserved(value);
+ ++num_read;
+ }
+ const int read_bytes = num_read * per_value_size;
+ if (read_bytes > 0) {
+ input->Skip(read_bytes);
+ }
+ }
return true;
}
-inline bool WireFormatLite::ReadBytes(io::CodedInputStream* input,
- string* value) {
+
+// Specializations of ReadRepeatedPrimitive for the fixed size types, which use
+// the optimized code path.
+#define READ_REPEATED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \
+template <> \
+inline bool WireFormatLite::ReadRepeatedPrimitive< \
+ CPPTYPE, WireFormatLite::DECLARED_TYPE>( \
+ int tag_size, \
+ uint32 tag, \
+ io::CodedInputStream* input, \
+ RepeatedField<CPPTYPE>* values) { \
+ return ReadRepeatedFixedSizePrimitive< \
+ CPPTYPE, WireFormatLite::DECLARED_TYPE>( \
+ tag_size, tag, input, values); \
+}
+
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32);
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64);
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32);
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64);
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT);
+READ_REPEATED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE);
+
+#undef READ_REPEATED_FIXED_SIZE_PRIMITIVE
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+bool WireFormatLite::ReadRepeatedPrimitiveNoInline(
+ int tag_size,
+ uint32 tag,
+ io::CodedInputStream* input,
+ RepeatedField<CType>* value) {
+ return ReadRepeatedPrimitive<CType, DeclaredType>(
+ tag_size, tag, input, value);
+}
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+inline bool WireFormatLite::ReadPackedPrimitive(io::CodedInputStream* input,
+ RepeatedField<CType>* values) {
uint32 length;
if (!input->ReadVarint32(&length)) return false;
- return input->ReadString(value, length);
+ io::CodedInputStream::Limit limit = input->PushLimit(length);
+ while (input->BytesUntilLimit() > 0) {
+ CType value;
+ if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
+ values->Add(value);
+ }
+ input->PopLimit(limit);
+ return true;
+}
+
+template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+bool WireFormatLite::ReadPackedPrimitiveNoInline(io::CodedInputStream* input,
+ RepeatedField<CType>* values) {
+ return ReadPackedPrimitive<CType, DeclaredType>(input, values);
}
@@ -270,107 +461,6 @@ inline void WireFormatLite::WriteEnumNoTag(int value,
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<typename MessageType>
inline void WireFormatLite::WriteGroupNoVirtual(int field_number,
const MessageType& value,
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index 51960ee7..867970c4 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -126,6 +126,38 @@ TEST(WireFormatTest, ParsePacked) {
TestUtil::ExpectPackedFieldsSet(dest);
}
+TEST(WireFormatTest, ParsePackedFromUnpacked) {
+ // Serialize using the generated code.
+ unittest::TestUnpackedTypes source;
+ TestUtil::SetUnpackedFields(&source);
+ string data = source.SerializeAsString();
+
+ // Parse using WireFormat.
+ unittest::TestPackedTypes dest;
+ io::ArrayInputStream raw_input(data.data(), data.size());
+ io::CodedInputStream input(&raw_input);
+ WireFormat::ParseAndMergePartial(&input, &dest);
+
+ // Check.
+ TestUtil::ExpectPackedFieldsSet(dest);
+}
+
+TEST(WireFormatTest, ParseUnpackedFromPacked) {
+ // Serialize using the generated code.
+ unittest::TestPackedTypes source;
+ TestUtil::SetPackedFields(&source);
+ string data = source.SerializeAsString();
+
+ // Parse using WireFormat.
+ unittest::TestUnpackedTypes dest;
+ io::ArrayInputStream raw_input(data.data(), data.size());
+ io::CodedInputStream input(&raw_input);
+ WireFormat::ParseAndMergePartial(&input, &dest);
+
+ // Check.
+ TestUtil::ExpectUnpackedFieldsSet(dest);
+}
+
TEST(WireFormatTest, ParsePackedExtensions) {
unittest::TestPackedExtensions source, dest;
string data;
@@ -568,6 +600,45 @@ TEST(WireFormatTest, ZigZag) {
LL(-75123905439571256))));
}
+TEST(WireFormatTest, RepeatedScalarsDifferentTagSizes) {
+ // At one point checks would trigger when parsing repeated fixed scalar
+ // fields.
+ protobuf_unittest::TestRepeatedScalarDifferentTagSizes msg1, msg2;
+ for (int i = 0; i < 100; ++i) {
+ msg1.add_repeated_fixed32(i);
+ msg1.add_repeated_int32(i);
+ msg1.add_repeated_fixed64(i);
+ msg1.add_repeated_int64(i);
+ msg1.add_repeated_float(i);
+ msg1.add_repeated_uint64(i);
+ }
+
+ // Make sure that we have a variety of tag sizes.
+ const google::protobuf::Descriptor* desc = msg1.GetDescriptor();
+ const google::protobuf::FieldDescriptor* field;
+ field = desc->FindFieldByName("repeated_fixed32");
+ ASSERT_TRUE(field != NULL);
+ ASSERT_EQ(1, WireFormat::TagSize(field->number(), field->type()));
+ field = desc->FindFieldByName("repeated_int32");
+ ASSERT_TRUE(field != NULL);
+ ASSERT_EQ(1, WireFormat::TagSize(field->number(), field->type()));
+ field = desc->FindFieldByName("repeated_fixed64");
+ ASSERT_TRUE(field != NULL);
+ ASSERT_EQ(2, WireFormat::TagSize(field->number(), field->type()));
+ field = desc->FindFieldByName("repeated_int64");
+ ASSERT_TRUE(field != NULL);
+ ASSERT_EQ(2, WireFormat::TagSize(field->number(), field->type()));
+ field = desc->FindFieldByName("repeated_float");
+ ASSERT_TRUE(field != NULL);
+ ASSERT_EQ(3, WireFormat::TagSize(field->number(), field->type()));
+ field = desc->FindFieldByName("repeated_uint64");
+ ASSERT_TRUE(field != NULL);
+ ASSERT_EQ(3, WireFormat::TagSize(field->number(), field->type()));
+
+ EXPECT_TRUE(msg2.ParseFromString(msg1.SerializeAsString()));
+ EXPECT_EQ(msg1.DebugString(), msg2.DebugString());
+}
+
class WireFormatInvalidInputTest : public testing::Test {
protected:
// Make a serialized TestAllTypes in which the field optional_nested_message
diff --git a/vsprojects/libprotobuf-lite.vcproj b/vsprojects/libprotobuf-lite.vcproj
index 7e7b1e66..8c0ec9f3 100644
--- a/vsprojects/libprotobuf-lite.vcproj
+++ b/vsprojects/libprotobuf-lite.vcproj
@@ -1,270 +1,270 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="9.00"
- Name="libprotobuf-lite"
- ProjectGUID="{49EA010D-706F-4BE2-A397-77854B72A040}"
- Keyword="Win32Proj"
- TargetFrameworkVersion="0"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="Debug"
- IntermediateDirectory="Debug"
- ConfigurationType="4"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
- Optimization="0"
- AdditionalIncludeDirectories="../src;."
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPROTOBUF_EXPORTS;"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="Release"
- IntermediateDirectory="Release"
- ConfigurationType="4"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
- AdditionalIncludeDirectories="../src;."
- PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPROTOBUF_EXPORTS;"
- RuntimeLibrary="2"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <File
- RelativePath="..\src\google\protobuf\io\coded_stream.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\common.h"
- >
- </File>
- <File
- RelativePath=".\config.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\extension_set.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\generated_message_util.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\hash.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\map-util.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\message_lite.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\once.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\repeated_field.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\stl_util-inl.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\wire_format_lite.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\wire_format_lite_inl.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.h"
- >
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
- >
- </Filter>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath="..\src\google\protobuf\io\coded_stream.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\common.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\extension_set.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\generated_message_util.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\hash.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\message_lite.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\once.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\repeated_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\wire_format_lite.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.cc"
- >
- </File>
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="libprotobuf-lite"
+ ProjectGUID="{49EA010D-706F-4BE2-A397-77854B72A040}"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="4"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
+ Optimization="0"
+ AdditionalIncludeDirectories="../src;."
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPROTOBUF_EXPORTS;"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="4"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
+ AdditionalIncludeDirectories="../src;."
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPROTOBUF_EXPORTS;"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\src\google\protobuf\io\coded_stream.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\common.h"
+ >
+ </File>
+ <File
+ RelativePath=".\config.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\extension_set.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\generated_message_util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\hash.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\map-util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\message_lite.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\once.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\repeated_field.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\stl_util-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\wire_format_lite.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\wire_format_lite_inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\src\google\protobuf\io\coded_stream.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\common.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\extension_set.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\generated_message_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\hash.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\message_lite.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\once.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\repeated_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\wire_format_lite.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/vsprojects/libprotobuf.vcproj b/vsprojects/libprotobuf.vcproj
index d6258675..0303a6e9 100644
--- a/vsprojects/libprotobuf.vcproj
+++ b/vsprojects/libprotobuf.vcproj
@@ -1,430 +1,430 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="9.00"
- Name="libprotobuf"
- ProjectGUID="{3E283F37-A4ED-41B7-A3E6-A2D89D131A30}"
- Keyword="Win32Proj"
- TargetFrameworkVersion="0"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="Debug"
- IntermediateDirectory="Debug"
- ConfigurationType="4"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
- Optimization="0"
- AdditionalIncludeDirectories="../src;."
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPROTOBUF_EXPORTS;"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="Release"
- IntermediateDirectory="Release"
- ConfigurationType="4"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
- AdditionalIncludeDirectories="../src;."
- PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPROTOBUF_EXPORTS;"
- RuntimeLibrary="2"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <File
- RelativePath="..\src\google\protobuf\io\coded_stream.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\common.h"
- >
- </File>
- <File
- RelativePath=".\config.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\descriptor.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\descriptor.pb.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\descriptor_database.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\dynamic_message.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\extension_set.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\generated_message_reflection.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\generated_message_util.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\gzip_stream.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\hash.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\importer.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\map-util.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\message.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\message_lite.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\once.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\parser.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\printer.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\reflection_ops.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\repeated_field.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\service.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\stl_util-inl.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\strutil.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\substitute.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\text_format.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\tokenizer.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\unknown_field_set.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\wire_format.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\wire_format_lite.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\wire_format_lite_inl.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.h"
- >
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
- >
- </Filter>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath="..\src\google\protobuf\io\coded_stream.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\common.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\descriptor.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\descriptor.pb.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\descriptor_database.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\dynamic_message.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\extension_set.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\extension_set_heavy.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\generated_message_reflection.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\generated_message_util.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\gzip_stream.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\hash.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\importer.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\message.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\message_lite.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\once.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\parser.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\printer.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\reflection_ops.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\repeated_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\service.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\structurally_valid.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\strutil.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\substitute.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\text_format.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\tokenizer.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\unknown_field_set.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\wire_format.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\wire_format_lite.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.cc"
- >
- </File>
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="libprotobuf"
+ ProjectGUID="{3E283F37-A4ED-41B7-A3E6-A2D89D131A30}"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="4"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
+ Optimization="0"
+ AdditionalIncludeDirectories="../src;."
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPROTOBUF_EXPORTS;"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="4"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
+ AdditionalIncludeDirectories="../src;."
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPROTOBUF_EXPORTS;"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\src\google\protobuf\io\coded_stream.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\common.h"
+ >
+ </File>
+ <File
+ RelativePath=".\config.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\descriptor.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\descriptor.pb.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\descriptor_database.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\dynamic_message.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\extension_set.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\generated_message_reflection.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\generated_message_util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\gzip_stream.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\hash.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\importer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\map-util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\message.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\message_lite.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\once.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\parser.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\printer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\reflection_ops.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\repeated_field.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\service.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\stl_util-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\strutil.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\substitute.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\text_format.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\tokenizer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unknown_field_set.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\wire_format.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\wire_format_lite.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\wire_format_lite_inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\src\google\protobuf\io\coded_stream.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\common.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\descriptor.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\descriptor.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\descriptor_database.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\dynamic_message.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\extension_set.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\extension_set_heavy.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\generated_message_reflection.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\generated_message_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\gzip_stream.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\hash.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\importer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\message.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\message_lite.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\once.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\parser.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\printer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\reflection_ops.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\repeated_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\service.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\structurally_valid.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\strutil.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\substitute.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\text_format.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\tokenizer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unknown_field_set.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\wire_format.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\wire_format_lite.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/vsprojects/lite-test.vcproj b/vsprojects/lite-test.vcproj
index 50153cfb..f66556ab 100644
--- a/vsprojects/lite-test.vcproj
+++ b/vsprojects/lite-test.vcproj
@@ -1,273 +1,273 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="9.00"
- Name="lite-test"
- ProjectGUID="{12015ACE-42BE-4952-A5A0-44A9A46908E2}"
- RootNamespace="tests"
- Keyword="Win32Proj"
- TargetFrameworkVersion="0"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="Debug"
- IntermediateDirectory="Debug"
- ConfigurationType="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- Description=""
- CommandLine=""
- AdditionalDependencies=""
- Outputs=""
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
- Optimization="0"
- AdditionalIncludeDirectories="../src;.;../gtest/include"
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- LinkIncremental="2"
- GenerateDebugInformation="true"
- SubSystem="1"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="Release"
- IntermediateDirectory="Release"
- ConfigurationType="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- Description=""
- CommandLine=""
- AdditionalDependencies=""
- Outputs=""
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
- AdditionalIncludeDirectories="../src;.;../gtest/include"
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;"
- RuntimeLibrary="2"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- LinkIncremental="2"
- GenerateDebugInformation="true"
- SubSystem="1"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <File
- RelativePath="..\src\google\protobuf\test_util_lite.h"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_lite.pb.h"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_import_lite.pb.h"
- >
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
- >
- </Filter>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath="..\src\google\protobuf\lite_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\test_util_lite.cc"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_lite.pb.cc"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_import_lite.pb.cc"
- >
- </File>
- </Filter>
- <File
- RelativePath="..\src\google\protobuf\unittest_lite.proto"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_lite.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_lite.pb.h;google\protobuf\unittest_lite.pb.cc"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_lite.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_lite.pb.h;google\protobuf\unittest_lite.pb.cc"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\src\google\protobuf\unittest_import_lite.proto"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_import_lite.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_lite.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_import_lite.pb.h;google\protobuf\unittest_import_lite.pb.cc"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_import_lite.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_lite.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_import_lite.pb.h;google\protobuf\unittest_import_lite.pb.cc"
- />
- </FileConfiguration>
- </File>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="lite-test"
+ ProjectGUID="{12015ACE-42BE-4952-A5A0-44A9A46908E2}"
+ RootNamespace="tests"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ Description=""
+ CommandLine=""
+ AdditionalDependencies=""
+ Outputs=""
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
+ Optimization="0"
+ AdditionalIncludeDirectories="../src;.;../gtest/include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ Description=""
+ CommandLine=""
+ AdditionalDependencies=""
+ Outputs=""
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
+ AdditionalIncludeDirectories="../src;.;../gtest/include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\src\google\protobuf\test_util_lite.h"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_lite.pb.h"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_import_lite.pb.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\src\google\protobuf\lite_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\test_util_lite.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_lite.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_import_lite.pb.cc"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\src\google\protobuf\unittest_lite.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_lite.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_lite.pb.h;google\protobuf\unittest_lite.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_lite.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_lite.pb.h;google\protobuf\unittest_lite.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unittest_import_lite.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_import_lite.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_lite.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_import_lite.pb.h;google\protobuf\unittest_import_lite.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_import_lite.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_lite.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_import_lite.pb.h;google\protobuf\unittest_import_lite.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/vsprojects/protobuf.sln b/vsprojects/protobuf.sln
index 9f2e8b61..6925a861 100644
--- a/vsprojects/protobuf.sln
+++ b/vsprojects/protobuf.sln
@@ -1,80 +1,80 @@
-
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotobuf", "libprotobuf.vcproj", "{3E283F37-A4ED-41B7-A3E6-A2D89D131A30}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotoc", "libprotoc.vcproj", "{B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}"
- ProjectSection(ProjectDependencies) = postProject
- {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "protoc", "protoc.vcproj", "{1738D5F6-ED1E-47E0-B2F0-456864B93C1E}"
- ProjectSection(ProjectDependencies) = postProject
- {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} = {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}
- {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "tests.vcproj", "{4DF72760-C055-40A5-A77E-30A17E2AC2DB}"
- ProjectSection(ProjectDependencies) = postProject
- {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} = {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}
- {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}
- {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} = {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}
- {3AF54C8A-10BF-4332-9147-F68ED9862032} = {3AF54C8A-10BF-4332-9147-F68ED9862032}
- {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} = {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "..\gtest\msvc\gtest.vcproj", "{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_main", "..\gtest\msvc\gtest_main.vcproj", "{3AF54C8A-10BF-4332-9147-F68ED9862032}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotobuf-lite", "libprotobuf-lite.vcproj", "{49EA010D-706F-4BE2-A397-77854B72A040}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lite-test", "lite-test.vcproj", "{12015ACE-42BE-4952-A5A0-44A9A46908E2}"
- ProjectSection(ProjectDependencies) = postProject
- {49EA010D-706F-4BE2-A397-77854B72A040} = {49EA010D-706F-4BE2-A397-77854B72A040}
- {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} = {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}
- EndProjectSection
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Win32 = Debug|Win32
- Release|Win32 = Release|Win32
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Debug|Win32.ActiveCfg = Debug|Win32
- {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Debug|Win32.Build.0 = Debug|Win32
- {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Release|Win32.ActiveCfg = Release|Win32
- {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Release|Win32.Build.0 = Release|Win32
- {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Debug|Win32.ActiveCfg = Debug|Win32
- {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Debug|Win32.Build.0 = Debug|Win32
- {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Release|Win32.ActiveCfg = Release|Win32
- {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Release|Win32.Build.0 = Release|Win32
- {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Debug|Win32.ActiveCfg = Debug|Win32
- {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Debug|Win32.Build.0 = Debug|Win32
- {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Release|Win32.ActiveCfg = Release|Win32
- {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Release|Win32.Build.0 = Release|Win32
- {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Debug|Win32.ActiveCfg = Debug|Win32
- {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Debug|Win32.Build.0 = Debug|Win32
- {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Release|Win32.ActiveCfg = Release|Win32
- {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Release|Win32.Build.0 = Release|Win32
- {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug|Win32.ActiveCfg = Debug|Win32
- {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug|Win32.Build.0 = Debug|Win32
- {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release|Win32.ActiveCfg = Release|Win32
- {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release|Win32.Build.0 = Release|Win32
- {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug|Win32.ActiveCfg = Debug|Win32
- {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug|Win32.Build.0 = Debug|Win32
- {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release|Win32.ActiveCfg = Release|Win32
- {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release|Win32.Build.0 = Release|Win32
- {49EA010D-706F-4BE2-A397-77854B72A040}.Debug|Win32.ActiveCfg = Debug|Win32
- {49EA010D-706F-4BE2-A397-77854B72A040}.Debug|Win32.Build.0 = Debug|Win32
- {49EA010D-706F-4BE2-A397-77854B72A040}.Release|Win32.ActiveCfg = Release|Win32
- {49EA010D-706F-4BE2-A397-77854B72A040}.Release|Win32.Build.0 = Release|Win32
- {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Debug|Win32.ActiveCfg = Debug|Win32
- {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Debug|Win32.Build.0 = Debug|Win32
- {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Release|Win32.ActiveCfg = Release|Win32
- {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Release|Win32.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotobuf", "libprotobuf.vcproj", "{3E283F37-A4ED-41B7-A3E6-A2D89D131A30}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotoc", "libprotoc.vcproj", "{B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}"
+ ProjectSection(ProjectDependencies) = postProject
+ {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "protoc", "protoc.vcproj", "{1738D5F6-ED1E-47E0-B2F0-456864B93C1E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} = {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}
+ {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "tests.vcproj", "{4DF72760-C055-40A5-A77E-30A17E2AC2DB}"
+ ProjectSection(ProjectDependencies) = postProject
+ {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE} = {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}
+ {3E283F37-A4ED-41B7-A3E6-A2D89D131A30} = {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}
+ {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7} = {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}
+ {3AF54C8A-10BF-4332-9147-F68ED9862032} = {3AF54C8A-10BF-4332-9147-F68ED9862032}
+ {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} = {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest", "..\gtest\msvc\gtest.vcproj", "{C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gtest_main", "..\gtest\msvc\gtest_main.vcproj", "{3AF54C8A-10BF-4332-9147-F68ED9862032}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libprotobuf-lite", "libprotobuf-lite.vcproj", "{49EA010D-706F-4BE2-A397-77854B72A040}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lite-test", "lite-test.vcproj", "{12015ACE-42BE-4952-A5A0-44A9A46908E2}"
+ ProjectSection(ProjectDependencies) = postProject
+ {49EA010D-706F-4BE2-A397-77854B72A040} = {49EA010D-706F-4BE2-A397-77854B72A040}
+ {1738D5F6-ED1E-47E0-B2F0-456864B93C1E} = {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Debug|Win32.ActiveCfg = Debug|Win32
+ {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Debug|Win32.Build.0 = Debug|Win32
+ {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Release|Win32.ActiveCfg = Release|Win32
+ {3E283F37-A4ED-41B7-A3E6-A2D89D131A30}.Release|Win32.Build.0 = Release|Win32
+ {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Debug|Win32.Build.0 = Debug|Win32
+ {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Release|Win32.ActiveCfg = Release|Win32
+ {B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}.Release|Win32.Build.0 = Release|Win32
+ {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Debug|Win32.Build.0 = Debug|Win32
+ {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Release|Win32.ActiveCfg = Release|Win32
+ {1738D5F6-ED1E-47E0-B2F0-456864B93C1E}.Release|Win32.Build.0 = Release|Win32
+ {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Debug|Win32.Build.0 = Debug|Win32
+ {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Release|Win32.ActiveCfg = Release|Win32
+ {4DF72760-C055-40A5-A77E-30A17E2AC2DB}.Release|Win32.Build.0 = Release|Win32
+ {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Debug|Win32.Build.0 = Debug|Win32
+ {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release|Win32.ActiveCfg = Release|Win32
+ {C8F6C172-56F2-4E76-B5FA-C3B423B31BE7}.Release|Win32.Build.0 = Release|Win32
+ {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug|Win32.ActiveCfg = Debug|Win32
+ {3AF54C8A-10BF-4332-9147-F68ED9862032}.Debug|Win32.Build.0 = Debug|Win32
+ {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release|Win32.ActiveCfg = Release|Win32
+ {3AF54C8A-10BF-4332-9147-F68ED9862032}.Release|Win32.Build.0 = Release|Win32
+ {49EA010D-706F-4BE2-A397-77854B72A040}.Debug|Win32.ActiveCfg = Debug|Win32
+ {49EA010D-706F-4BE2-A397-77854B72A040}.Debug|Win32.Build.0 = Debug|Win32
+ {49EA010D-706F-4BE2-A397-77854B72A040}.Release|Win32.ActiveCfg = Release|Win32
+ {49EA010D-706F-4BE2-A397-77854B72A040}.Release|Win32.Build.0 = Release|Win32
+ {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Debug|Win32.ActiveCfg = Debug|Win32
+ {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Debug|Win32.Build.0 = Debug|Win32
+ {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Release|Win32.ActiveCfg = Release|Win32
+ {12015ACE-42BE-4952-A5A0-44A9A46908E2}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/vsprojects/tests.vcproj b/vsprojects/tests.vcproj
index 013ff1b4..c3976a78 100644
--- a/vsprojects/tests.vcproj
+++ b/vsprojects/tests.vcproj
@@ -1,573 +1,573 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="9.00"
- Name="tests"
- ProjectGUID="{4DF72760-C055-40A5-A77E-30A17E2AC2DB}"
- RootNamespace="tests"
- Keyword="Win32Proj"
- TargetFrameworkVersion="0"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="Debug"
- IntermediateDirectory="Debug"
- ConfigurationType="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- Description=""
- CommandLine=""
- AdditionalDependencies=""
- Outputs=""
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
- Optimization="0"
- AdditionalIncludeDirectories="../src;.;../gtest/include"
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- LinkIncremental="2"
- GenerateDebugInformation="true"
- SubSystem="1"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="Release"
- IntermediateDirectory="Release"
- ConfigurationType="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- Description=""
- CommandLine=""
- AdditionalDependencies=""
- Outputs=""
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
- AdditionalIncludeDirectories="../src;.;../gtest/include"
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;"
- RuntimeLibrary="2"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- LinkIncremental="2"
- GenerateDebugInformation="true"
- SubSystem="1"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <File
- RelativePath=".\google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\testing\file.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\testing\googletest.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\test_util.h"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest.pb.h"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_custom_options.pb.h"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_embed_optimize_for.pb.h"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_import.pb.h"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_lite_imports_nonline.pb.h"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_mset.pb.h"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_optimize_for.pb.h"
- >
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
- >
- </Filter>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath="..\src\google\protobuf\io\coded_stream_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\command_line_interface_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\common_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_bootstrap_unittest.cc"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\descriptor_database_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\descriptor_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\dynamic_message_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\extension_set_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\testing\file.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\generated_message_reflection_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\testing\googletest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\importer_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\message_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\once_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\parser_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\printer_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\reflection_ops_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\repeated_field_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\structurally_valid_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\stubs\strutil_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\test_util.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\text_format_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\tokenizer_unittest.cc"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest.pb.cc"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_custom_options.pb.cc"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_embed_optimize_for.pb.cc"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_import.pb.cc"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_lite_imports_nonlite.pb.cc"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_mset.pb.cc"
- >
- </File>
- <File
- RelativePath=".\google\protobuf\unittest_optimize_for.pb.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\unknown_field_set_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\wire_format_unittest.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream_unittest.cc"
- >
- </File>
- </Filter>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_test_bad_identifiers.proto"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating cpp_test_bad_identifiers.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.h;google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating cpp_test_bad_identifiers.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.h;google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\src\google\protobuf\unittest.proto"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest.pb.h;google\protobuf\unittest.pb.cc"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest.pb.h;google\protobuf\unittest.pb.cc"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\src\google\protobuf\unittest_custom_options.proto"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_custom_options.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_custom_options.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_custom_options.pb.h;google\protobuf\unittest_custom_options.pb.cc"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_custom_options.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_custom_options.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_custom_options.pb.h;google\protobuf\unittest_custom_options.pb.cc"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\src\google\protobuf\unittest_embed_optimize_for.proto"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_embed_optimize_for.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_embed_optimize_for.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_embed_optimize_for.pb.h;google\protobuf\unittest_embed_optimize_for.pb.cc"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_embed_optimize_for.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_embed_optimize_for.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_embed_optimize_for.pb.h;google\protobuf\unittest_embed_optimize_for.pb.cc"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\src\google\protobuf\unittest_import.proto"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_import.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_import.pb.h;google\protobuf\unittest_import.pb.cc"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_import.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_import.pb.h;google\protobuf\unittest_import.pb.cc"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\src\google\protobuf\unittest_lite_imports_nonlite.proto"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_lite_imports_nonlite.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite_imports_nonlite.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_lite_imports_nonlite.pb.h;google\protobuf\unittest_lite_imports_nonlite.pb.cc"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_lite_imports_nonlite.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite_imports_nonlite.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_lite_imports_nonlite.pb.h;google\protobuf\unittest_lite_imports_nonlite.pb.cc"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\src\google\protobuf\unittest_mset.proto"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_mset.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_mset.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_mset.pb.h;google\protobuf\unittest_mset.pb.cc"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_mset.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_mset.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_mset.pb.h;google\protobuf\unittest_mset.pb.cc"
- />
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\src\google\protobuf\unittest_optimize_for.proto"
- >
- <FileConfiguration
- Name="Debug|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_optimize_for.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_optimize_for.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_optimize_for.pb.h;google\protobuf\unittest_optimize_for.pb.cc"
- />
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32"
- >
- <Tool
- Name="VCCustomBuildTool"
- Description="Generating unittest_optimize_for.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_optimize_for.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_optimize_for.pb.h;google\protobuf\unittest_optimize_for.pb.cc"
- />
- </FileConfiguration>
- </File>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="tests"
+ ProjectGUID="{4DF72760-C055-40A5-A77E-30A17E2AC2DB}"
+ RootNamespace="tests"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ Description=""
+ CommandLine=""
+ AdditionalDependencies=""
+ Outputs=""
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
+ Optimization="0"
+ AdditionalIncludeDirectories="../src;.;../gtest/include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ Description=""
+ CommandLine=""
+ AdditionalDependencies=""
+ Outputs=""
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
+ AdditionalIncludeDirectories="../src;.;../gtest/include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\testing\file.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\testing\googletest.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\test_util.h"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest.pb.h"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_custom_options.pb.h"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_embed_optimize_for.pb.h"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_import.pb.h"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_lite_imports_nonline.pb.h"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_mset.pb.h"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_optimize_for.pb.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\src\google\protobuf\io\coded_stream_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\command_line_interface_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\common_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_bootstrap_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\descriptor_database_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\descriptor_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\dynamic_message_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\extension_set_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\testing\file.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\generated_message_reflection_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\testing\googletest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\importer_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\message_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\once_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\parser_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\printer_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\reflection_ops_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\repeated_field_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\structurally_valid_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\strutil_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\test_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\text_format_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\tokenizer_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_custom_options.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_embed_optimize_for.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_import.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_lite_imports_nonlite.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_mset.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_optimize_for.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unknown_field_set_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\wire_format_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream_unittest.cc"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_test_bad_identifiers.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating cpp_test_bad_identifiers.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.h;google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating cpp_test_bad_identifiers.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.h;google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unittest.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest.pb.h;google\protobuf\unittest.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest.pb.h;google\protobuf\unittest.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unittest_custom_options.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_custom_options.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_custom_options.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_custom_options.pb.h;google\protobuf\unittest_custom_options.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_custom_options.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_custom_options.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_custom_options.pb.h;google\protobuf\unittest_custom_options.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unittest_embed_optimize_for.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_embed_optimize_for.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_embed_optimize_for.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_embed_optimize_for.pb.h;google\protobuf\unittest_embed_optimize_for.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_embed_optimize_for.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_embed_optimize_for.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_embed_optimize_for.pb.h;google\protobuf\unittest_embed_optimize_for.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unittest_import.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_import.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_import.pb.h;google\protobuf\unittest_import.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_import.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_import.pb.h;google\protobuf\unittest_import.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unittest_lite_imports_nonlite.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_lite_imports_nonlite.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite_imports_nonlite.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_lite_imports_nonlite.pb.h;google\protobuf\unittest_lite_imports_nonlite.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_lite_imports_nonlite.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite_imports_nonlite.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_lite_imports_nonlite.pb.h;google\protobuf\unittest_lite_imports_nonlite.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unittest_mset.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_mset.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_mset.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_mset.pb.h;google\protobuf\unittest_mset.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_mset.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_mset.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_mset.pb.h;google\protobuf\unittest_mset.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unittest_optimize_for.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_optimize_for.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_optimize_for.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_optimize_for.pb.h;google\protobuf\unittest_optimize_for.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_optimize_for.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_optimize_for.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\unittest_optimize_for.pb.h;google\protobuf\unittest_optimize_for.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>