aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-04-25 02:53:47 +0000
committerGravatar kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-04-25 02:53:47 +0000
commitd37d46dfbcedadeb439ad0367f8afcf8867dca43 (patch)
treeb896df229f7c671637924c156d5a759ba50a3190
parent709ea28f3264aa5632e5577a4080671173fc6166 (diff)
Integrate recent changes from Google-internal code tree. See CHANGES.txt
for details.
-rw-r--r--CHANGES.txt81
-rw-r--r--CONTRIBUTORS.txt3
-rw-r--r--Makefile.am3
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessage.java58
-rw-r--r--java/src/main/java/com/google/protobuf/BlockingRpcChannel.java51
-rw-r--r--java/src/main/java/com/google/protobuf/BlockingService.java64
-rw-r--r--java/src/main/java/com/google/protobuf/CodedInputStream.java62
-rw-r--r--java/src/main/java/com/google/protobuf/Descriptors.java2
-rw-r--r--java/src/main/java/com/google/protobuf/DynamicMessage.java7
-rw-r--r--java/src/main/java/com/google/protobuf/Message.java43
-rw-r--r--java/src/main/java/com/google/protobuf/RpcUtil.java6
-rw-r--r--java/src/main/java/com/google/protobuf/ServiceException.java42
-rw-r--r--java/src/main/java/com/google/protobuf/UnknownFieldSet.java45
-rw-r--r--java/src/test/java/com/google/protobuf/AbstractMessageTest.java38
-rw-r--r--java/src/test/java/com/google/protobuf/CodedInputStreamTest.java61
-rw-r--r--java/src/test/java/com/google/protobuf/DynamicMessageTest.java12
-rw-r--r--java/src/test/java/com/google/protobuf/GeneratedMessageTest.java11
-rw-r--r--java/src/test/java/com/google/protobuf/ServiceTest.java99
-rw-r--r--java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java99
-rw-r--r--java/src/test/java/com/google/protobuf/WireFormatTest.java20
-rwxr-xr-xpython/google/protobuf/internal/input_stream.py115
-rwxr-xr-xpython/google/protobuf/internal/input_stream_test.py21
-rwxr-xr-xpython/google/protobuf/internal/reflection_test.py9
-rwxr-xr-xpython/google/protobuf/reflection.py4
-rw-r--r--src/Makefile.am6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc24
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc72
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.h6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_extension.cc81
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_extension.h3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.h23
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc152
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc47
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h10
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc455
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h29
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc34
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.h6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.cc99
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.h6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_service.cc6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc100
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.h6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc140
-rw-r--r--src/google/protobuf/compiler/importer.cc34
-rw-r--r--src/google/protobuf/compiler/importer.h10
-rw-r--r--src/google/protobuf/compiler/importer_unittest.cc28
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc20
-rw-r--r--src/google/protobuf/compiler/java/java_service.cc281
-rw-r--r--src/google/protobuf/compiler/java/java_service.h33
-rw-r--r--src/google/protobuf/compiler/parser.cc9
-rw-r--r--src/google/protobuf/compiler/parser.h15
-rw-r--r--src/google/protobuf/compiler/parser_unittest.cc44
-rw-r--r--src/google/protobuf/descriptor.cc1195
-rw-r--r--src/google/protobuf/descriptor.h97
-rw-r--r--src/google/protobuf/descriptor.pb.cc1995
-rw-r--r--src/google/protobuf/descriptor.pb.h1036
-rw-r--r--src/google/protobuf/descriptor.proto9
-rw-r--r--src/google/protobuf/descriptor_database.cc397
-rw-r--r--src/google/protobuf/descriptor_database.h207
-rw-r--r--src/google/protobuf/descriptor_database_unittest.cc413
-rw-r--r--src/google/protobuf/descriptor_unittest.cc313
-rw-r--r--src/google/protobuf/dynamic_message.cc4
-rw-r--r--src/google/protobuf/extension_set.cc988
-rw-r--r--src/google/protobuf/extension_set.h441
-rw-r--r--src/google/protobuf/extension_set_unittest.cc86
-rw-r--r--src/google/protobuf/generated_message_reflection.cc67
-rw-r--r--src/google/protobuf/generated_message_reflection.h26
-rw-r--r--src/google/protobuf/io/coded_stream.cc258
-rw-r--r--src/google/protobuf/io/coded_stream.h179
-rw-r--r--src/google/protobuf/io/coded_stream_unittest.cc20
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl.cc5
-rw-r--r--src/google/protobuf/message.cc112
-rw-r--r--src/google/protobuf/message.h58
-rw-r--r--src/google/protobuf/reflection_ops_unittest.cc36
-rw-r--r--src/google/protobuf/repeated_field.h124
-rw-r--r--src/google/protobuf/repeated_field_unittest.cc149
-rw-r--r--src/google/protobuf/stubs/common.h6
-rw-r--r--src/google/protobuf/stubs/hash.h27
-rw-r--r--src/google/protobuf/stubs/map-util.h15
-rw-r--r--src/google/protobuf/stubs/once.cc82
-rw-r--r--src/google/protobuf/stubs/once.h122
-rw-r--r--src/google/protobuf/stubs/once_unittest.cc253
-rw-r--r--src/google/protobuf/test_util.cc22
-rw-r--r--src/google/protobuf/test_util.h6
-rw-r--r--src/google/protobuf/text_format.cc271
-rw-r--r--src/google/protobuf/text_format.h99
-rw-r--r--src/google/protobuf/text_format_unittest.cc83
-rw-r--r--src/google/protobuf/unittest.proto8
-rw-r--r--src/google/protobuf/unittest_empty.proto37
-rw-r--r--src/google/protobuf/unknown_field_set.cc244
-rw-r--r--src/google/protobuf/unknown_field_set.h415
-rw-r--r--src/google/protobuf/unknown_field_set_unittest.cc361
-rw-r--r--src/google/protobuf/wire_format.cc297
-rw-r--r--src/google/protobuf/wire_format.h183
-rw-r--r--src/google/protobuf/wire_format_inl.h408
-rw-r--r--src/google/protobuf/wire_format_unittest.cc75
97 files changed, 9632 insertions, 4332 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 2ac9091e..8fa7a536 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,4 @@
-????-??-?? version 2.0.4:
+????-??-?? version 2.1.0:
General
* Repeated fields of primitive types (types other that string, group, and
@@ -20,22 +20,70 @@
* Updated bundled Google Test to version 1.3.0. Google Test is now bundled
in its verbatim form as a nested autoconf package, so you can drop in any
other version of Google Test if needed.
+ * optimize_for = SPEED is now the default, by popular demand. Use
+ optimize_for = CODE_SIZE if code size is more important in your app.
+ * It is now an error to define a default value for a repeated field.
+ Previously, this was silently ignored (it had no effect on the generated
+ code).
+ * Fields can now be marked deprecated like:
+ optional int32 foo = 1 [deprecated = true];
+ Currently this does not have any actual effect, but in the future the code
+ generators may generate deprecation annotations in each language.
protoc
* --error_format=msvs option causes errors to be printed in Visual Studio
format, which should allow them to be clicked on in the build log to go
- directly to the error location.
+ directly to the error location.
+ * The type name resolver will no longer resolve type names to fields. For
+ example, this now works:
+ message Foo {}
+ message Bar {
+ optional int32 Foo = 1;
+ optional Foo baz = 2;
+ }
+ Previously, the type of "baz" would resolve to "Bar.Foo", and you'd get
+ an error because Bar.Foo is a field, not a type. Now the type of "baz"
+ resolves to the message type Foo. This change is unlikely to make a
+ difference to anyone who follows the Protocol Buffers style guide.
C++
- * UnknownFieldSet now supports STL-like iteration.
+ * Several optimizations, including but not limited to:
+ - Serialization, especially to flat arrays, is 10%-50% faster, possibly
+ more for small objects.
+ - Several descriptor operations which previously required locking no longer
+ do.
+ - Descriptors are now constructed lazily on first use, rather than at
+ process startup time. This should save memory in programs which do not
+ use descriptors or reflection.
+ - UnknownFieldSet completely redesigned to be more efficient (especially in
+ terms of memory usage).
+ - Various optimizations to reduce code size (though the serialization speed
+ optimizations increased code size).
* Message interface has method ParseFromBoundedZeroCopyStream() which parses
a limited number of bytes from an input stream rather than parsing until
EOF.
* GzipInputStream and GzipOutputStream support reading/writing gzip- or
zlib-compressed streams if zlib is available.
(google/protobuf/io/gzip_stream.h)
- * Generated constructors explicitly initialize all fields (to avoid warnings
- with certain compiler settings).
+ * DescriptorPool::FindAllExtensions() and corresponding
+ DescriptorDatabase::FindAllExtensions() can be used to enumerate all
+ extensions of a given type.
+ * For each enum type Foo, protoc will generate functions:
+ const string& Foo_Name(Foo value);
+ bool Foo_Parse(const string& name, Foo* result);
+ The former returns the name of the enum constant corresponding to the given
+ value while the latter finds the value corresponding to a name.
+ * RepeatedField and RepeatedPtrField now have back-insertion iterators.
+ * String fields now have setters that take a char* and a size, in addition
+ to the existing ones that took char* or const string&.
+ * DescriptorPool::AllowUnknownDependencies() may be used to tell
+ DescriptorPool to create placeholder descriptors for unknown entities
+ referenced in a FileDescriptorProto. This can allow you to parse a .proto
+ file without having access to other .proto files that it imports, for
+ example.
+ * Updated gtest to latest version. The gtest package is now included as a
+ nested autoconf package, so it should be able to drop new versions into the
+ "gtest" subdirectory without modification.
Java
* Fixed bug where Message.mergeFrom(Message) failed to merge extensions.
@@ -48,6 +96,28 @@
regex implementation (which unfortunately uses recursive backtracking
rather than building an NFA). Worked around by making use of possesive
quantifiers.
+ * Generated service classes now also generate pure interfaces. For a service
+ Foo, Foo.Interface is a pure interface containing all of the service's
+ defined methods. Foo.newReflectiveService() can be called to wrap an
+ instance of this interface in a class that implements the generic
+ RpcService interface, which provides reflection support that is usually
+ needed by RPC server implementations.
+ * RPC interfaces now support blocking operation in addition to non-blocking.
+ The protocol compiler generates separate blocking and non-blocking stubs
+ which operate against separate blocking and non-blocking RPC interfaces.
+ RPC implementations will have to implement the new interfaces in order to
+ support blocking mode.
+ * New I/O methods parseDelimitedFrom(), mergeDelimitedFrom(), and
+ writeDelimitedTo() read and write "delemited" messages from/to a stream,
+ meaning that the message size precedes the data. This way, you can write
+ multiple messages to a stream without having to worry about delimiting
+ them yourself.
+ * Throw a more descriptive exception when build() is double-called.
+ * Add a method to query whether CodedInputStream is at the end of the input
+ stream.
+ * Add a method to reset a CodedInputStream's size counter; useful when
+ reading many messages with the same stream.
+ * equals() and hashCode() now account for unknown fields.
Python
* Added slicing support for repeated scalar fields. Added slice retrieval and
@@ -58,6 +128,7 @@
object will be returned directly to the caller. This interface change
cannot be used in practice until RPC implementations are updated to
implement it.
+ * Changes to input_stream.py should make protobuf compatible with appengine.
2008-11-25 version 2.0.3:
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index 259a6f7e..8adb1ff7 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -18,6 +18,7 @@ Proto2 Python primary authors:
Petar Petrov <petar@google.com>
Large code contributions:
+ Jason Hsueh <jasonh@google.com>
Joseph Schorr <jschorr@google.com>
Wenbo Zhu <wenboz@google.com>
@@ -38,7 +39,7 @@ Patch contributors:
Kevin Ko <kevin.s.ko@gmail.com>
* Small patch to handle trailing slashes in --proto_path flag.
Johan Euphrosine <proppy@aminche.com>
- * Small patch to fix Pyhton CallMethod().
+ * Small patch to fix Python CallMethod().
Ulrich Kunitz <kune@deine-taler.de>
* Small optimizations to Python serialization.
Leandro Lucarella <llucax@gmail.com>
diff --git a/Makefile.am b/Makefile.am
index c7aadc60..afdfff09 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -61,6 +61,8 @@ EXTRA_DIST = \
examples/add_person.py \
examples/list_people.py \
java/src/main/java/com/google/protobuf/AbstractMessage.java \
+ java/src/main/java/com/google/protobuf/BlockingRpcChannel.java \
+ java/src/main/java/com/google/protobuf/BlockingService.java \
java/src/main/java/com/google/protobuf/ByteString.java \
java/src/main/java/com/google/protobuf/CodedInputStream.java \
java/src/main/java/com/google/protobuf/CodedOutputStream.java \
@@ -77,6 +79,7 @@ EXTRA_DIST = \
java/src/main/java/com/google/protobuf/RpcController.java \
java/src/main/java/com/google/protobuf/RpcUtil.java \
java/src/main/java/com/google/protobuf/Service.java \
+ java/src/main/java/com/google/protobuf/ServiceException.java \
java/src/main/java/com/google/protobuf/TextFormat.java \
java/src/main/java/com/google/protobuf/UninitializedMessageException.java \
java/src/main/java/com/google/protobuf/UnknownFieldSet.java \
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java
index 24c32a47..53175cdd 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -32,6 +32,7 @@ package com.google.protobuf;
import com.google.protobuf.Descriptors.FieldDescriptor;
+import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -152,6 +153,13 @@ public abstract class AbstractMessage implements Message {
codedOutput.flush();
}
+ public void writeDelimitedTo(OutputStream output) throws IOException {
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ codedOutput.writeRawVarint32(getSerializedSize());
+ writeTo(codedOutput);
+ codedOutput.flush();
+ }
+
private int memoizedSize = -1;
public int getSerializedSize() {
@@ -207,7 +215,8 @@ public abstract class AbstractMessage implements Message {
if (getDescriptorForType() != otherMessage.getDescriptorForType()) {
return false;
}
- return getAllFields().equals(otherMessage.getAllFields());
+ return getAllFields().equals(otherMessage.getAllFields()) &&
+ getUnknownFields().equals(otherMessage.getUnknownFields());
}
@Override
@@ -215,6 +224,7 @@ public abstract class AbstractMessage implements Message {
int hash = 41;
hash = (19 * hash) + getDescriptorForType().hashCode();
hash = (53 * hash) + getAllFields().hashCode();
+ hash = (29 * hash) + getUnknownFields().hashCode();
return hash;
}
@@ -397,5 +407,51 @@ public abstract class AbstractMessage implements Message {
codedInput.checkLastTagWas(0);
return (BuilderType) this;
}
+
+ public BuilderType mergeDelimitedFrom(InputStream input,
+ ExtensionRegistry extensionRegistry)
+ throws IOException {
+ final int size = CodedInputStream.readRawVarint32(input);
+
+ // A stream which will not read more than |size| bytes.
+ InputStream limitedInput = new FilterInputStream(input) {
+ int limit = size;
+
+ @Override
+ public int available() throws IOException {
+ return Math.min(super.available(), limit);
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (limit <= 0) return -1;
+ int result = super.read();
+ if (result >= 0) --limit;
+ return result;
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (limit <= 0) return -1;
+ len = Math.min(len, limit);
+ int result = super.read(b, off, len);
+ if (result >= 0) limit -= result;
+ return result;
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ long result = super.skip(Math.min(n, limit));
+ if (result >= 0) limit -= result;
+ return result;
+ }
+ };
+ return mergeFrom(limitedInput, extensionRegistry);
+ }
+
+ public BuilderType mergeDelimitedFrom(InputStream input)
+ throws IOException {
+ return mergeDelimitedFrom(input, ExtensionRegistry.getEmptyRegistry());
+ }
}
}
diff --git a/java/src/main/java/com/google/protobuf/BlockingRpcChannel.java b/java/src/main/java/com/google/protobuf/BlockingRpcChannel.java
new file mode 100644
index 00000000..1e81143a
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/BlockingRpcChannel.java
@@ -0,0 +1,51 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+/**
+ * <p>Abstract interface for a blocking RPC channel. {@code BlockingRpcChannel}
+ * is the blocking equivalent to {@link RpcChannel}.
+ *
+ * @author kenton@google.com Kenton Varda
+ * @author cpovirk@google.com Chris Povirk
+ */
+public interface BlockingRpcChannel {
+ /**
+ * Call the given method of the remote service and blocks until it returns.
+ * {@code callBlockingMethod()} is the blocking equivalent to
+ * {@link RpcChannel#callMethod}.
+ */
+ Message callBlockingMethod(
+ Descriptors.MethodDescriptor method,
+ RpcController controller,
+ Message request,
+ Message responsePrototype) throws ServiceException;
+}
diff --git a/java/src/main/java/com/google/protobuf/BlockingService.java b/java/src/main/java/com/google/protobuf/BlockingService.java
new file mode 100644
index 00000000..ecc80096
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/BlockingService.java
@@ -0,0 +1,64 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+/**
+ * Blocking equivalent to {@link Service}.
+ *
+ * @author kenton@google.com Kenton Varda
+ * @author cpovirk@google.com Chris Povirk
+ */
+public interface BlockingService {
+ /**
+ * Equivalent to {@link Service#getDescriptorForType}.
+ */
+ Descriptors.ServiceDescriptor getDescriptorForType();
+
+ /**
+ * Equivalent to {@link Service#callMethod}, except that
+ * {@code callBlockingMethod()} returns the result of the RPC or throws a
+ * {@link ServiceException} if there is a failure, rather than passing the
+ * information to a callback.
+ */
+ Message callBlockingMethod(Descriptors.MethodDescriptor method,
+ RpcController controller,
+ Message request) throws ServiceException;
+
+ /**
+ * Equivalent to {@link Service#getRequestPrototype}.
+ */
+ Message getRequestPrototype(Descriptors.MethodDescriptor method);
+
+ /**
+ * Equivalent to {@link Service#getResponsePrototype}.
+ */
+ Message getResponsePrototype(Descriptors.MethodDescriptor method);
+}
diff --git a/java/src/main/java/com/google/protobuf/CodedInputStream.java b/java/src/main/java/com/google/protobuf/CodedInputStream.java
index 8f277a9f..b6be2e87 100644
--- a/java/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -77,7 +77,7 @@ public final class CodedInputStream {
* may legally end wherever a tag occurs, and zero is not a valid tag number.
*/
public int readTag() throws IOException {
- if (bufferPos == bufferSize && !refillBuffer(false)) {
+ if (isAtEnd()) {
lastTag = 0;
return 0;
}
@@ -383,6 +383,39 @@ public final class CodedInputStream {
return result;
}
+ /**
+ * Reads a varint from the input one byte at a time, so that it does not
+ * read any bytes after the end of the varint. If you simply wrapped the
+ * stream in a CodedInputStream and used {@link #readRawVarint32(InputStream)}
+ * then you would probably end up reading past the end of the varint since
+ * CodedInputStream buffers its input.
+ */
+ static int readRawVarint32(InputStream input) throws IOException {
+ int result = 0;
+ int offset = 0;
+ for (; offset < 32; offset += 7) {
+ int b = input.read();
+ if (b == -1) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ result |= (b & 0x7f) << offset;
+ if ((b & 0x80) == 0) {
+ return result;
+ }
+ }
+ // Keep reading up to 64 bits.
+ for (; offset < 64; offset += 7) {
+ int b = input.read();
+ if (b == -1) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ if ((b & 0x80) == 0) {
+ return result;
+ }
+ }
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+
/** Read a raw Varint from the stream. */
public long readRawVarint64() throws IOException {
int shift = 0;
@@ -526,6 +559,10 @@ public final class CodedInputStream {
* size limits only apply when reading from an {@code InputStream}, not
* when constructed around a raw byte array (nor with
* {@link ByteString#newCodedInput}).
+ * <p>
+ * If you want to read several messages from a single CodedInputStream, you
+ * could call {@link #resetSizeCounter()} after each one to avoid hitting the
+ * size limit.
*
* @return the old limit.
*/
@@ -540,6 +577,13 @@ public final class CodedInputStream {
}
/**
+ * Resets the current size counter to zero (see {@link #setSizeLimit(int)}).
+ */
+ public void resetSizeCounter() {
+ totalBytesRetired = 0;
+ }
+
+ /**
* Sets {@code currentLimit} to (current position) + {@code byteLimit}. This
* is called when descending into a length-delimited embedded message.
*
@@ -597,6 +641,15 @@ public final class CodedInputStream {
}
/**
+ * Returns true if the stream has reached the end of the input. This is the
+ * case if either the end of the underlying input source has been reached or
+ * if the stream has reached a limit created using {@link #pushLimit(int)}.
+ */
+ public boolean isAtEnd() throws IOException {
+ return bufferPos == bufferSize && !refillBuffer(false);
+ }
+
+ /**
* Called with {@code this.buffer} is empty to read more bytes from the
* input. If {@code mustSucceed} is true, refillBuffer() gurantees that
* either there will be at least one byte in the buffer when it returns
@@ -622,6 +675,11 @@ public final class CodedInputStream {
bufferPos = 0;
bufferSize = (input == null) ? -1 : input.read(buffer);
+ if (bufferSize == 0 || bufferSize < -1) {
+ throw new IllegalStateException(
+ "InputStream#read(byte[]) returned invalid result: " + bufferSize +
+ "\nThe InputStream implementation is buggy.");
+ }
if (bufferSize == -1) {
bufferSize = 0;
if (mustSucceed) {
@@ -778,7 +836,7 @@ public final class CodedInputStream {
throw InvalidProtocolBufferException.truncatedMessage();
}
- if (size < bufferSize - bufferPos) {
+ if (size <= bufferSize - bufferPos) {
// We have all the bytes we need already.
bufferPos += size;
} else {
diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java
index 80266a59..24499efb 100644
--- a/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -1689,7 +1689,7 @@ public final class Descriptors {
GenericDescriptor old =
descriptorsByName.put(fullName,
- new PackageDescriptor(fullName, name, file));
+ new PackageDescriptor(name, fullName, file));
if (old != null) {
descriptorsByName.put(fullName, old);
if (!(old instanceof PackageDescriptor)) {
diff --git a/java/src/main/java/com/google/protobuf/DynamicMessage.java b/java/src/main/java/com/google/protobuf/DynamicMessage.java
index 99ae253c..59fb7b02 100644
--- a/java/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/java/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -260,7 +260,8 @@ public final class DynamicMessage extends AbstractMessage {
}
public DynamicMessage build() {
- if (!isInitialized()) {
+ // If fields == null, we'll throw an appropriate exception later.
+ if (fields != null && !isInitialized()) {
throw new UninitializedMessageException(
new DynamicMessage(type, fields, unknownFields));
}
@@ -282,6 +283,10 @@ public final class DynamicMessage extends AbstractMessage {
}
public DynamicMessage buildPartial() {
+ if (fields == null) {
+ throw new IllegalStateException(
+ "build() has already been called on this Builder.");
+ }
fields.makeImmutable();
DynamicMessage result =
new DynamicMessage(type, fields, unknownFields);
diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java
index 2f8700db..a5951232 100644
--- a/java/src/main/java/com/google/protobuf/Message.java
+++ b/java/src/main/java/com/google/protobuf/Message.java
@@ -183,9 +183,28 @@ public interface Message {
* Serializes the message and writes it to {@code output}. This is just a
* trivial wrapper around {@link #writeTo(CodedOutputStream)}. This does
* not flush or close the stream.
+ * <p>
+ * NOTE: Protocol Buffers are not self-delimiting. Therefore, if you write
+ * any more data to the stream after the message, you must somehow ensure
+ * that the parser on the receiving end does not interpret this as being
+ * part of the protocol message. This can be done e.g. by writing the size
+ * of the message before the data, then making sure to limit the input to
+ * that size on the receiving end (e.g. by wrapping the InputStream in one
+ * which limits the input). Alternatively, just use
+ * {@link #writeDelimitedTo(OutputStream)}.
*/
void writeTo(OutputStream output) throws IOException;
+ /**
+ * Like {@link #writeTo(OutputStream)}, but writes the size of the message
+ * as a varint before writing the data. This allows more data to be written
+ * to the stream after the message without the need to delimit the message
+ * data yourself. Use {@link Builder#mergeDelimitedFrom(InputStream)} (or
+ * the static method {@code YourMessageType.parseDelimitedFrom(InputStream)})
+ * to parse messages written by this method.
+ */
+ void writeDelimitedTo(OutputStream output) throws IOException;
+
// =================================================================
// Builders
@@ -434,8 +453,11 @@ public interface Message {
* {@link #mergeFrom(CodedInputStream)}. Note that this method always
* reads the <i>entire</i> input (unless it throws an exception). If you
* want it to stop earlier, you will need to wrap your input in some
- * wrapper stream that limits reading. Despite usually reading the entire
- * input, this does not close the stream.
+ * wrapper stream that limits reading. Or, use
+ * {@link Message#writeDelimitedTo(OutputStream)} to write your message and
+ * {@link #mergeDelimitedFrom(InputStream)} to read it.
+ * <p>
+ * Despite usually reading the entire input, this does not close the stream.
*/
Builder mergeFrom(InputStream input) throws IOException;
@@ -447,5 +469,22 @@ public interface Message {
Builder mergeFrom(InputStream input,
ExtensionRegistry extensionRegistry)
throws IOException;
+
+ /**
+ * Like {@link #mergeFrom(InputStream)}, but does not read until EOF.
+ * Instead, the size of the message (encoded as a varint) is read first,
+ * then the message data. Use
+ * {@link Message#writeDelimitedTo(OutputStream)} to write messages in this
+ * format.
+ */
+ Builder mergeDelimitedFrom(InputStream input)
+ throws IOException;
+
+ /**
+ * Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions.
+ */
+ Builder mergeDelimitedFrom(InputStream input,
+ ExtensionRegistry extensionRegistry)
+ throws IOException;
}
}
diff --git a/java/src/main/java/com/google/protobuf/RpcUtil.java b/java/src/main/java/com/google/protobuf/RpcUtil.java
index a11b0437..8144bbfb 100644
--- a/java/src/main/java/com/google/protobuf/RpcUtil.java
+++ b/java/src/main/java/com/google/protobuf/RpcUtil.java
@@ -39,7 +39,7 @@ public final class RpcUtil {
private RpcUtil() {}
/**
- * Take an {@code RcpCallabck<Message>} and convert it to an
+ * Take an {@code RpcCallback<Message>} and convert it to an
* {@code RpcCallback} accepting a specific message type. This is always
* type-safe (parameter type contravariance).
*/
@@ -58,8 +58,8 @@ public final class RpcUtil {
}
/**
- * Take an {@code RcpCallabck} accepting a specific message type and convert
- * it to an {@code RcpCallabck<Message>}. The generalized callback will
+ * Take an {@code RpcCallback} accepting a specific message type and convert
+ * it to an {@code RpcCallback<Message>}. The generalized callback will
* accept any message object which has the same descriptor, and will convert
* it to the correct class before calling the original callback. However,
* if the generalized callback is given a message with a different descriptor,
diff --git a/java/src/main/java/com/google/protobuf/ServiceException.java b/java/src/main/java/com/google/protobuf/ServiceException.java
new file mode 100644
index 00000000..70b9d0c1
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/ServiceException.java
@@ -0,0 +1,42 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+/**
+ * Thrown by blocking RPC methods when a failure occurs.
+ *
+ * @author cpovirk@google.com (Chris Povirk)
+ */
+public final class ServiceException extends Exception {
+ public ServiceException(String message) {
+ super(message);
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
index 445951b0..77fef323 100644
--- a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -34,6 +34,7 @@ import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.TreeMap;
import java.util.List;
@@ -85,6 +86,20 @@ public final class UnknownFieldSet {
}
private Map<Integer, Field> fields;
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ return (other instanceof UnknownFieldSet) &&
+ this.fields.equals(((UnknownFieldSet) other).fields);
+ }
+
+ @Override
+ public int hashCode() {
+ return this.fields.hashCode();
+ }
+
/** Get a map of fields in the set by number. */
public Map<Integer, Field> asMap() {
return fields;
@@ -540,6 +555,36 @@ public final class UnknownFieldSet {
*/
public List<UnknownFieldSet> getGroupList() { return group; }
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof Field)) {
+ return false;
+ }
+ return Arrays.equals(this.getIdentityArray(),
+ ((Field) other).getIdentityArray());
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(getIdentityArray());
+ }
+
+ /**
+ * Returns the array of objects to be used to uniquely identify this
+ * {@link UnknownFieldSet.Field} instance.
+ */
+ private Object[] getIdentityArray() {
+ return new Object[] {
+ this.varint,
+ this.fixed32,
+ this.fixed64,
+ this.lengthDelimited,
+ this.group};
+ }
+
/**
* Serializes the field, including field number, and writes it to
* {@code output}.
diff --git a/java/src/test/java/com/google/protobuf/AbstractMessageTest.java b/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
index da073561..2c59fd0d 100644
--- a/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
@@ -30,14 +30,14 @@
package com.google.protobuf;
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
import protobuf_unittest.UnittestProto;
import protobuf_unittest.UnittestProto.ForeignMessage;
-import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestPackedTypes;
import protobuf_unittest.UnittestProto.TestRequired;
import protobuf_unittest.UnittestProto.TestRequiredForeign;
-import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
import junit.framework.TestCase;
@@ -329,7 +329,7 @@ public class AbstractMessageTest extends TestCase {
// -----------------------------------------------------------------
// Tests for equals and hashCode
- public void testEqualsAndHashCode() {
+ public void testEqualsAndHashCode() throws Exception {
TestAllTypes a = TestUtil.getAllSet();
TestAllTypes b = TestAllTypes.newBuilder().build();
TestAllTypes c = TestAllTypes.newBuilder(b).addRepeatedString("x").build();
@@ -337,7 +337,7 @@ public class AbstractMessageTest extends TestCase {
TestAllExtensions e = TestUtil.getAllExtensionsSet();
TestAllExtensions f = TestAllExtensions.newBuilder(e)
.addExtension(UnittestProto.repeatedInt32Extension, 999).build();
-
+
checkEqualsIsConsistent(a);
checkEqualsIsConsistent(b);
checkEqualsIsConsistent(c);
@@ -364,10 +364,25 @@ public class AbstractMessageTest extends TestCase {
checkNotEqual(d, f);
checkNotEqual(e, f);
+
+ // Deserializing into the TestEmptyMessage such that every field
+ // is an {@link UnknownFieldSet.Field}.
+ UnittestProto.TestEmptyMessage eUnknownFields =
+ UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
+ UnittestProto.TestEmptyMessage fUnknownFields =
+ UnittestProto.TestEmptyMessage.parseFrom(f.toByteArray());
+ checkNotEqual(eUnknownFields, fUnknownFields);
+ checkEqualsIsConsistent(eUnknownFields);
+ checkEqualsIsConsistent(fUnknownFields);
+
+ // Subseqent reconstitutions should be identical
+ UnittestProto.TestEmptyMessage eUnknownFields2 =
+ UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
+ checkEqualsIsConsistent(eUnknownFields, eUnknownFields2);
}
/**
- * Asserts that the given protos are equal and have the same hash code.
+ * Asserts that the given proto has symetric equals and hashCode methods.
*/
private void checkEqualsIsConsistent(Message message) {
// Object should be equal to itself.
@@ -375,9 +390,16 @@ public class AbstractMessageTest extends TestCase {
// Object should be equal to a dynamic copy of itself.
DynamicMessage dynamic = DynamicMessage.newBuilder(message).build();
- assertEquals(message, dynamic);
- assertEquals(dynamic, message);
- assertEquals(dynamic.hashCode(), message.hashCode());
+ checkEqualsIsConsistent(message, dynamic);
+ }
+
+ /**
+ * Asserts that the given protos are equal and have the same hash code.
+ */
+ private void checkEqualsIsConsistent(Message message1, Message message2) {
+ assertEquals(message1, message2);
+ assertEquals(message2, message1);
+ assertEquals(message2.hashCode(), message1.hashCode());
}
/**
diff --git a/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
index eaaddf44..850b8aa7 100644
--- a/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
+++ b/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
@@ -95,6 +95,7 @@ public class CodedInputStreamTest extends TestCase {
input = CodedInputStream.newInstance(data);
assertEquals(value, input.readRawVarint64());
+ assertTrue(input.isAtEnd());
// Try different block sizes.
for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
@@ -105,7 +106,17 @@ public class CodedInputStreamTest extends TestCase {
input = CodedInputStream.newInstance(
new SmallBlockInputStream(data, blockSize));
assertEquals(value, input.readRawVarint64());
+ assertTrue(input.isAtEnd());
}
+
+ // Try reading direct from an InputStream. We want to verify that it
+ // doesn't read past the end of the input, so we copy to a new, bigger
+ // array first.
+ byte[] longerData = new byte[data.length + 1];
+ System.arraycopy(data, 0, longerData, 0, data.length);
+ InputStream rawInput = new ByteArrayInputStream(longerData);
+ assertEquals((int)value, CodedInputStream.readRawVarint32(rawInput));
+ assertEquals(1, rawInput.available());
}
/**
@@ -131,6 +142,14 @@ public class CodedInputStreamTest extends TestCase {
} catch (InvalidProtocolBufferException e) {
assertEquals(expected.getMessage(), e.getMessage());
}
+
+ // Make sure we get the same error when reading direct from an InputStream.
+ try {
+ CodedInputStream.readRawVarint32(new ByteArrayInputStream(data));
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(expected.getMessage(), e.getMessage());
+ }
}
/** Tests readRawVarint32() and readRawVarint64(). */
@@ -180,12 +199,14 @@ public class CodedInputStreamTest extends TestCase {
throws Exception {
CodedInputStream input = CodedInputStream.newInstance(data);
assertEquals(value, input.readRawLittleEndian32());
+ assertTrue(input.isAtEnd());
// Try different block sizes.
for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
input = CodedInputStream.newInstance(
new SmallBlockInputStream(data, blockSize));
assertEquals(value, input.readRawLittleEndian32());
+ assertTrue(input.isAtEnd());
}
}
@@ -197,12 +218,14 @@ public class CodedInputStreamTest extends TestCase {
throws Exception {
CodedInputStream input = CodedInputStream.newInstance(data);
assertEquals(value, input.readRawLittleEndian64());
+ assertTrue(input.isAtEnd());
// Try different block sizes.
for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
input = CodedInputStream.newInstance(
new SmallBlockInputStream(data, blockSize));
assertEquals(value, input.readRawLittleEndian64());
+ assertTrue(input.isAtEnd());
}
}
@@ -288,6 +311,20 @@ public class CodedInputStreamTest extends TestCase {
}
}
+ /**
+ * Test that a bug in skipRawBytes() has been fixed: if the skip skips
+ * exactly up to a limit, this should not break things.
+ */
+ public void testSkipRawBytesBug() throws Exception {
+ byte[] rawBytes = new byte[] { 1, 2 };
+ CodedInputStream input = CodedInputStream.newInstance(rawBytes);
+
+ int limit = input.pushLimit(1);
+ input.skipRawBytes(1);
+ input.popLimit(limit);
+ assertEquals(2, input.readRawByte());
+ }
+
public void testReadHugeBlob() throws Exception {
// Allocate and initialize a 1MB blob.
byte[] blob = new byte[1 << 20];
@@ -392,6 +429,30 @@ public class CodedInputStreamTest extends TestCase {
}
}
+ public void testResetSizeCounter() throws Exception {
+ CodedInputStream input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(new byte[256], 8));
+ input.setSizeLimit(16);
+ input.readRawBytes(16);
+
+ try {
+ input.readRawByte();
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException e) {
+ // success.
+ }
+
+ input.resetSizeCounter();
+ input.readRawByte(); // No exception thrown.
+
+ try {
+ input.readRawBytes(16); // Hits limit again.
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException e) {
+ // success.
+ }
+ }
+
/**
* Tests that if we read an string that contains invalid UTF-8, no exception
* is thrown. Instead, the invalid bytes are replaced with the Unicode
diff --git a/java/src/test/java/com/google/protobuf/DynamicMessageTest.java b/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
index fc53c531..120b0f13 100644
--- a/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -61,6 +61,18 @@ public class DynamicMessageTest extends TestCase {
reflectionTester.assertAllFieldsSetViaReflection(message);
}
+ public void testDoubleBuildError() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ builder.build();
+ try {
+ builder.build();
+ fail("Should have thrown exception.");
+ } catch (IllegalStateException e) {
+ // Success.
+ }
+ }
+
public void testDynamicMessageSettersRejectNull() throws Exception {
Message.Builder builder =
DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 04ba769e..58d82193 100644
--- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -71,6 +71,17 @@ public class GeneratedMessageTest extends TestCase {
TestUtil.assertAllFieldsSet(message);
}
+ public void testDoubleBuildError() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.build();
+ try {
+ builder.build();
+ fail("Should have thrown exception.");
+ } catch (IllegalStateException e) {
+ // Success.
+ }
+ }
+
public void testSettersRejectNull() throws Exception {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
try {
diff --git a/java/src/test/java/com/google/protobuf/ServiceTest.java b/java/src/test/java/com/google/protobuf/ServiceTest.java
index 6a747f48..d8523ea3 100644
--- a/java/src/test/java/com/google/protobuf/ServiceTest.java
+++ b/java/src/test/java/com/google/protobuf/ServiceTest.java
@@ -30,6 +30,10 @@
package com.google.protobuf;
+import com.google.protobuf.Descriptors.MethodDescriptor;
+import protobuf_unittest.MessageWithNoOuter;
+import protobuf_unittest.ServiceWithNoOuter;
+import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestService;
import protobuf_unittest.UnittestProto.FooRequest;
import protobuf_unittest.UnittestProto.FooResponse;
@@ -56,6 +60,7 @@ public class ServiceTest extends TestCase {
private final Descriptors.MethodDescriptor barDescriptor =
TestService.getDescriptor().getMethods().get(1);
+ @Override
protected void setUp() throws Exception {
super.setUp();
control = EasyMock.createStrictControl();
@@ -127,6 +132,94 @@ public class ServiceTest extends TestCase {
control.verify();
}
+ /** Tests generated blocking stubs. */
+ public void testBlockingStub() throws Exception {
+ FooRequest fooRequest = FooRequest.newBuilder().build();
+ BarRequest barRequest = BarRequest.newBuilder().build();
+ BlockingRpcChannel mockChannel =
+ control.createMock(BlockingRpcChannel.class);
+ TestService.BlockingInterface stub =
+ TestService.newBlockingStub(mockChannel);
+
+ FooResponse fooResponse = FooResponse.newBuilder().build();
+ BarResponse barResponse = BarResponse.newBuilder().build();
+
+ EasyMock.expect(mockChannel.callBlockingMethod(
+ EasyMock.same(fooDescriptor),
+ EasyMock.same(mockController),
+ EasyMock.same(fooRequest),
+ EasyMock.same(FooResponse.getDefaultInstance()))).andReturn(fooResponse);
+ EasyMock.expect(mockChannel.callBlockingMethod(
+ EasyMock.same(barDescriptor),
+ EasyMock.same(mockController),
+ EasyMock.same(barRequest),
+ EasyMock.same(BarResponse.getDefaultInstance()))).andReturn(barResponse);
+ control.replay();
+
+ assertSame(fooResponse, stub.foo(mockController, fooRequest));
+ assertSame(barResponse, stub.bar(mockController, barRequest));
+ control.verify();
+ }
+
+ public void testNewReflectiveService() {
+ ServiceWithNoOuter.Interface impl =
+ control.createMock(ServiceWithNoOuter.Interface.class);
+ RpcController controller = control.createMock(RpcController.class);
+ Service service = ServiceWithNoOuter.newReflectiveService(impl);
+
+ MethodDescriptor fooMethod =
+ ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
+ MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
+ RpcCallback<Message> callback = new RpcCallback<Message>() {
+ public void run(Message parameter) {
+ // No reason this should be run.
+ fail();
+ }
+ };
+ RpcCallback<TestAllTypes> specializedCallback =
+ RpcUtil.specializeCallback(callback);
+
+ impl.foo(EasyMock.same(controller), EasyMock.same(request),
+ EasyMock.same(specializedCallback));
+ EasyMock.expectLastCall();
+
+ control.replay();
+
+ service.callMethod(fooMethod, controller, request, callback);
+
+ control.verify();
+ }
+
+ public void testNewReflectiveBlockingService() throws ServiceException {
+ ServiceWithNoOuter.BlockingInterface impl =
+ control.createMock(ServiceWithNoOuter.BlockingInterface.class);
+ RpcController controller = control.createMock(RpcController.class);
+ BlockingService service =
+ ServiceWithNoOuter.newReflectiveBlockingService(impl);
+
+ MethodDescriptor fooMethod =
+ ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
+ MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
+ RpcCallback<Message> callback = new RpcCallback<Message>() {
+ public void run(Message parameter) {
+ // No reason this should be run.
+ fail();
+ }
+ };
+
+ TestAllTypes expectedResponse = TestAllTypes.getDefaultInstance();
+ EasyMock.expect(impl.foo(EasyMock.same(controller), EasyMock.same(request)))
+ .andReturn(expectedResponse);
+
+ control.replay();
+
+ Message response =
+ service.callBlockingMethod(fooMethod, controller, request);
+ assertEquals(expectedResponse, response);
+
+ control.verify();
+ }
+
// =================================================================
/**
@@ -135,7 +228,7 @@ public class ServiceTest extends TestCase {
* In other words, c wraps the given callback.
*/
private <Type extends Message> RpcCallback<Type> wrapsCallback(
- MockCallback callback) {
+ MockCallback<?> callback) {
EasyMock.reportMatcher(new WrapsCallback(callback));
return null;
}
@@ -153,9 +246,9 @@ public class ServiceTest extends TestCase {
/** Implementation of the wrapsCallback() argument matcher. */
private static class WrapsCallback implements IArgumentMatcher {
- private MockCallback callback;
+ private MockCallback<?> callback;
- public WrapsCallback(MockCallback callback) {
+ public WrapsCallback(MockCallback<?> callback) {
this.callback = callback;
}
diff --git a/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java b/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
index 212b381f..ea088b32 100644
--- a/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
+++ b/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
@@ -31,13 +31,13 @@
package com.google.protobuf;
import protobuf_unittest.UnittestProto;
-import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestEmptyMessage;
-import protobuf_unittest.UnittestProto.
- TestEmptyMessageWithExtensions;
+import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions;
import junit.framework.TestCase;
+
import java.util.Arrays;
import java.util.Map;
@@ -341,4 +341,97 @@ public class UnknownFieldSetTest extends TestCase {
assertEquals(1, field.getVarintList().size());
assertEquals(0x7FFFFFFFFFFFFFFFL, (long)field.getVarintList().get(0));
}
+
+ public void testEqualsAndHashCode() {
+ UnknownFieldSet.Field fixed32Field =
+ UnknownFieldSet.Field.newBuilder()
+ .addFixed32(1)
+ .build();
+ UnknownFieldSet.Field fixed64Field =
+ UnknownFieldSet.Field.newBuilder()
+ .addFixed64(1)
+ .build();
+ UnknownFieldSet.Field varIntField =
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(1)
+ .build();
+ UnknownFieldSet.Field lengthDelimitedField =
+ UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(ByteString.EMPTY)
+ .build();
+ UnknownFieldSet.Field groupField =
+ UnknownFieldSet.Field.newBuilder()
+ .addGroup(unknownFields)
+ .build();
+
+ UnknownFieldSet a =
+ UnknownFieldSet.newBuilder()
+ .addField(1, fixed32Field)
+ .build();
+ UnknownFieldSet b =
+ UnknownFieldSet.newBuilder()
+ .addField(1, fixed64Field)
+ .build();
+ UnknownFieldSet c =
+ UnknownFieldSet.newBuilder()
+ .addField(1, varIntField)
+ .build();
+ UnknownFieldSet d =
+ UnknownFieldSet.newBuilder()
+ .addField(1, lengthDelimitedField)
+ .build();
+ UnknownFieldSet e =
+ UnknownFieldSet.newBuilder()
+ .addField(1, groupField)
+ .build();
+
+ checkEqualsIsConsistent(a);
+ checkEqualsIsConsistent(b);
+ checkEqualsIsConsistent(c);
+ checkEqualsIsConsistent(d);
+ checkEqualsIsConsistent(e);
+
+ checkNotEqual(a, b);
+ checkNotEqual(a, c);
+ checkNotEqual(a, d);
+ checkNotEqual(a, e);
+ checkNotEqual(b, c);
+ checkNotEqual(b, d);
+ checkNotEqual(b, e);
+ checkNotEqual(c, d);
+ checkNotEqual(c, e);
+ checkNotEqual(d, e);
+ }
+
+ /**
+ * Asserts that the given field sets are not equal and have different
+ * hash codes.
+ *
+ * @warning It's valid for non-equal objects to have the same hash code, so
+ * this test is stricter than it needs to be. However, this should happen
+ * relatively rarely.
+ */
+ private void checkNotEqual(UnknownFieldSet s1, UnknownFieldSet s2) {
+ String equalsError = String.format("%s should not be equal to %s", s1, s2);
+ assertFalse(equalsError, s1.equals(s2));
+ assertFalse(equalsError, s2.equals(s1));
+
+ assertFalse(
+ String.format("%s should have a different hash code from %s", s1, s2),
+ s1.hashCode() == s2.hashCode());
+ }
+
+ /**
+ * Asserts that the given field sets are equal and have identical hash codes.
+ */
+ private void checkEqualsIsConsistent(UnknownFieldSet set) {
+ // Object should be equal to itself.
+ assertEquals(set, set);
+
+ // Object should be equal to a copy of itself.
+ UnknownFieldSet copy = UnknownFieldSet.newBuilder(set).build();
+ assertEquals(set, copy);
+ assertEquals(copy, set);
+ assertEquals(set.hashCode(), copy.hashCode());
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/WireFormatTest.java b/java/src/test/java/com/google/protobuf/WireFormatTest.java
index 48453faf..4afefdb6 100644
--- a/java/src/test/java/com/google/protobuf/WireFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -31,6 +31,10 @@
package com.google.protobuf;
import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
import protobuf_unittest.UnittestProto;
import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestAllTypes;
@@ -130,6 +134,22 @@ public class WireFormatTest extends TestCase {
TestUtil.getAllExtensionsSet().getSerializedSize());
}
+ public void testSerializeDelimited() throws Exception {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ TestUtil.getAllSet().writeDelimitedTo(output);
+ output.write(12);
+ TestUtil.getPackedSet().writeDelimitedTo(output);
+ output.write(34);
+
+ ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
+
+ TestUtil.assertAllFieldsSet(TestAllTypes.parseDelimitedFrom(input));
+ assertEquals(12, input.read());
+ TestUtil.assertPackedFieldsSet(TestPackedTypes.parseDelimitedFrom(input));
+ assertEquals(34, input.read());
+ assertEquals(-1, input.read());
+ }
+
private void assertFieldsInOrder(ByteString data) throws Exception {
CodedInputStream input = data.newCodedInput();
int previousTag = 0;
diff --git a/python/google/protobuf/internal/input_stream.py b/python/google/protobuf/internal/input_stream.py
index 2cff93db..7bda17e3 100755
--- a/python/google/protobuf/internal/input_stream.py
+++ b/python/google/protobuf/internal/input_stream.py
@@ -36,6 +36,7 @@ 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
@@ -46,7 +47,7 @@ from google.protobuf.internal import wire_format
# proto2 implementation.
-class InputStream(object):
+class InputStreamBuffer(object):
"""Contains all logic for reading bits, and dealing with stream position.
@@ -223,3 +224,115 @@ class InputStream(object):
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
index 8cc1d126..ecec7f7d 100755
--- a/python/google/protobuf/internal/input_stream_test.py
+++ b/python/google/protobuf/internal/input_stream_test.py
@@ -40,7 +40,14 @@ from google.protobuf.internal import wire_format
from google.protobuf.internal import input_stream
-class InputStreamTest(unittest.TestCase):
+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')
@@ -291,5 +298,17 @@ class InputStreamTest(unittest.TestCase):
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/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index 1d88c1cc..e2da769a 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -1102,6 +1102,15 @@ class FullProtosEqualityTest(unittest.TestCase):
test_util.SetAllFields(self.first_proto)
test_util.SetAllFields(self.second_proto)
+ def testNoneNotEqual(self):
+ self.assertNotEqual(self.first_proto, None)
+ self.assertNotEqual(None, self.second_proto)
+
+ def testNotEqualToOtherMessage(self):
+ third_proto = unittest_pb2.TestRequired()
+ self.assertNotEqual(self.first_proto, third_proto)
+ self.assertNotEqual(third_proto, self.second_proto)
+
def testAllFieldsFilledEquality(self):
self.assertEqual(self.first_proto, self.second_proto)
diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py
index f345067a..5ab7a1b1 100755
--- a/python/google/protobuf/reflection.py
+++ b/python/google/protobuf/reflection.py
@@ -599,6 +599,10 @@ def _AddHasExtensionMethod(cls):
def _AddEqualsMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
def __eq__(self, other):
+ if (not isinstance(other, message_mod.Message) or
+ other.DESCRIPTOR != self.DESCRIPTOR):
+ return False
+
if self is other:
return True
diff --git a/src/Makefile.am b/src/Makefile.am
index c12d3b9b..9206d094 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,6 +35,7 @@ MAINTAINERCLEANFILES = \
nobase_include_HEADERS = \
google/protobuf/stubs/common.h \
+ google/protobuf/stubs/once.h \
google/protobuf/descriptor.h \
google/protobuf/descriptor.pb.h \
google/protobuf/descriptor_database.h \
@@ -69,6 +70,7 @@ libprotobuf_la_LIBADD = $(PTHREAD_LIBS)
libprotobuf_la_LDFLAGS = -version-info 3:0:0
libprotobuf_la_SOURCES = \
google/protobuf/stubs/common.cc \
+ google/protobuf/stubs/once.cc \
google/protobuf/stubs/hash.cc \
google/protobuf/stubs/hash.h \
google/protobuf/stubs/map-util.cc \
@@ -161,6 +163,7 @@ protoc_SOURCES = google/protobuf/compiler/main.cc
protoc_inputs = \
google/protobuf/unittest.proto \
+ google/protobuf/unittest_empty.proto \
google/protobuf/unittest_import.proto \
google/protobuf/unittest_mset.proto \
google/protobuf/unittest_optimize_for.proto \
@@ -184,6 +187,8 @@ EXTRA_DIST = \
protoc_outputs = \
google/protobuf/unittest.pb.cc \
google/protobuf/unittest.pb.h \
+ google/protobuf/unittest_empty.pb.cc \
+ google/protobuf/unittest_empty.pb.h \
google/protobuf/unittest_import.pb.cc \
google/protobuf/unittest_import.pb.h \
google/protobuf/unittest_mset.pb.cc \
@@ -223,6 +228,7 @@ protobuf_test_CPPFLAGS = -I$(top_srcdir)/gtest/include \
-I$(top_builddir)/gtest/include
protobuf_test_SOURCES = \
google/protobuf/stubs/common_unittest.cc \
+ google/protobuf/stubs/once_unittest.cc \
google/protobuf/stubs/strutil_unittest.cc \
google/protobuf/stubs/structurally_valid_unittest.cc \
google/protobuf/descriptor_database_unittest.cc \
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 77e50332..875cbef8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -100,6 +100,19 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
"const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
"const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"
"\n");
+
+ // The _Name and _Parse methods
+ printer->Print(vars,
+ "inline const ::std::string& $classname$_Name($classname$ value) {\n"
+ " return ::google::protobuf::internal::NameOfEnum(\n"
+ " $classname$_descriptor(), value);\n"
+ "}\n");
+ printer->Print(vars,
+ "inline bool $classname$_Parse(\n"
+ " const ::std::string& name, $classname$* value) {\n"
+ " return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n"
+ " $classname$_descriptor(), name, value);\n"
+ "}\n");
}
void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
@@ -122,6 +135,13 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
"static inline bool $nested_name$_IsValid(int value) {\n"
" return $classname$_IsValid(value);\n"
"}\n"
+ "static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
+ " return $classname$_Name(value);\n"
+ "}\n"
+ "static inline bool $nested_name$_Parse(const ::std::string& name,\n"
+ " $nested_name$* value) {\n"
+ " return $classname$_Parse(name, value);\n"
+ "}\n"
"static const $nested_name$ $nested_name$_MIN =\n"
" $classname$_$nested_name$_MIN;\n"
"static const $nested_name$ $nested_name$_MAX =\n"
@@ -147,12 +167,10 @@ void EnumGenerator::GenerateDescriptorInitializer(
void EnumGenerator::GenerateMethods(io::Printer* printer) {
map<string, string> vars;
vars["classname"] = classname_;
- vars["builddescriptorsname"] =
- GlobalBuildDescriptorsName(descriptor_->file()->name());
printer->Print(vars,
"const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
- " if ($classname$_descriptor_ == NULL) $builddescriptorsname$();\n"
+ " protobuf_AssignDescriptorsOnce();\n"
" return $classname$_descriptor_;\n"
"}\n"
"bool $classname$_IsValid(int value) {\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index a78bf887..b90eb372 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -116,8 +116,8 @@ GenerateSwappingCode(io::Printer* printer) const {
}
void EnumFieldGenerator::
-GenerateInitializer(io::Printer* printer) const {
- printer->Print(variables_, ",\n$name$_($default$)");
+GenerateConstructorCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $default$;\n");
}
void EnumFieldGenerator::
@@ -128,15 +128,22 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"if ($type$_IsValid(value)) {\n"
" set_$name$(static_cast< $type$ >(value));\n"
"} else {\n"
- " mutable_unknown_fields()->AddField($number$)->add_varint(value);\n"
+ " mutable_unknown_fields()->AddVarint($number$, value);\n"
"}\n");
}
void EnumFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
- "DO_(::google::protobuf::internal::WireFormat::WriteEnum("
- "$number$, this->$name$(), output));\n");
+ "::google::protobuf::internal::WireFormat::WriteEnum("
+ "$number$, this->$name$(), output);\n");
+}
+
+void EnumFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+ printer->Print(variables_,
+ "target = ::google::protobuf::internal::WireFormat::WriteEnumToArray("
+ "$number$, this->$name$(), target);\n");
}
void EnumFieldGenerator::
@@ -217,12 +224,8 @@ GenerateSwappingCode(io::Printer* printer) const {
}
void RepeatedEnumFieldGenerator::
-GenerateInitializer(io::Printer* printer) const {
- printer->Print(variables_, ",\n$name$_()");
- if (descriptor_->options().packed() &&
- descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
- printer->Print(variables_, ",\n_$name$_cached_byte_size_()");
- }
+GenerateConstructorCode(io::Printer* printer) const {
+ // Not needed for repeated fields.
}
void RepeatedEnumFieldGenerator::
@@ -248,7 +251,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"if ($type$_IsValid(value)) {\n"
" add_$name$(static_cast< $type$ >(value));\n"
"} else {\n"
- " mutable_unknown_fields()->AddField($number$)->add_varint(value);\n"
+ " mutable_unknown_fields()->AddVarint($number$, value);\n"
"}\n");
}
}
@@ -259,22 +262,51 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
// Write the tag and the size.
printer->Print(variables_,
"if (this->$name$_size() > 0) {\n"
- " DO_(::google::protobuf::internal::WireFormat::WriteTag("
- "$number$, ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED,"
- "output));\n"
- " DO_(output->WriteVarint32(_$name$_cached_byte_size_));\n"
+ " ::google::protobuf::internal::WireFormat::WriteTag("
+ "$number$, "
+ "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
+ "output);\n"
+ " output->WriteVarint32(_$name$_cached_byte_size_);\n"
+ "}\n");
+ }
+ printer->Print(variables_,
+ "for (int i = 0; i < this->$name$_size(); i++) {\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ " ::google::protobuf::internal::WireFormat::WriteEnumNoTag("
+ "this->$name$(i), output);\n");
+ } else {
+ printer->Print(variables_,
+ " ::google::protobuf::internal::WireFormat::WriteEnum("
+ "$number$, this->$name$(i), output);\n");
+ }
+ printer->Print("}\n");
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+ if (descriptor_->options().packed()) {
+ // Write the tag and the size.
+ printer->Print(variables_,
+ "if (this->$name$_size() > 0) {\n"
+ " target = ::google::protobuf::internal::WireFormat::WriteTagToArray("
+ "$number$, "
+ "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
+ "target);\n"
+ " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
+ "_$name$_cached_byte_size_, target);\n"
"}\n");
}
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
if (descriptor_->options().packed()) {
printer->Print(variables_,
- " DO_(::google::protobuf::internal::WireFormat::WriteEnumNoTag("
- "this->$name$(i), output));\n");
+ " target = ::google::protobuf::internal::WireFormat::WriteEnumNoTagToArray("
+ "this->$name$(i), target);\n");
} else {
printer->Print(variables_,
- " DO_(::google::protobuf::internal::WireFormat::WriteEnum("
- "$number$, this->$name$(i), output));\n");
+ " target = ::google::protobuf::internal::WireFormat::WriteEnumToArray("
+ "$number$, this->$name$(i), target);\n");
}
printer->Print("}\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index f67b7ac0..20dd57bb 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -56,9 +56,10 @@ class EnumFieldGenerator : public FieldGenerator {
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
- void GenerateInitializer(io::Printer* printer) const;
+ void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+ void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
private:
@@ -80,9 +81,10 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
- void GenerateInitializer(io::Printer* printer) const;
+ void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+ void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
private:
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc
index 3f212b93..61ebda73 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc
@@ -36,6 +36,7 @@
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
namespace google {
namespace protobuf {
@@ -55,7 +56,9 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
case FieldDescriptor::CPPTYPE_ENUM:
type_traits_.append("EnumTypeTraits< ");
type_traits_.append(ClassName(descriptor_->enum_type(), true));
- type_traits_.append(" >");
+ type_traits_.append(", ");
+ type_traits_.append(ClassName(descriptor_->enum_type(), true));
+ type_traits_.append("_IsValid>");
break;
case FieldDescriptor::CPPTYPE_STRING:
type_traits_.append("StringTypeTraits");
@@ -81,6 +84,8 @@ void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
vars["number" ] = SimpleItoa(descriptor_->number());
vars["type_traits" ] = type_traits_;
vars["name" ] = descriptor_->name();
+ vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
+ vars["packed" ] = descriptor_->options().packed() ? "true" : "false";
vars["constant_name"] = FieldConstantName(descriptor_);
// If this is a class member, it needs to be declared "static". Otherwise,
@@ -95,19 +100,39 @@ void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
printer->Print(vars,
"static const int $constant_name$ = $number$;\n"
"$qualifier$ ::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
- " ::google::protobuf::internal::$type_traits$ > $name$;\n");
+ " ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
+ " $name$;\n"
+ );
}
void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
+ // If this is a class member, it needs to be declared in its class scope.
+ string scope = (descriptor_->extension_scope() == NULL) ? "" :
+ ClassName(descriptor_->extension_scope(), false) + "::";
+ string name = scope + descriptor_->name();
+
map<string, string> vars;
vars["extendee" ] = ClassName(descriptor_->containing_type(), true);
vars["type_traits" ] = type_traits_;
- vars["name" ] = descriptor_->name();
+ vars["name" ] = name;
vars["constant_name"] = FieldConstantName(descriptor_);
-
- // If this is a class member, it needs to be declared in its class scope.
- vars["scope"] = (descriptor_->extension_scope() == NULL) ? "" :
- ClassName(descriptor_->extension_scope(), false) + "::";
+ vars["default" ] = DefaultValue(descriptor_);
+ vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
+ vars["packed" ] = descriptor_->options().packed() ? "true" : "false";
+ vars["scope" ] = scope;
+
+ if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ // We need to declare a global string which will contain the default value.
+ // We cannot declare it at class scope because that would require exposing
+ // it in the header which would be annoying for other reasons. So we
+ // replace :: with _ in the name and declare it as a global.
+ string global_name = StringReplace(name, "::", "_", true);
+ vars["global_name"] = global_name;
+ printer->Print(vars,
+ "const ::std::string $global_name$_default($default$);\n");
+ // Update the default to refer to the string global.
+ vars["default"] = global_name + "_default";
+ }
// Likewise, class members need to declare the field constant variable.
if (descriptor_->extension_scope() != NULL) {
@@ -119,8 +144,46 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
printer->Print(vars,
"::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n"
- " ::google::protobuf::internal::$type_traits$ > $scope$$name$("
- "$constant_name$);\n");
+ " ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n"
+ " $name$($constant_name$, $default$);\n");
+}
+
+void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
+ map<string, string> vars;
+ vars["extendee" ] = ClassName(descriptor_->containing_type(), true);
+ vars["number" ] = SimpleItoa(descriptor_->number());
+ vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));
+ vars["is_repeated"] = descriptor_->is_repeated() ? "true" : "false";
+ vars["is_packed" ] = (descriptor_->is_repeated() &&
+ descriptor_->options().packed())
+ ? "true" : "false";
+
+ switch (descriptor_->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_ENUM:
+ printer->Print(vars,
+ "::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n"
+ " &$extendee$::default_instance(),\n"
+ " $number$, $field_type$, $is_repeated$, $is_packed$,\n");
+ printer->Print(
+ " &$type$_IsValid);\n",
+ "type", ClassName(descriptor_->enum_type(), true));
+ break;
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ printer->Print(vars,
+ "::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n"
+ " &$extendee$::default_instance(),\n"
+ " $number$, $field_type$, $is_repeated$, $is_packed$,\n");
+ printer->Print(
+ " &$type$::default_instance());\n",
+ "type", ClassName(descriptor_->message_type(), true));
+ break;
+ default:
+ printer->Print(vars,
+ "::google::protobuf::internal::ExtensionSet::RegisterExtension(\n"
+ " &$extendee$::default_instance(),\n"
+ " $number$, $field_type$, $is_repeated$, $is_packed$);\n");
+ break;
+ }
}
} // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.h b/src/google/protobuf/compiler/cpp/cpp_extension.h
index a9e58c18..3068b091 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.h
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.h
@@ -66,6 +66,9 @@ class ExtensionGenerator {
// Source file stuff.
void GenerateDefinition(io::Printer* printer);
+ // Generate code to register the extension.
+ void GenerateRegistration(io::Printer* printer);
+
private:
const FieldDescriptor* descriptor_;
string type_traits_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index e5f8258f..7e7c7f83 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -94,16 +94,13 @@ class FieldGenerator {
// message.cc under the GenerateSwap method.
virtual void GenerateSwappingCode(io::Printer* printer) const = 0;
- // Generate any initializers needed for the private members declared by
- // GeneratePrivateMembers(). These go into the message class's
- // constructor's initializer list. For each initializer, this method
- // must print the comma and newline separating it from the *previous*
- // initializer, not the *next* initailizer. That is, print a ",\n" first,
- // e.g.:
- // printer->Print(",\n$name$_($default$)");
- virtual void GenerateInitializer(io::Printer* printer) const = 0;
-
- // Generate any code that needs to go in the class's destructor.
+ // Generate initialization code for private members declared by
+ // GeneratePrivateMembers(). These go into the message class's SharedCtor()
+ // method, invoked by each of the generated constructors.
+ virtual void GenerateConstructorCode(io::Printer* printer) const = 0;
+
+ // Generate any code that needs to go in the class's SharedDtor() method,
+ // invoked by the destructor.
// Most field types don't need this, so the default implementation is empty.
virtual void GenerateDestructorCode(io::Printer* printer) const {}
@@ -115,6 +112,12 @@ class FieldGenerator {
// message's SerializeWithCachedSizes() method.
virtual void GenerateSerializeWithCachedSizes(io::Printer* printer) const = 0;
+ // Generate lines to serialize this field directly to the array "target",
+ // which are placed within the message's SerializeWithCachedSizesToArray()
+ // method. This must also advance "target" past the written bytes.
+ virtual void GenerateSerializeWithCachedSizesToArray(
+ io::Printer* printer) const = 0;
+
// Generate lines to compute the serialized size of this field, which
// are placed in the message's ByteSize() method.
virtual void GenerateByteSize(io::Printer* printer) const = 0;
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 6487979f..dcc48552 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -143,17 +143,20 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
// Open namespace.
GenerateNamespaceOpeners(printer);
- // Forward-declare the AssignGlobalDescriptors function, so that we can
- // declare it to be a friend of each class.
+ // Forward-declare the AddDescriptors and AssignDescriptors functions, so
+ // that we can declare them to be friends of each class.
printer->Print(
"\n"
"// Internal implementation detail -- do not call these.\n"
- "void $dllexport_decl$ $builddescriptorsname$();\n"
- "void $builddescriptorsname$_AssignGlobalDescriptors(\n"
- " ::google::protobuf::FileDescriptor* file);\n"
- "\n",
- "builddescriptorsname", GlobalBuildDescriptorsName(file_->name()),
+ "void $dllexport_decl$ $adddescriptorsname$();\n",
+ "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
"dllexport_decl", dllexport_decl_);
+ printer->Print(
+ // Note that we don't put dllexport_decl on this because it is only called
+ // by the .pb.cc file in which it is defined.
+ "void $assigndescriptorsname$();\n"
+ "\n",
+ "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
// Generate forward declarations of classes.
for (int i = 0; i < file_->message_type_count(); i++) {
@@ -232,6 +235,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
"\n"
"#include \"$basename$.pb.h\"\n"
+ "#include <google/protobuf/stubs/once.h>\n"
"#include <google/protobuf/descriptor.h>\n"
"#include <google/protobuf/io/coded_stream.h>\n"
"#include <google/protobuf/reflection_ops.h>\n"
@@ -296,23 +300,46 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
}
void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
- // BuildDescriptors() is a file-level procedure which initializes all of
- // the Descriptor objects for this file. It runs the first time one of the
- // descriptors is accessed. This will always be at static initialization
- // time, because every message has a statically-initialized default instance,
- // and the constructor for a message class accesses its descriptor. See the
- // constructor and the descriptor() method of message classes.
+ // AddDescriptors() is a file-level procedure which adds the encoded
+ // FileDescriptorProto for this .proto file to the global DescriptorPool
+ // for generated files (DescriptorPool::generated_pool()). It always runs
+ // at static initialization time, so all files will be registered before
+ // main() starts. This procedure also constructs default instances and
+ // registers extensions.
//
- // We also construct the reflection object for each class inside
- // BuildDescriptors().
+ // Its sibling, AssignDescriptors(), actually pulls the compiled
+ // FileDescriptor from the DescriptorPool and uses it to populate all of
+ // the global variables which store pointers to the descriptor objects.
+ // It also constructs the reflection objects. It is called the first time
+ // anyone calls descriptor() or GetReflection() on one of the types defined
+ // in the file.
- // First we generate a method to assign the global descriptors.
printer->Print(
"\n"
- "void $builddescriptorsname$_AssignGlobalDescriptors("
- "const ::google::protobuf::FileDescriptor* file) {\n",
- "builddescriptorsname", GlobalBuildDescriptorsName(file_->name()));
+ "void $assigndescriptorsname$() {\n",
+ "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
printer->Indent();
+
+ // Make sure the file has found its way into the pool. If a descriptor
+ // is requested *during* static init then AddDescriptors() may not have
+ // been called yet, so we call it manually. Note that it's fine if
+ // AddDescriptors() is called multiple times.
+ printer->Print(
+ "$adddescriptorsname$();\n",
+ "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
+
+ // Get the file's descriptor from the pool.
+ printer->Print(
+ "const ::google::protobuf::FileDescriptor* file =\n"
+ " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
+ " \"$filename$\");\n"
+ // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
+ // being unused when compiling an empty .proto file.
+ "GOOGLE_CHECK(file != NULL);\n",
+ "filename", file_->name());
+
+ // Go through all the stuff defined in this file and generated code to
+ // assign the global descriptor pointers based on the file descriptor.
for (int i = 0; i < file_->message_type_count(); i++) {
message_generators_[i]->GenerateDescriptorInitializer(printer, i);
}
@@ -322,29 +349,63 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
for (int i = 0; i < file_->service_count(); i++) {
service_generators_[i]->GenerateDescriptorInitializer(printer, i);
}
+
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+
+ // -----------------------------------------------------------------
+
+ // protobuf_AssignDescriptorsOnce(): The first time it is called, calls
+ // AssignDescriptors(). All later times, waits for the first call to
+ // complete and then returns.
+ printer->Print(
+ "namespace {\n"
+ "\n"
+ "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
+ "inline void protobuf_AssignDescriptorsOnce() {\n"
+ " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
+ " &$assigndescriptorsname$);\n"
+ "}\n"
+ "\n",
+ "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
+
+ // protobuf_RegisterTypes(): Calls
+ // MessageFactory::InternalRegisterGeneratedType() for each message type.
+ printer->Print(
+ "void protobuf_RegisterTypes() {\n"
+ " protobuf_AssignDescriptorsOnce();\n");
+ printer->Indent();
+
for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
+ message_generators_[i]->GenerateTypeRegistrations(printer);
}
printer->Outdent();
printer->Print(
- "}\n");
+ "}\n"
+ "\n"
+ "} // namespace\n");
+ // -----------------------------------------------------------------
+
+ // Now generate the AddDescriptors() function.
printer->Print(
"\n"
- "void $builddescriptorsname$() {\n"
+ "void $adddescriptorsname$() {\n"
+ // We don't need any special synchronization here because this code is
+ // called at static init time before any threads exist.
" static bool already_here = false;\n"
" if (already_here) return;\n"
" already_here = true;\n"
" GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
- " ::google::protobuf::DescriptorPool* pool =\n"
- " ::google::protobuf::DescriptorPool::internal_generated_pool();\n"
"\n",
- "builddescriptorsname", GlobalBuildDescriptorsName(file_->name()));
+ "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
printer->Indent();
- // Call the BuildDescriptors() methods for all of our dependencies, to make
- // sure they get initialized first.
+ // Call the AddDescriptors() methods for all of our dependencies, to make
+ // sure they get added first.
for (int i = 0; i < file_->dependency_count(); i++) {
const FileDescriptor* dependency = file_->dependency(i);
// Print the namespace prefix for the dependency.
@@ -355,10 +416,10 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
printer->Print("$name$::",
"name", dependency_package_parts[i]);
}
- // Call its BuildDescriptors function.
+ // Call its AddDescriptors function.
printer->Print(
"$name$();\n",
- "name", GlobalBuildDescriptorsName(dependency->name()));
+ "name", GlobalAddDescriptorsName(dependency->name()));
}
// Embed the descriptor. We simply serialize the entire FileDescriptorProto
@@ -370,7 +431,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
file_proto.SerializeToString(&file_data);
printer->Print(
- "pool->InternalBuildGeneratedFile(");
+ "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
// Only write 40 bytes per line.
static const int kBytesPerLine = 40;
@@ -379,24 +440,41 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
"data", CEscape(file_data.substr(i, kBytesPerLine)));
}
printer->Print(
- ", $size$,\n"
- "&$builddescriptorsname$_AssignGlobalDescriptors);\n",
- "size", SimpleItoa(file_data.size()),
- "builddescriptorsname", GlobalBuildDescriptorsName(file_->name()));
+ ", $size$);\n",
+ "size", SimpleItoa(file_data.size()));
+
+ // Call MessageFactory::InternalRegisterGeneratedFile().
+ printer->Print(
+ "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
+ " \"$filename$\", &protobuf_RegisterTypes);\n",
+ "filename", file_->name());
+
+ // Allocate and initialize default instances. This can't be done lazily
+ // since default instances are returned by simple accessors and are used with
+ // extensions. Speaking of which, we also register extensions at this time.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
+ }
+ for (int i = 0; i < file_->extension_count(); i++) {
+ extension_generators_[i]->GenerateRegistration(printer);
+ }
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
+ }
printer->Outdent();
printer->Print(
"}\n"
"\n"
- "// Force BuildDescriptors() to be called at static initialization time.\n"
+ "// Force AddDescriptors() to be called at static initialization time.\n"
"struct StaticDescriptorInitializer_$filename$ {\n"
" StaticDescriptorInitializer_$filename$() {\n"
- " $builddescriptorsname$();\n"
+ " $adddescriptorsname$();\n"
" }\n"
"} static_descriptor_initializer_$filename$_;\n"
"\n",
- "builddescriptorsname", GlobalBuildDescriptorsName(file_->name()),
+ "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
"filename", FilenameIdentifier(file_->name()));
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index d536bea4..214daff9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
namespace google {
namespace protobuf {
@@ -213,6 +214,41 @@ const char* DeclaredTypeMethodName(FieldDescriptor::Type type) {
return "";
}
+string DefaultValue(const FieldDescriptor* field) {
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ return SimpleItoa(field->default_value_int32());
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return SimpleItoa(field->default_value_uint32()) + "u";
+ case FieldDescriptor::CPPTYPE_INT64:
+ 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_FLOAT:
+ return SimpleFtoa(field->default_value_float());
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return field->default_value_bool() ? "true" : "false";
+ case FieldDescriptor::CPPTYPE_ENUM:
+ // Lazy: Generate a static_cast because we don't have a helper function
+ // that constructs the full name of an enum value.
+ return strings::Substitute(
+ "static_cast< $0 >($1)",
+ ClassName(field->enum_type(), true),
+ field->default_value_enum()->number());
+ case FieldDescriptor::CPPTYPE_STRING:
+ return "\"" + CEscape(field->default_value_string()) + "\"";
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return ClassName(field->message_type(), true) + "::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
+ // new type is added.)
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return "";
+}
+
// Convert a file name into a valid identifier.
string FilenameIdentifier(const string& filename) {
string result;
@@ -230,9 +266,14 @@ string FilenameIdentifier(const string& filename) {
return result;
}
-// Return the name of the BuildDescriptors() function for a given file.
-string GlobalBuildDescriptorsName(const string& filename) {
- return "protobuf_BuildDesc_" + FilenameIdentifier(filename);
+// Return the name of the AddDescriptors() function for a given file.
+string GlobalAddDescriptorsName(const string& filename) {
+ return "protobuf_AddDesc_" + FilenameIdentifier(filename);
+}
+
+// Return the name of the AssignDescriptors() function for a given file.
+string GlobalAssignDescriptorsName(const string& filename) {
+ return "protobuf_AssignDesc_" + FilenameIdentifier(filename);
}
} // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 30c6e7d0..2260a934 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -90,11 +90,17 @@ const char* PrimitiveTypeName(FieldDescriptor::CppType type);
// methods of WireFormat. For example, TYPE_INT32 becomes "Int32".
const char* DeclaredTypeMethodName(FieldDescriptor::Type type);
+// Get code that evaluates to the field's default value.
+string DefaultValue(const FieldDescriptor* field);
+
// Convert a file name into a valid identifier.
string FilenameIdentifier(const string& filename);
-// Return the name of the BuildDescriptors() function for a given file.
-string GlobalBuildDescriptorsName(const string& filename);
+// Return the name of the AddDescriptors() function for a given file.
+string GlobalAddDescriptorsName(const string& filename);
+
+// Return the name of the AssignDescriptors() function for a given file.
+string GlobalAssignDescriptorsName(const string& filename);
} // namespace cpp
} // namespace compiler
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 2ec49234..44546bd0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -223,104 +223,10 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
}
if (descriptor_->extension_range_count() > 0) {
- // Generate accessors for extensions.
-
- // Normally I'd generate prototypes here and generate the actual
- // definitions of these methods in GenerateFieldAccessorDefinitions, but
- // the prototypes for these silly methods are so absurdly complicated that
- // it meant way too much repitition.
- //
- // We use "_proto_TypeTraits" as a type name below because "TypeTraits"
- // causes problems if the class has a nested message or enum type with that
- // name and "_TypeTraits" is technically reserved for the C++ library since
- // it starts with an underscore followed by a capital letter.
+ // Generate accessors for extensions. We just call a macro located in
+ // extension_set.h since the accessors about 80 lines of static code.
printer->Print(
- // Has, Size, Clear
- "template <typename _proto_TypeTraits>\n"
- "inline bool HasExtension(\n"
- " const ::google::protobuf::internal::ExtensionIdentifier<\n"
- " $classname$, _proto_TypeTraits>& id) const {\n"
- " return _extensions_.Has(id.number());\n"
- "}\n"
- "\n"
- "template <typename _proto_TypeTraits>\n"
- "inline void ClearExtension(\n"
- " const ::google::protobuf::internal::ExtensionIdentifier<\n"
- " $classname$, _proto_TypeTraits>& id) {\n"
- " _extensions_.ClearExtension(id.number());\n"
- "}\n"
- "\n"
- "template <typename _proto_TypeTraits>\n"
- "inline int ExtensionSize(\n"
- " const ::google::protobuf::internal::ExtensionIdentifier<\n"
- " $classname$, _proto_TypeTraits>& id) const {\n"
- " return _extensions_.ExtensionSize(id.number());\n"
- "}\n"
- "\n"
-
- // Singular accessors
- "template <typename _proto_TypeTraits>\n"
- "inline typename _proto_TypeTraits::ConstType GetExtension(\n"
- " const ::google::protobuf::internal::ExtensionIdentifier<\n"
- " $classname$, _proto_TypeTraits>& id) const {\n"
- " return _proto_TypeTraits::Get(id.number(), _extensions_);\n"
- "}\n"
- "\n"
- "template <typename _proto_TypeTraits>\n"
- "inline typename _proto_TypeTraits::MutableType MutableExtension(\n"
- " const ::google::protobuf::internal::ExtensionIdentifier<\n"
- " $classname$, _proto_TypeTraits>& id) {\n"
- " return _proto_TypeTraits::Mutable(id.number(), &_extensions_);\n"
- "}\n"
- "\n"
- "template <typename _proto_TypeTraits>\n"
- "inline void SetExtension(\n"
- " const ::google::protobuf::internal::ExtensionIdentifier<\n"
- " $classname$, _proto_TypeTraits>& id,\n"
- " typename _proto_TypeTraits::ConstType value) {\n"
- " _proto_TypeTraits::Set(id.number(), value, &_extensions_);\n"
- "}\n"
- "\n"
-
- // Repeated accessors
- "template <typename _proto_TypeTraits>\n"
- "inline typename _proto_TypeTraits::ConstType GetExtension(\n"
- " const ::google::protobuf::internal::ExtensionIdentifier<\n"
- " $classname$, _proto_TypeTraits>& id,\n"
- " int index) const {\n"
- " return _proto_TypeTraits::Get(id.number(), _extensions_, index);\n"
- "}\n"
- "\n"
- "template <typename _proto_TypeTraits>\n"
- "inline typename _proto_TypeTraits::MutableType MutableExtension(\n"
- " const ::google::protobuf::internal::ExtensionIdentifier<\n"
- " $classname$, _proto_TypeTraits>& id,\n"
- " int index) {\n"
- " return _proto_TypeTraits::Mutable(id.number(),index,&_extensions_);\n"
- "}\n"
- "\n"
- "template <typename _proto_TypeTraits>\n"
- "inline void SetExtension(\n"
- " const ::google::protobuf::internal::ExtensionIdentifier<\n"
- " $classname$, _proto_TypeTraits>& id,\n"
- " int index, typename _proto_TypeTraits::ConstType value) {\n"
- " _proto_TypeTraits::Set(id.number(), index, value, &_extensions_);\n"
- "}\n"
- "\n"
- "template <typename _proto_TypeTraits>\n"
- "inline typename _proto_TypeTraits::MutableType AddExtension(\n"
- " const ::google::protobuf::internal::ExtensionIdentifier<\n"
- " $classname$, _proto_TypeTraits>& id) {\n"
- " return _proto_TypeTraits::Add(id.number(), &_extensions_);\n"
- "}\n"
- "\n"
- "template <typename _proto_TypeTraits>\n"
- "inline void AddExtension(\n"
- " const ::google::protobuf::internal::ExtensionIdentifier<\n"
- " $classname$, _proto_TypeTraits>& id,\n"
- " typename _proto_TypeTraits::ConstType value) {\n"
- " _proto_TypeTraits::Add(id.number(), value, &_extensions_);\n"
- "}\n",
+ "GOOGLE_PROTOBUF_EXTENSION_ACCESSORS($classname$)\n",
"classname", classname_);
}
}
@@ -391,8 +297,6 @@ GenerateClassDefinition(io::Printer* printer) {
} else {
vars["dllexport"] = dllexport_decl_ + " ";
}
- vars["builddescriptorsname"] =
- GlobalBuildDescriptorsName(descriptor_->file()->name());
printer->Print(vars,
"class $dllexport$$classname$ : public ::google::protobuf::Message {\n"
@@ -433,18 +337,30 @@ GenerateClassDefinition(io::Printer* printer) {
"void CopyFrom(const $classname$& from);\n"
"void MergeFrom(const $classname$& from);\n"
"void Clear();\n"
- "bool IsInitialized() const;\n"
- "int ByteSize() const;\n"
- "\n"
- "bool MergePartialFromCodedStream(\n"
- " ::google::protobuf::io::CodedInputStream* input);\n"
- "bool SerializeWithCachedSizes(\n"
- " ::google::protobuf::io::CodedOutputStream* output) const;\n");
+ "bool IsInitialized() const;\n");
+
+ if (!descriptor_->options().message_set_wire_format()) {
+ // For message_set_wire_format, we don't generate parsing or
+ // serialization code even if optimize_for = SPEED, since MessageSet
+ // encoding is somewhat more complicated than normal extension encoding
+ // and we'd like to avoid having to implement it in multiple places.
+ // WireFormat's implementation is probably good enough.
+ printer->Print(vars,
+ "\n"
+ "int ByteSize() const;\n"
+ "bool MergePartialFromCodedStream(\n"
+ " ::google::protobuf::io::CodedInputStream* input);\n"
+ "void SerializeWithCachedSizes(\n"
+ " ::google::protobuf::io::CodedOutputStream* output) const;\n"
+ "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n");
+ }
}
printer->Print(vars,
"int GetCachedSize() const { return _cached_size_; }\n"
"private:\n"
+ "void SharedCtor();\n"
+ "void SharedDtor();\n"
"void SetCachedSize(int size) const { _cached_size_ = size; }\n"
"public:\n"
"\n"
@@ -505,11 +421,17 @@ GenerateClassDefinition(io::Printer* printer) {
.GeneratePrivateMembers(printer);
}
- // Generate offsets and _has_bits_ boilerplate.
- printer->Print(vars,
- "friend void $builddescriptorsname$_AssignGlobalDescriptors(\n"
- " const ::google::protobuf::FileDescriptor* file);\n");
+ // Declare AddDescriptors() and BuildDescriptors() as friends so that they
+ // can assign private static variables like default_instance_ and reflection_.
+ printer->Print(
+ "friend void $adddescriptorsname$();\n"
+ "friend void $assigndescriptorsname$();\n",
+ "adddescriptorsname",
+ GlobalAddDescriptorsName(descriptor_->file()->name()),
+ "assigndescriptorsname",
+ GlobalAssignDescriptorsName(descriptor_->file()->name()));
+ // Generate offsets and _has_bits_ boilerplate.
if (descriptor_->field_count() > 0) {
printer->Print(vars,
"::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\n");
@@ -592,12 +514,6 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
"$parent$_descriptor_->nested_type($index$);\n");
}
- // Construct the default instance. We can't call InitAsDefaultInstance() yet
- // because we need to make sure all default instances that this one might
- // depend on are constructed first.
- printer->Print(vars,
- "$classname$::default_instance_ = new $classname$();\n");
-
// Generate the offsets.
GenerateOffsets(printer);
@@ -622,6 +538,7 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
}
printer->Print(vars,
" ::google::protobuf::DescriptorPool::generated_pool(),\n"
+ " ::google::protobuf::MessageFactory::generated_factory(),\n"
" sizeof($classname$));\n");
// Handle nested types.
@@ -632,11 +549,35 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
}
+}
+void MessageGenerator::
+GenerateTypeRegistrations(io::Printer* printer) {
// Register this message type with the message factory.
- printer->Print(vars,
+ printer->Print(
"::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
- " $classname$_descriptor_, $classname$::default_instance_);\n");
+ " $classname$_descriptor_, &$classname$::default_instance());\n",
+ "classname", classname_);
+
+ // Handle nested types.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ nested_generators_[i]->GenerateTypeRegistrations(printer);
+ }
+}
+
+void MessageGenerator::
+GenerateDefaultInstanceAllocator(io::Printer* printer) {
+ // Construct the default instance. We can't call InitAsDefaultInstance() yet
+ // because we need to make sure all default instances that this one might
+ // depend on are constructed first.
+ printer->Print(
+ "$classname$::default_instance_ = new $classname$();\n",
+ "classname", classname_);
+
+ // Handle nested types.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ nested_generators_[i]->GenerateDefaultInstanceAllocator(printer);
+ }
}
void MessageGenerator::
@@ -645,6 +586,11 @@ GenerateDefaultInstanceInitializer(io::Printer* printer) {
"$classname$::default_instance_->InitAsDefaultInstance();\n",
"classname", classname_);
+ // Register extensions.
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ extension_generators_[i]->GenerateRegistration(printer);
+ }
+
// Handle nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
nested_generators_[i]->GenerateDefaultInstanceInitializer(printer);
@@ -695,14 +641,24 @@ GenerateClassMethods(io::Printer* printer) {
GenerateClear(printer);
printer->Print("\n");
- GenerateMergeFromCodedStream(printer);
- printer->Print("\n");
+ if (!descriptor_->options().message_set_wire_format()) {
+ // For message_set_wire_format, we don't generate parsing or
+ // serialization code even if optimize_for = SPEED, since MessageSet
+ // encoding is somewhat more complicated than normal extension encoding
+ // and we'd like to avoid having to implement it in multiple places.
+ // WireFormat's implementation is probably good enough.
+ GenerateMergeFromCodedStream(printer);
+ printer->Print("\n");
- GenerateSerializeWithCachedSizes(printer);
- printer->Print("\n");
+ GenerateSerializeWithCachedSizes(printer);
+ printer->Print("\n");
- GenerateByteSize(printer);
- printer->Print("\n");
+ GenerateSerializeWithCachedSizesToArray(printer);
+ printer->Print("\n");
+
+ GenerateByteSize(printer);
+ printer->Print("\n");
+ }
GenerateMergeFrom(printer);
printer->Print("\n");
@@ -723,12 +679,10 @@ GenerateClassMethods(io::Printer* printer) {
"}\n"
"\n"
"const ::google::protobuf::Reflection* $classname$::GetReflection() const {\n"
- " if ($classname$_reflection_ == NULL) $builddescriptorsname$();\n"
+ " protobuf_AssignDescriptorsOnce();\n"
" return $classname$_reflection_;\n"
"}\n",
- "classname", classname_,
- "builddescriptorsname",
- GlobalBuildDescriptorsName(descriptor_->file()->name()));
+ "classname", classname_);
}
void MessageGenerator::
@@ -757,28 +711,68 @@ GenerateInitializerList(io::Printer* printer) {
printer->Indent();
printer->Print(
- "::google::protobuf::Message(),\n");
+ "::google::protobuf::Message()");
- if (descriptor_->extension_range_count() > 0) {
- printer->Print(
- "_extensions_(&$classname$_descriptor_,\n"
- " ::google::protobuf::DescriptorPool::generated_pool(),\n"
- " ::google::protobuf::MessageFactory::generated_factory()),\n",
- "classname", classname_);
- }
+ printer->Outdent();
+ printer->Outdent();
+}
+
+void MessageGenerator::
+GenerateSharedConstructorCode(io::Printer* printer) {
+ printer->Print(
+ "void $classname$::SharedCtor() {\n",
+ "classname", classname_);
+ printer->Indent();
printer->Print(
- "_unknown_fields_(),\n"
- "_cached_size_(0)");
+ "_cached_size_ = 0;\n");
- // Write the initializers for each field.
for (int i = 0; i < descriptor_->field_count(); i++) {
field_generators_.get(descriptor_->field(i))
- .GenerateInitializer(printer);
+ .GenerateConstructorCode(printer);
}
+ printer->Print(
+ "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
+
printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+void MessageGenerator::
+GenerateSharedDestructorCode(io::Printer* printer) {
+ printer->Print(
+ "void $classname$::SharedDtor() {\n",
+ "classname", classname_);
+ printer->Indent();
+ // Write the destructors for each field.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateDestructorCode(printer);
+ }
+
+ printer->Print(
+ "if (this != default_instance_) {\n");
+
+ // We need to delete all embedded messages.
+ // TODO(kenton): If we make unset messages point at default instances
+ // instead of NULL, then it would make sense to move this code into
+ // MessageFieldGenerator::GenerateDestructorCode().
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+
+ if (!field->is_repeated() &&
+ field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer->Print(" delete $name$_;\n",
+ "name", FieldName(field));
+ }
+ }
+
printer->Outdent();
+ printer->Print(
+ " }\n"
+ "}\n"
+ "\n");
}
void MessageGenerator::
@@ -790,7 +784,7 @@ GenerateStructors(io::Printer* printer) {
"classname", classname_);
GenerateInitializerList(printer);
printer->Print(" {\n"
- " ::memset(_has_bits_, 0, sizeof(_has_bits_));\n"
+ " SharedCtor();\n"
"}\n");
printer->Print(
@@ -826,54 +820,33 @@ GenerateStructors(io::Printer* printer) {
"classname", classname_);
GenerateInitializerList(printer);
printer->Print(" {\n"
- " ::memset(_has_bits_, 0, sizeof(_has_bits_));\n"
+ " SharedCtor();\n"
" MergeFrom(from);\n"
"}\n"
"\n");
+ // Generate the shared constructor code.
+ GenerateSharedConstructorCode(printer);
+
// Generate the destructor.
printer->Print(
- "$classname$::~$classname$() {\n",
+ "$classname$::~$classname$() {\n"
+ " SharedDtor();\n"
+ "}\n"
+ "\n",
"classname", classname_);
- printer->Indent();
-
- // Write the destructors for each field.
- for (int i = 0; i < descriptor_->field_count(); i++) {
- field_generators_.get(descriptor_->field(i))
- .GenerateDestructorCode(printer);
- }
+ // Generate the shared destructor code.
+ GenerateSharedDestructorCode(printer);
printer->Print(
- "if (this != default_instance_) {\n");
-
- // We need to delete all embedded messages.
- // TODO(kenton): If we make unset messages point at default instances
- // instead of NULL, then it would make sense to move this code into
- // MessageFieldGenerator::GenerateDestructorCode().
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const FieldDescriptor* field = descriptor_->field(i);
-
- if (!field->is_repeated() &&
- field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- printer->Print(" delete $name$_;\n",
- "name", FieldName(field));
- }
- }
-
- printer->Outdent();
-
- printer->Print(
- " }\n"
- "}\n"
- "\n"
"const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
- " if ($classname$_descriptor_ == NULL) $builddescriptorsname$();\n"
+ " protobuf_AssignDescriptorsOnce();\n"
" return $classname$_descriptor_;\n"
"}\n"
"\n"
"const $classname$& $classname$::default_instance() {\n"
- " if (default_instance_ == NULL) $builddescriptorsname$();\n"
+ " if (default_instance_ == NULL) $adddescriptorsname$();"
" return *default_instance_;\n"
"}\n"
"\n"
@@ -883,8 +856,8 @@ GenerateStructors(io::Printer* printer) {
" return new $classname$;\n"
"}\n",
"classname", classname_,
- "builddescriptorsname",
- GlobalBuildDescriptorsName(descriptor_->file()->name()));
+ "adddescriptorsname",
+ GlobalAddDescriptorsName(descriptor_->file()->name()));
}
void MessageGenerator::
@@ -1127,24 +1100,6 @@ GenerateCopyFrom(io::Printer* printer) {
void MessageGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) {
- if (descriptor_->options().message_set_wire_format()) {
- // For message_set_wire_format, we don't generate a parser, for two
- // reasons:
- // - WireFormat already needs to special-case this, and we'd like to
- // avoid having multiple implementations of MessageSet wire format
- // lying around the code base.
- // - All fields are extensions, and extension parsing falls back to
- // reflection anyway, so it wouldn't be any faster.
- printer->Print(
- "bool $classname$::MergePartialFromCodedStream(\n"
- " ::google::protobuf::io::CodedInputStream* input) {\n"
- " return ::google::protobuf::internal::WireFormat::ParseAndMergePartial(\n"
- " input, this);\n"
- "}\n",
- "classname", classname_);
- return;
- }
-
printer->Print(
"bool $classname$::MergePartialFromCodedStream(\n"
" ::google::protobuf::io::CodedInputStream* input) {\n"
@@ -1267,7 +1222,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
}
}
printer->Print(") {\n"
- " DO_(_extensions_.ParseField(tag, input, this));\n"
+ " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
+ " mutable_unknown_fields()));\n"
" continue;\n"
"}\n");
}
@@ -1295,7 +1251,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
}
void MessageGenerator::GenerateSerializeOneField(
- io::Printer* printer, const FieldDescriptor* field) {
+ io::Printer* printer, const FieldDescriptor* field, bool to_array) {
PrintFieldComment(printer, field);
if (!field->is_repeated()) {
@@ -1305,7 +1261,12 @@ void MessageGenerator::GenerateSerializeOneField(
printer->Indent();
}
- field_generators_.get(field).GenerateSerializeWithCachedSizes(printer);
+ if (to_array) {
+ field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(
+ printer);
+ } else {
+ field_generators_.get(field).GenerateSerializeWithCachedSizes(printer);
+ }
if (!field->is_repeated()) {
printer->Outdent();
@@ -1315,25 +1276,66 @@ void MessageGenerator::GenerateSerializeOneField(
}
void MessageGenerator::GenerateSerializeOneExtensionRange(
- io::Printer* printer, const Descriptor::ExtensionRange* range) {
+ io::Printer* printer, const Descriptor::ExtensionRange* range,
+ bool to_array) {
map<string, string> vars;
vars["start"] = SimpleItoa(range->start);
vars["end"] = SimpleItoa(range->end);
printer->Print(vars,
- "// Extension range [$start$, $end$)\n"
- "DO_(_extensions_.SerializeWithCachedSizes(\n"
- " $start$, $end$, *this, output));\n\n");
+ "// Extension range [$start$, $end$)\n");
+ if (to_array) {
+ printer->Print(vars,
+ "target = _extensions_.SerializeWithCachedSizesToArray(\n"
+ " $start$, $end$, target);\n\n");
+ } else {
+ printer->Print(vars,
+ "_extensions_.SerializeWithCachedSizes(\n"
+ " $start$, $end$, output);\n\n");
+ }
}
void MessageGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) {
printer->Print(
- "bool $classname$::SerializeWithCachedSizes(\n"
- " ::google::protobuf::io::CodedOutputStream* output) const {\n"
- "#define DO_(EXPRESSION) if (!(EXPRESSION)) return false\n",
+ "void $classname$::SerializeWithCachedSizes(\n"
+ " ::google::protobuf::io::CodedOutputStream* output) const {\n",
+ "classname", classname_);
+ printer->Indent();
+
+ printer->Print(
+ "::google::protobuf::uint8* raw_buffer = "
+ "output->GetDirectBufferForNBytesAndAdvance(_cached_size_);\n"
+ "if (raw_buffer != NULL) {\n"
+ " $classname$::SerializeWithCachedSizesToArray(raw_buffer);\n"
+ " return;\n"
+ "}\n"
+ "\n",
+ "classname", classname_);
+ GenerateSerializeWithCachedSizesBody(printer, false);
+
+ printer->Outdent();
+ printer->Print(
+ "}\n");
+}
+
+void MessageGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) {
+ printer->Print(
+ "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
+ " ::google::protobuf::uint8* target) const {\n",
"classname", classname_);
printer->Indent();
+ GenerateSerializeWithCachedSizesBody(printer, true);
+
+ printer->Outdent();
+ printer->Print(
+ " return target;\n"
+ "}\n");
+}
+
+void MessageGenerator::
+GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
scoped_array<const FieldDescriptor*> ordered_fields(
SortFieldsByNumber(descriptor_));
@@ -1350,35 +1352,35 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) {
i < descriptor_->field_count() || j < sorted_extensions.size();
) {
if (i == descriptor_->field_count()) {
- GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+ GenerateSerializeOneExtensionRange(printer,
+ sorted_extensions[j++],
+ to_array);
} else if (j == sorted_extensions.size()) {
- GenerateSerializeOneField(printer, ordered_fields[i++]);
+ GenerateSerializeOneField(printer, ordered_fields[i++], to_array);
} else if (ordered_fields[i]->number() < sorted_extensions[j]->start) {
- GenerateSerializeOneField(printer, ordered_fields[i++]);
+ GenerateSerializeOneField(printer, ordered_fields[i++], to_array);
} else {
- GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+ GenerateSerializeOneExtensionRange(printer,
+ sorted_extensions[j++],
+ to_array);
}
}
printer->Print("if (!unknown_fields().empty()) {\n");
printer->Indent();
- if (descriptor_->options().message_set_wire_format()) {
+ if (to_array) {
printer->Print(
- "DO_(::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n"
- " unknown_fields(), output));\n");
+ "target = "
+ "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
+ " unknown_fields(), target);\n");
} else {
printer->Print(
- "DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
- " unknown_fields(), output));\n");
+ "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
+ " unknown_fields(), output);\n");
}
printer->Outdent();
- printer->Print(
- "}\n"
- "return true;\n");
- printer->Outdent();
printer->Print(
- "#undef DO_\n"
"}\n");
}
@@ -1449,23 +1451,16 @@ GenerateByteSize(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) {
printer->Print(
- "total_size += _extensions_.ByteSize(*this);\n"
+ "total_size += _extensions_.ByteSize();\n"
"\n");
}
printer->Print("if (!unknown_fields().empty()) {\n");
printer->Indent();
- if (descriptor_->options().message_set_wire_format()) {
- printer->Print(
- "total_size +=\n"
- " ::google::protobuf::internal::WireFormat::ComputeUnknownMessageSetItemsSize(\n"
- " unknown_fields());\n");
- } else {
- printer->Print(
- "total_size +=\n"
- " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
- " unknown_fields());\n");
- }
+ printer->Print(
+ "total_size +=\n"
+ " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
+ " unknown_fields());\n");
printer->Outdent();
printer->Print("}\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index d6669a34..31aa1c4c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -86,7 +86,16 @@ class MessageGenerator {
// descriptor.
void GenerateDescriptorInitializer(io::Printer* printer, int index);
- // Generates code that initializes the message's default instance.
+ // Generate code that calls MessageFactory::InternalRegisterGeneratedMessage()
+ // for all types.
+ void GenerateTypeRegistrations(io::Printer* printer);
+
+ // Generates code that allocates the message's default instance.
+ void GenerateDefaultInstanceAllocator(io::Printer* printer);
+
+ // Generates code that initializes the message's default instance. This
+ // is separate from allocating because all default instances must be
+ // allocated before any can be initialized.
void GenerateDefaultInstanceInitializer(io::Printer* printer);
// Generate all non-inline methods for this class.
@@ -103,6 +112,15 @@ class MessageGenerator {
// Generate constructors and destructor.
void GenerateStructors(io::Printer* printer);
+ // The compiler typically generates multiple copies of each constructor and
+ // destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx
+ // Placing common code in a separate method reduces the generated code size.
+ //
+ // Generate the shared constructor code.
+ void GenerateSharedConstructorCode(io::Printer* printer);
+ // Generate the shared destructor code.
+ void GenerateSharedDestructorCode(io::Printer* printer);
+
// Generate the member initializer list for the constructors. The member
// initializer list is shared between the default constructor and the copy
// constructor.
@@ -112,6 +130,9 @@ class MessageGenerator {
void GenerateClear(io::Printer* printer);
void GenerateMergeFromCodedStream(io::Printer* printer);
void GenerateSerializeWithCachedSizes(io::Printer* printer);
+ void GenerateSerializeWithCachedSizesToArray(io::Printer* printer);
+ void GenerateSerializeWithCachedSizesBody(io::Printer* printer,
+ bool to_array);
void GenerateByteSize(io::Printer* printer);
void GenerateMergeFrom(io::Printer* printer);
void GenerateCopyFrom(io::Printer* printer);
@@ -120,9 +141,11 @@ class MessageGenerator {
// Helpers for GenerateSerializeWithCachedSizes().
void GenerateSerializeOneField(io::Printer* printer,
- const FieldDescriptor* field);
+ const FieldDescriptor* field,
+ bool unbounded);
void GenerateSerializeOneExtensionRange(
- io::Printer* printer, const Descriptor::ExtensionRange* range);
+ io::Printer* printer, const Descriptor::ExtensionRange* range,
+ bool unbounded);
const Descriptor* descriptor_;
string classname_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index e2d2370b..2a7eb3f8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -116,8 +116,8 @@ GenerateSwappingCode(io::Printer* printer) const {
}
void MessageFieldGenerator::
-GenerateInitializer(io::Printer* printer) const {
- printer->Print(variables_, ",\n$name$_(NULL)");
+GenerateConstructorCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = NULL;\n");
}
void MessageFieldGenerator::
@@ -136,8 +136,16 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
void MessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
- "DO_(::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual("
- "$number$, this->$name$(), output));\n");
+ "::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual("
+ "$number$, this->$name$(), output);\n");
+}
+
+void MessageFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+ printer->Print(variables_,
+ "target = ::google::protobuf::internal::WireFormat::"
+ "Write$declared_type$NoVirtualToArray("
+ "$number$, this->$name$(), target);\n");
}
void MessageFieldGenerator::
@@ -212,8 +220,8 @@ GenerateSwappingCode(io::Printer* printer) const {
}
void RepeatedMessageFieldGenerator::
-GenerateInitializer(io::Printer* printer) const {
- printer->Print(variables_, ",\n$name$_()");
+GenerateConstructorCode(io::Printer* printer) const {
+ // Not needed for repeated fields.
}
void RepeatedMessageFieldGenerator::
@@ -233,8 +241,18 @@ void RepeatedMessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n"
- " DO_(::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual("
- "$number$, this->$name$(i), output));\n"
+ " ::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual("
+ "$number$, this->$name$(i), output);\n"
+ "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+ printer->Print(variables_,
+ "for (int i = 0; i < this->$name$_size(); i++) {\n"
+ " target = ::google::protobuf::internal::WireFormat::"
+ "Write$declared_type$NoVirtualToArray("
+ "$number$, this->$name$(i), target);\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h
index 7ce4c32b..f5147278 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -56,9 +56,10 @@ class MessageFieldGenerator : public FieldGenerator {
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
- void GenerateInitializer(io::Printer* printer) const;
+ void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+ void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
private:
@@ -80,9 +81,10 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
- void GenerateInitializer(io::Printer* printer) const;
+ void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+ void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
private:
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 57244c5d..44d0b97c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -79,35 +79,6 @@ int FixedSize(FieldDescriptor::Type type) {
return -1;
}
-string DefaultValue(const FieldDescriptor* field) {
- switch (field->cpp_type()) {
- case FieldDescriptor::CPPTYPE_INT32:
- return SimpleItoa(field->default_value_int32());
- case FieldDescriptor::CPPTYPE_UINT32:
- return SimpleItoa(field->default_value_uint32()) + "u";
- case FieldDescriptor::CPPTYPE_INT64:
- 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_FLOAT:
- return SimpleFtoa(field->default_value_float());
- case FieldDescriptor::CPPTYPE_BOOL:
- return field->default_value_bool() ? "true" : "false";
-
- case FieldDescriptor::CPPTYPE_ENUM:
- case FieldDescriptor::CPPTYPE_STRING:
- case FieldDescriptor::CPPTYPE_MESSAGE:
- GOOGLE_LOG(FATAL) << "Shouldn't get here.";
- return "";
- }
- // 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
- // new type is added.)
- return "";
-}
-
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
// repeat code between this and the other field types.
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
@@ -180,8 +151,8 @@ GenerateSwappingCode(io::Printer* printer) const {
}
void PrimitiveFieldGenerator::
-GenerateInitializer(io::Printer* printer) const {
- printer->Print(variables_, ",\n$name$_($default$)");
+GenerateConstructorCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $default$;\n");
}
void PrimitiveFieldGenerator::
@@ -195,8 +166,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
void PrimitiveFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
- "DO_(::google::protobuf::internal::WireFormat::Write$declared_type$("
- "$number$, this->$name$(), output));\n");
+ "::google::protobuf::internal::WireFormat::Write$declared_type$("
+ "$number$, this->$name$(), output);\n");
+}
+
+void PrimitiveFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+ printer->Print(variables_,
+ "target = ::google::protobuf::internal::WireFormat::Write$declared_type$ToArray("
+ "$number$, this->$name$(), target);\n");
}
void PrimitiveFieldGenerator::
@@ -282,12 +260,8 @@ GenerateSwappingCode(io::Printer* printer) const {
}
void RepeatedPrimitiveFieldGenerator::
-GenerateInitializer(io::Printer* printer) const {
- printer->Print(variables_, ",\n$name$_()");
- if (descriptor_->options().packed() &&
- descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
- printer->Print(variables_, ",\n_$name$_cached_byte_size_()");
- }
+GenerateConstructorCode(io::Printer* printer) const {
+ // Not needed for repeated fields.
}
void RepeatedPrimitiveFieldGenerator::
@@ -324,22 +298,53 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
// Write the tag and the size.
printer->Print(variables_,
"if (this->$name$_size() > 0) {\n"
- " DO_(::google::protobuf::internal::WireFormat::WriteTag("
- "$number$, ::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED,"
- "output));\n"
- " DO_(output->WriteVarint32(_$name$_cached_byte_size_));\n"
+ " ::google::protobuf::internal::WireFormat::WriteTag("
+ "$number$, "
+ "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
+ "output);\n"
+ " output->WriteVarint32(_$name$_cached_byte_size_);\n"
+ "}\n");
+ }
+ printer->Print(variables_,
+ "for (int i = 0; i < this->$name$_size(); i++) {\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ " ::google::protobuf::internal::WireFormat::Write$declared_type$NoTag("
+ "this->$name$(i), output);\n");
+ } else {
+ printer->Print(variables_,
+ " ::google::protobuf::internal::WireFormat::Write$declared_type$("
+ "$number$, this->$name$(i), output);\n");
+ }
+ printer->Print("}\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+ if (descriptor_->options().packed()) {
+ // Write the tag and the size.
+ printer->Print(variables_,
+ "if (this->$name$_size() > 0) {\n"
+ " target = ::google::protobuf::internal::WireFormat::WriteTagToArray("
+ "$number$, "
+ "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
+ "target);\n"
+ " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
+ "_$name$_cached_byte_size_, target);\n"
"}\n");
}
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
if (descriptor_->options().packed()) {
printer->Print(variables_,
- " DO_(::google::protobuf::internal::WireFormat::Write$declared_type$NoTag("
- "this->$name$(i), output));\n");
+ " target = ::google::protobuf::internal::WireFormat::"
+ "Write$declared_type$NoTagToArray("
+ "this->$name$(i), target);\n");
} else {
printer->Print(variables_,
- " DO_(::google::protobuf::internal::WireFormat::Write$declared_type$("
- "$number$, this->$name$(i), output));\n");
+ " target = ::google::protobuf::internal::WireFormat::"
+ "Write$declared_type$ToArray("
+ "$number$, this->$name$(i), target);\n");
}
printer->Print("}\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index c7f7f310..6b96614c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -56,9 +56,10 @@ class PrimitiveFieldGenerator : public FieldGenerator {
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
- void GenerateInitializer(io::Printer* printer) const;
+ void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+ void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
private:
@@ -80,9 +81,10 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
- void GenerateInitializer(io::Printer* printer) const;
+ void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+ void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
private:
diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc
index 59dbac1f..7689fa13 100644
--- a/src/google/protobuf/compiler/cpp/cpp_service.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_service.cc
@@ -176,10 +176,12 @@ void ServiceGenerator::GenerateImplementation(io::Printer* printer) {
"$classname$::~$classname$() {}\n"
"\n"
"const ::google::protobuf::ServiceDescriptor* $classname$::descriptor() {\n"
+ " protobuf_AssignDescriptorsOnce();\n"
" return $classname$_descriptor_;\n"
"}\n"
"\n"
"const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() {\n"
+ " protobuf_AssignDescriptorsOnce();\n"
" return $classname$_descriptor_;\n"
"}\n"
"\n");
@@ -279,7 +281,7 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
printer->Print(vars_,
" const ::google::protobuf::MethodDescriptor* method) const {\n"
- " GOOGLE_DCHECK_EQ(method->service(), $classname$_descriptor_);\n"
+ " GOOGLE_DCHECK_EQ(method->service(), descriptor());\n"
" switch(method->index()) {\n");
for (int i = 0; i < descriptor_->method_count(); i++) {
@@ -320,7 +322,7 @@ void ServiceGenerator::GenerateStubMethods(io::Printer* printer) {
" const $input_type$* request,\n"
" $output_type$* response,\n"
" ::google::protobuf::Closure* done) {\n"
- " channel_->CallMethod($classname$_descriptor_->method($index$),\n"
+ " channel_->CallMethod(descriptor()->method($index$),\n"
" controller, request, response, done);\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 8e10e9b0..05858da4 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -61,6 +61,8 @@ void SetStringVariables(const FieldDescriptor* descriptor,
(*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
(*variables)["tag_size"] = SimpleItoa(
WireFormat::TagSize(descriptor->number(), descriptor->type()));
+ (*variables)["pointer_type"] =
+ descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
}
} // namespace
@@ -111,13 +113,8 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
"inline const ::std::string& $name$() const;\n"
"inline void set_$name$(const ::std::string& value);\n"
- "inline void set_$name$(const char* value);\n");
- if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) {
- printer->Print(variables_,
- "inline void set_$name$(const void* value, size_t size);\n");
- }
-
- printer->Print(variables_,
+ "inline void set_$name$(const char* value);\n"
+ "inline void set_$name$(const $pointer_type$* value, size_t size);\n"
"inline ::std::string* mutable_$name$();\n");
if (descriptor_->options().has_ctype()) {
@@ -146,20 +143,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $name$_ = new ::std::string;\n"
" }\n"
" $name$_->assign(value);\n"
- "}\n");
-
- if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) {
- printer->Print(variables_,
- "inline void $classname$::set_$name$(const void* value, size_t size) {\n"
- " _set_bit($index$);\n"
- " if ($name$_ == &_default_$name$_) {\n"
- " $name$_ = new ::std::string;\n"
- " }\n"
- " $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
- "}\n");
- }
-
- printer->Print(variables_,
+ "}\n"
+ "inline "
+ "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
+ " _set_bit($index$);\n"
+ " if ($name$_ == &_default_$name$_) {\n"
+ " $name$_ = new ::std::string;\n"
+ " }\n"
+ " $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
+ "}\n"
"inline ::std::string* $classname$::mutable_$name$() {\n"
" _set_bit($index$);\n"
" if ($name$_ == &_default_$name$_) {\n");
@@ -213,9 +205,9 @@ GenerateSwappingCode(io::Printer* printer) const {
}
void StringFieldGenerator::
-GenerateInitializer(io::Printer* printer) const {
+GenerateConstructorCode(io::Printer* printer) const {
printer->Print(variables_,
- ",\n$name$_(const_cast< ::std::string*>(&_default_$name$_))");
+ "$name$_ = const_cast< ::std::string*>(&_default_$name$_);\n");
}
void StringFieldGenerator::
@@ -236,8 +228,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
void StringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
- "DO_(::google::protobuf::internal::WireFormat::Write$declared_type$("
- "$number$, this->$name$(), output));\n");
+ "::google::protobuf::internal::WireFormat::Write$declared_type$("
+ "$number$, this->$name$(), output);\n");
+}
+
+void StringFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+ printer->Print(variables_,
+ "target = ::google::protobuf::internal::WireFormat::Write$declared_type$ToArray("
+ "$number$, this->$name$(), target);\n");
}
void StringFieldGenerator::
@@ -281,15 +280,12 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"inline ::std::string* mutable_$name$(int index);\n"
"inline void set_$name$(int index, const ::std::string& value);\n"
"inline void set_$name$(int index, const char* value);\n"
+ "inline "
+ "void set_$name$(int index, const $pointer_type$* value, size_t size);\n"
"inline ::std::string* add_$name$();\n"
"inline void add_$name$(const ::std::string& value);\n"
- "inline void add_$name$(const char* value);\n");
-
- if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) {
- printer->Print(variables_,
- "inline void set_$name$(int index, const void* value, size_t size);\n"
- "inline void add_$name$(const void* value, size_t size);\n");
- }
+ "inline void add_$name$(const char* value);\n"
+ "inline void add_$name$(const $pointer_type$* value, size_t size);\n");
if (descriptor_->options().has_ctype()) {
printer->Outdent();
@@ -321,6 +317,12 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"inline void $classname$::set_$name$(int index, const char* value) {\n"
" $name$_.Mutable(index)->assign(value);\n"
"}\n"
+ "inline void "
+ "$classname$::set_$name$"
+ "(int index, const $pointer_type$* value, size_t size) {\n"
+ " $name$_.Mutable(index)->assign(\n"
+ " reinterpret_cast<const char*>(value), size);\n"
+ "}\n"
"inline ::std::string* $classname$::add_$name$() {\n"
" return $name$_.Add();\n"
"}\n"
@@ -329,19 +331,11 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"}\n"
"inline void $classname$::add_$name$(const char* value) {\n"
" $name$_.Add()->assign(value);\n"
+ "}\n"
+ "inline void "
+ "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
+ " $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
"}\n");
-
- if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) {
- printer->Print(variables_,
- "inline void "
- "$classname$::set_$name$(int index, const void* value, size_t size) {\n"
- " $name$_.Mutable(index)->assign(\n"
- " reinterpret_cast<const char*>(value), size);\n"
- "}\n"
- "inline void $classname$::add_$name$(const void* value, size_t size) {\n"
- " $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
- "}\n");
- }
}
void RepeatedStringFieldGenerator::
@@ -360,8 +354,8 @@ GenerateSwappingCode(io::Printer* printer) const {
}
void RepeatedStringFieldGenerator::
-GenerateInitializer(io::Printer* printer) const {
- printer->Print(variables_, ",\n$name$_()");
+GenerateConstructorCode(io::Printer* printer) const {
+ // Not needed for repeated fields.
}
void RepeatedStringFieldGenerator::
@@ -375,8 +369,18 @@ void RepeatedStringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n"
- " DO_(::google::protobuf::internal::WireFormat::Write$declared_type$("
- "$number$, this->$name$(i), output));\n"
+ " ::google::protobuf::internal::WireFormat::Write$declared_type$("
+ "$number$, this->$name$(i), output);\n"
+ "}\n");
+}
+
+void RepeatedStringFieldGenerator::
+GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
+ printer->Print(variables_,
+ "for (int i = 0; i < this->$name$_size(); i++) {\n"
+ " target = ::google::protobuf::internal::WireFormat::"
+ "Write$declared_type$ToArray("
+ "$number$, this->$name$(i), target);\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index 2244bd77..7f45107d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -57,10 +57,11 @@ class StringFieldGenerator : public FieldGenerator {
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
- void GenerateInitializer(io::Printer* printer) const;
+ void GenerateConstructorCode(io::Printer* printer) const;
void GenerateDestructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+ void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
private:
@@ -82,9 +83,10 @@ class RepeatedStringFieldGenerator : public FieldGenerator {
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
- void GenerateInitializer(io::Printer* printer) const;
+ void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
+ void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
private:
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index c7e4ee3d..ea9cc32d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -52,6 +52,8 @@
#include <google/protobuf/test_util.h>
#include <google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h>
#include <google/protobuf/compiler/importer.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/dynamic_message.h>
@@ -61,6 +63,7 @@
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util-inl.h>
namespace google {
namespace protobuf {
@@ -86,6 +89,8 @@ class MockErrorCollector : public MultiFileErrorCollector {
}
};
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
// Test that generated code has proper descriptors:
// Parse a descriptor directly (using google::protobuf::compiler::Importer) and
// compare it to the one that was produced by generated code.
@@ -115,6 +120,8 @@ TEST(GeneratedDescriptorTest, IdenticalDescriptors) {
generated_decsriptor_proto.DebugString());
}
+#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
+
// ===================================================================
TEST(GeneratedMessageTest, Defaults) {
@@ -222,6 +229,22 @@ TEST(GeneratedMessageTest, ClearOneField) {
TestUtil::ExpectAllFieldsSet(message);
}
+TEST(GeneratedMessageTest, StringCharStarLength) {
+ // Verify that we can use a char*,length to set one of the string fields.
+ unittest::TestAllTypes message;
+ message.set_optional_string("abcdef", 3);
+ EXPECT_EQ("abc", message.optional_string());
+
+ // Verify that we can use a char*,length to add to a repeated string field.
+ message.add_repeated_string("abcdef", 3);
+ EXPECT_EQ(1, message.repeated_string_size());
+ EXPECT_EQ("abc", message.repeated_string(0));
+
+ // Verify that we can use a char*,length to set a repeated string field.
+ message.set_repeated_string(0, "wxyz", 2);
+ EXPECT_EQ("wx", message.repeated_string(0));
+}
+
TEST(GeneratedMessageTest, CopyFrom) {
unittest::TestAllTypes message1, message2;
@@ -346,6 +369,8 @@ TEST(GeneratedMessageTest, UpcastCopyFrom) {
TestUtil::ExpectAllFieldsSet(message2);
}
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
TEST(GeneratedMessageTest, DynamicMessageCopyFrom) {
// Test copying from a DynamicMessage, which must fall back to using
// reflection.
@@ -366,6 +391,8 @@ TEST(GeneratedMessageTest, DynamicMessageCopyFrom) {
TestUtil::ExpectAllFieldsSet(message2);
}
+#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
+
TEST(GeneratedMessageTest, NonEmptyMergeFrom) {
// Test merging with a non-empty message. Code is a modified form
// of that found in google/protobuf/reflection_ops_unittest.cc.
@@ -403,24 +430,75 @@ TEST(GeneratedMessageTest, MergeFromSelf) {
#endif // GTEST_HAS_DEATH_TEST
-TEST(GeneratedMessageTest, Serialization) {
+// Test the generated SerializeWithCachedSizesToArray(),
+TEST(GeneratedMessageTest, SerializationToArray) {
unittest::TestAllTypes message1, message2;
string data;
-
TestUtil::SetAllFields(&message1);
- message1.SerializeToString(&data);
+ int size = message1.ByteSize();
+ data.resize(size);
+ uint8* start = reinterpret_cast<uint8*>(string_as_array(&data));
+ uint8* end =
+ message1.TestAllTypes::SerializeWithCachedSizesToArray(start);
+ EXPECT_EQ(size, end - start);
EXPECT_TRUE(message2.ParseFromString(data));
TestUtil::ExpectAllFieldsSet(message2);
+}
+TEST(GeneratedMessageTest, PackedFieldsSerializationToArray) {
unittest::TestPackedTypes packed_message1, packed_message2;
string packed_data;
TestUtil::SetPackedFields(&packed_message1);
- packed_message1.SerializeToString(&packed_data);
+ int packed_size = packed_message1.ByteSize();
+ packed_data.resize(packed_size);
+ uint8* start = reinterpret_cast<uint8*>(string_as_array(&packed_data));
+ uint8* end =
+ packed_message1.TestPackedTypes::SerializeWithCachedSizesToArray(start);
+ EXPECT_EQ(packed_size, end - start);
EXPECT_TRUE(packed_message2.ParseFromString(packed_data));
TestUtil::ExpectPackedFieldsSet(packed_message2);
}
+// Test the generated SerializeWithCachedSizes() by forcing the buffer to write
+// one byte at a time.
+TEST(GeneratedMessageTest, SerializationToStream) {
+ unittest::TestAllTypes message1, message2;
+ TestUtil::SetAllFields(&message1);
+ int size = message1.ByteSize();
+ string data;
+ data.resize(size);
+ {
+ // Allow the output stream to buffer only one byte at a time.
+ io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+ io::CodedOutputStream output_stream(&array_stream);
+ message1.TestAllTypes::SerializeWithCachedSizes(&output_stream);
+ EXPECT_FALSE(output_stream.HadError());
+ EXPECT_EQ(size, output_stream.ByteCount());
+ }
+ EXPECT_TRUE(message2.ParseFromString(data));
+ TestUtil::ExpectAllFieldsSet(message2);
+
+}
+
+TEST(GeneratedMessageTest, PackedFieldsSerializationToStream) {
+ unittest::TestPackedTypes message1, message2;
+ TestUtil::SetPackedFields(&message1);
+ int size = message1.ByteSize();
+ string data;
+ data.resize(size);
+ {
+ // Allow the output stream to buffer only one byte at a time.
+ io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+ io::CodedOutputStream output_stream(&array_stream);
+ message1.TestPackedTypes::SerializeWithCachedSizes(&output_stream);
+ EXPECT_FALSE(output_stream.HadError());
+ EXPECT_EQ(size, output_stream.ByteCount());
+ }
+ EXPECT_TRUE(message2.ParseFromString(data));
+ TestUtil::ExpectPackedFieldsSet(message2);
+}
+
TEST(GeneratedMessageTest, Required) {
// Test that IsInitialized() returns false if required fields are missing.
@@ -547,6 +625,8 @@ TEST(GeneratedMessageTest, TestConflictingSymbolNames) {
EXPECT_EQ(5, message.friend_());
}
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
TEST(GeneratedMessageTest, TestOptimizedForSize) {
// We rely on the tests in reflection_ops_unittest and wire_format_unittest
// to really test that reflection-based methods work. Here we are mostly
@@ -614,6 +694,8 @@ TEST(GeneratedMessageTest, TestSpaceUsed) {
message1.SpaceUsed());
}
+#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
+
// ===================================================================
TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) {
@@ -682,8 +764,37 @@ TEST(GeneratedEnumTest, MinAndMax) {
}
}
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
+TEST(GeneratedEnumTest, Name) {
+ // "Names" in the presence of dup values are a bit arbitrary.
+ EXPECT_EQ("FOO1", unittest::TestEnumWithDupValue_Name(unittest::FOO1));
+ EXPECT_EQ("FOO1", unittest::TestEnumWithDupValue_Name(unittest::FOO2));
+
+ EXPECT_EQ("SPARSE_A", unittest::TestSparseEnum_Name(unittest::SPARSE_A));
+ EXPECT_EQ("SPARSE_B", unittest::TestSparseEnum_Name(unittest::SPARSE_B));
+ EXPECT_EQ("SPARSE_C", unittest::TestSparseEnum_Name(unittest::SPARSE_C));
+ EXPECT_EQ("SPARSE_D", unittest::TestSparseEnum_Name(unittest::SPARSE_D));
+ EXPECT_EQ("SPARSE_E", unittest::TestSparseEnum_Name(unittest::SPARSE_E));
+ EXPECT_EQ("SPARSE_F", unittest::TestSparseEnum_Name(unittest::SPARSE_F));
+ EXPECT_EQ("SPARSE_G", unittest::TestSparseEnum_Name(unittest::SPARSE_G));
+}
+
+TEST(GeneratedEnumTest, Parse) {
+ unittest::TestEnumWithDupValue dup_value = unittest::FOO1;
+ EXPECT_TRUE(unittest::TestEnumWithDupValue_Parse("FOO1", &dup_value));
+ EXPECT_EQ(unittest::FOO1, dup_value);
+ EXPECT_TRUE(unittest::TestEnumWithDupValue_Parse("FOO2", &dup_value));
+ EXPECT_EQ(unittest::FOO2, dup_value);
+ EXPECT_FALSE(unittest::TestEnumWithDupValue_Parse("FOO", &dup_value));
+}
+
+#endif // PROTOBUF_TEST_NO_DESCRIPTORS
+
// ===================================================================
+#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
+
// Support code for testing services.
class GeneratedServiceTest : public testing::Test {
protected:
@@ -977,6 +1088,27 @@ TEST_F(GeneratedServiceTest, NotImplemented) {
EXPECT_TRUE(controller.called_);
}
+#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
+
+// ===================================================================
+
+// This test must run last. It verifies that descriptors were or were not
+// initialized depending on whether PROTOBUF_TEST_NO_DESCRIPTORS was defined.
+// When this is defined, we skip all tests which are expected to trigger
+// descriptor initialization. This verifies that everything else still works
+// if descriptors are not initialized.
+TEST(DescriptorInitializationTest, Initialized) {
+#ifdef PROTOBUF_TEST_NO_DESCRIPTORS
+ bool should_have_descriptors = false;
+#else
+ bool should_have_descriptors = true;
+#endif
+
+ EXPECT_EQ(should_have_descriptors,
+ DescriptorPool::generated_pool()->InternalIsFileLoaded(
+ "google/protobuf/unittest.proto"));
+}
+
} // namespace cpp_unittest
} // namespace cpp
diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc
index 30e106e8..8a07dfc4 100644
--- a/src/google/protobuf/compiler/importer.cc
+++ b/src/google/protobuf/compiler/importer.cc
@@ -387,9 +387,22 @@ DiskSourceTree::DiskFileToVirtualFile(
return SUCCESS;
}
+bool DiskSourceTree::VirtualFileToDiskFile(const string& virtual_file,
+ string* disk_file) {
+ scoped_ptr<io::ZeroCopyInputStream> stream(OpenVirtualFile(virtual_file,
+ disk_file));
+ return stream != NULL;
+}
+
io::ZeroCopyInputStream* DiskSourceTree::Open(const string& filename) {
- if (filename != CanonicalizePath(filename) ||
- ContainsParentReference(filename)) {
+ return OpenVirtualFile(filename, NULL);
+}
+
+io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile(
+ const string& virtual_file,
+ string* disk_file) {
+ if (virtual_file != CanonicalizePath(virtual_file) ||
+ ContainsParentReference(virtual_file)) {
// We do not allow importing of paths containing things like ".." or
// consecutive slashes since the compiler expects files to be uniquely
// identified by file name.
@@ -397,16 +410,21 @@ io::ZeroCopyInputStream* DiskSourceTree::Open(const string& filename) {
}
for (int i = 0; i < mappings_.size(); i++) {
- string disk_file;
- if (ApplyMapping(filename, mappings_[i].virtual_path,
- mappings_[i].disk_path, &disk_file)) {
- io::ZeroCopyInputStream* stream = OpenDiskFile(disk_file);
- if (stream != NULL) return stream;
+ string temp_disk_file;
+ if (ApplyMapping(virtual_file, mappings_[i].virtual_path,
+ mappings_[i].disk_path, &temp_disk_file)) {
+ io::ZeroCopyInputStream* stream = OpenDiskFile(temp_disk_file);
+ if (stream != NULL) {
+ if (disk_file != NULL) {
+ *disk_file = temp_disk_file;
+ }
+ return stream;
+ }
if (errno == EACCES) {
// The file exists but is not readable.
// TODO(kenton): Find a way to report this more nicely.
- GOOGLE_LOG(WARNING) << "Read access is denied for file: " << disk_file;
+ GOOGLE_LOG(WARNING) << "Read access is denied for file: " << temp_disk_file;
return NULL;
}
}
diff --git a/src/google/protobuf/compiler/importer.h b/src/google/protobuf/compiler/importer.h
index e2177e1c..7a2efc29 100644
--- a/src/google/protobuf/compiler/importer.h
+++ b/src/google/protobuf/compiler/importer.h
@@ -267,6 +267,11 @@ class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree {
string* virtual_file,
string* shadowing_disk_file);
+ // Given a virtual path, find the path to the file on disk.
+ // Return true and update disk_file with the on-disk path if the file exists.
+ // Return false and leave disk_file untouched if the file doesn't exist.
+ bool VirtualFileToDiskFile(const string& virtual_file, string* disk_file);
+
// implements SourceTree -------------------------------------------
io::ZeroCopyInputStream* Open(const string& filename);
@@ -280,6 +285,11 @@ class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree {
};
vector<Mapping> mappings_;
+ // Like Open(), but returns the on-disk path in disk_file if disk_file is
+ // non-NULL and the file could be successfully opened.
+ io::ZeroCopyInputStream* OpenVirtualFile(const string& virtual_file,
+ string* disk_file);
+
// Like Open() but given the actual on-disk path.
io::ZeroCopyInputStream* OpenDiskFile(const string& filename);
diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc
index 51aeb90c..56fad56e 100644
--- a/src/google/protobuf/compiler/importer_unittest.cc
+++ b/src/google/protobuf/compiler/importer_unittest.cc
@@ -565,6 +565,34 @@ TEST_F(DiskSourceTreeTest, DiskFileToVirtualFileCanonicalization) {
EXPECT_EQ("dir5/bar", virtual_file);
}
+TEST_F(DiskSourceTreeTest, VirtualFileToDiskFile) {
+ // Test VirtualFileToDiskFile.
+
+ AddFile(dirnames_[0] + "/foo", "Hello World!");
+ AddFile(dirnames_[1] + "/foo", "This file should be hidden.");
+ AddFile(dirnames_[1] + "/quux", "This file should not be hidden.");
+ source_tree_.MapPath("bar", dirnames_[0]);
+ source_tree_.MapPath("bar", dirnames_[1]);
+
+ // Existent files, shadowed and non-shadowed case.
+ string disk_file;
+ EXPECT_TRUE(source_tree_.VirtualFileToDiskFile("bar/foo", &disk_file));
+ EXPECT_EQ(dirnames_[0] + "/foo", disk_file);
+ EXPECT_TRUE(source_tree_.VirtualFileToDiskFile("bar/quux", &disk_file));
+ EXPECT_EQ(dirnames_[1] + "/quux", disk_file);
+
+ // Nonexistent file in existent directory and vice versa.
+ string not_touched = "not touched";
+ EXPECT_FALSE(source_tree_.VirtualFileToDiskFile("bar/baz", &not_touched));
+ EXPECT_EQ("not touched", not_touched);
+ EXPECT_FALSE(source_tree_.VirtualFileToDiskFile("baz/foo", &not_touched));
+ EXPECT_EQ("not touched", not_touched);
+
+ // Accept NULL as output parameter.
+ EXPECT_TRUE(source_tree_.VirtualFileToDiskFile("bar/foo", NULL));
+ EXPECT_FALSE(source_tree_.VirtualFileToDiskFile("baz/foo", NULL));
+}
+
} // namespace
} // namespace compiler
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index c2e0c115..c9cbd13f 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -466,6 +466,17 @@ GenerateParseFromMethods(io::Printer* printer) {
" return newBuilder().mergeFrom(input, extensionRegistry)\n"
" .buildParsed();\n"
"}\n"
+ "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
+ " throws java.io.IOException {\n"
+ " return newBuilder().mergeDelimitedFrom(input).buildParsed();\n"
+ "}\n"
+ "public static $classname$ parseDelimitedFrom(\n"
+ " java.io.InputStream input,\n"
+ " com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
+ " throws java.io.IOException {\n"
+ " return newBuilder().mergeDelimitedFrom(input, extensionRegistry)\n"
+ " .buildParsed();\n"
+ "}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.CodedInputStream input)\n"
" throws java.io.IOException {\n"
@@ -579,7 +590,8 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
printer->Print(
"public $classname$ build() {\n"
- " if (!isInitialized()) {\n"
+ // If result == null, we'll throw an appropriate exception later.
+ " if (result != null && !isInitialized()) {\n"
" throw new com.google.protobuf.UninitializedMessageException(\n"
" result);\n"
" }\n"
@@ -595,7 +607,11 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
" return buildPartial();\n"
"}\n"
"\n"
- "public $classname$ buildPartial() {\n",
+ "public $classname$ buildPartial() {\n"
+ " if (result == null) {\n"
+ " throw new IllegalStateException(\n"
+ " \"build() has already been called on this Builder.\");"
+ " }\n",
"classname", ClassName(descriptor_));
printer->Indent();
diff --git a/src/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc
index 5308dd20..5545bf7f 100644
--- a/src/google/protobuf/compiler/java/java_service.cc
+++ b/src/google/protobuf/compiler/java/java_service.cc
@@ -57,45 +57,111 @@ void ServiceGenerator::Generate(io::Printer* printer) {
"classname", descriptor_->name());
printer->Indent();
- // Generate abstract method declarations.
- for (int i = 0; i < descriptor_->method_count(); i++) {
- const MethodDescriptor* method = descriptor_->method(i);
- map<string, string> vars;
- vars["name"] = UnderscoresToCamelCase(method);
- vars["input"] = ClassName(method->input_type());
- vars["output"] = ClassName(method->output_type());
- printer->Print(vars,
- "public abstract void $name$(\n"
- " com.google.protobuf.RpcController controller,\n"
- " $input$ request,\n"
- " com.google.protobuf.RpcCallback<$output$> done);\n");
- }
+ printer->Print(
+ "protected $classname$() {}\n\n",
+ "classname", descriptor_->name());
+
+ GenerateInterface(printer);
+
+ GenerateNewReflectiveServiceMethod(printer);
+ GenerateNewReflectiveBlockingServiceMethod(printer);
+
+ GenerateAbstractMethods(printer);
// Generate getDescriptor() and getDescriptorForType().
printer->Print(
- "\n"
"public static final\n"
" com.google.protobuf.Descriptors.ServiceDescriptor\n"
" getDescriptor() {\n"
" return $file$.getDescriptor().getServices().get($index$);\n"
- "}\n"
- "public final com.google.protobuf.Descriptors.ServiceDescriptor\n"
- " getDescriptorForType() {\n"
- " return getDescriptor();\n"
"}\n",
"file", ClassName(descriptor_->file()),
"index", SimpleItoa(descriptor_->index()));
+ GenerateGetDescriptorForType(printer);
// Generate more stuff.
GenerateCallMethod(printer);
GenerateGetPrototype(REQUEST, printer);
GenerateGetPrototype(RESPONSE, printer);
GenerateStub(printer);
+ GenerateBlockingStub(printer);
printer->Outdent();
printer->Print("}\n\n");
}
+void ServiceGenerator::GenerateGetDescriptorForType(io::Printer* printer) {
+ printer->Print(
+ "public final com.google.protobuf.Descriptors.ServiceDescriptor\n"
+ " getDescriptorForType() {\n"
+ " return getDescriptor();\n"
+ "}\n");
+}
+
+void ServiceGenerator::GenerateInterface(io::Printer* printer) {
+ printer->Print("public interface Interface {\n");
+ printer->Indent();
+ GenerateAbstractMethods(printer);
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+void ServiceGenerator::GenerateNewReflectiveServiceMethod(
+ io::Printer* printer) {
+ printer->Print(
+ "public static com.google.protobuf.Service newReflectiveService(\n"
+ " final Interface impl) {\n"
+ " return new $classname$() {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ printer->Print("@Override\n");
+ GenerateMethodSignature(printer, method, IS_CONCRETE);
+ printer->Print(
+ " {\n"
+ " impl.$method$(controller, request, done);\n"
+ "}\n\n",
+ "method", UnderscoresToCamelCase(method));
+ }
+
+ printer->Outdent();
+ printer->Print("};\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+void ServiceGenerator::GenerateNewReflectiveBlockingServiceMethod(
+ io::Printer* printer) {
+ printer->Print(
+ "public static com.google.protobuf.BlockingService\n"
+ " newReflectiveBlockingService(final BlockingInterface impl) {\n"
+ " return new com.google.protobuf.BlockingService() {\n");
+ printer->Indent();
+ printer->Indent();
+
+ GenerateGetDescriptorForType(printer);
+
+ GenerateCallBlockingMethod(printer);
+ GenerateGetPrototype(REQUEST, printer);
+ GenerateGetPrototype(RESPONSE, printer);
+
+ printer->Outdent();
+ printer->Print("};\n");
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+void ServiceGenerator::GenerateAbstractMethods(io::Printer* printer) {
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ GenerateMethodSignature(printer, method, IS_ABSTRACT);
+ printer->Print(";\n\n");
+ }
+}
+
void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
printer->Print(
"\n"
@@ -131,7 +197,49 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
printer->Print(
"default:\n"
- " throw new java.lang.RuntimeException(\"Can't get here.\");\n");
+ " throw new java.lang.AssertionError(\"Can't get here.\");\n");
+
+ printer->Outdent();
+ printer->Outdent();
+
+ printer->Print(
+ " }\n"
+ "}\n"
+ "\n");
+}
+
+void ServiceGenerator::GenerateCallBlockingMethod(io::Printer* printer) {
+ printer->Print(
+ "\n"
+ "public final com.google.protobuf.Message callBlockingMethod(\n"
+ " com.google.protobuf.Descriptors.MethodDescriptor method,\n"
+ " com.google.protobuf.RpcController controller,\n"
+ " com.google.protobuf.Message request)\n"
+ " throws com.google.protobuf.ServiceException {\n"
+ " if (method.getService() != getDescriptor()) {\n"
+ " throw new java.lang.IllegalArgumentException(\n"
+ " \"Service.callBlockingMethod() given method descriptor for \" +\n"
+ " \"wrong service type.\");\n"
+ " }\n"
+ " switch(method.getIndex()) {\n");
+ printer->Indent();
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ map<string, string> vars;
+ vars["index"] = SimpleItoa(i);
+ vars["method"] = UnderscoresToCamelCase(method);
+ vars["input"] = ClassName(method->input_type());
+ vars["output"] = ClassName(method->output_type());
+ printer->Print(vars,
+ "case $index$:\n"
+ " return impl.$method$(controller, ($input$)request);\n");
+ }
+
+ printer->Print(
+ "default:\n"
+ " throw new java.lang.AssertionError(\"Can't get here.\");\n");
printer->Outdent();
printer->Outdent();
@@ -144,6 +252,10 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
io::Printer* printer) {
+ /*
+ * TODO(cpovirk): The exception message says "Service.foo" when it may be
+ * "BlockingService.foo." Consider fixing.
+ */
printer->Print(
"public final com.google.protobuf.Message\n"
" get$request_or_response$Prototype(\n"
@@ -171,7 +283,7 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
printer->Print(
"default:\n"
- " throw new java.lang.RuntimeException(\"Can't get here.\");\n");
+ " throw new java.lang.AssertionError(\"Can't get here.\");\n");
printer->Outdent();
printer->Outdent();
@@ -189,7 +301,8 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) {
" return new Stub(channel);\n"
"}\n"
"\n"
- "public static final class Stub extends $classname$ {\n",
+ "public static final class Stub extends $classname$ implements Interface {"
+ "\n",
"classname", ClassName(descriptor_));
printer->Indent();
@@ -206,33 +319,125 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) {
for (int i = 0; i < descriptor_->method_count(); i++) {
const MethodDescriptor* method = descriptor_->method(i);
+ printer->Print("\n");
+ GenerateMethodSignature(printer, method, IS_CONCRETE);
+ printer->Print(" {\n");
+ printer->Indent();
+
map<string, string> vars;
vars["index"] = SimpleItoa(i);
- vars["method"] = UnderscoresToCamelCase(method);
- vars["input"] = ClassName(method->input_type());
vars["output"] = ClassName(method->output_type());
printer->Print(vars,
- "\n"
- "public void $method$(\n"
- " com.google.protobuf.RpcController controller,\n"
- " $input$ request,\n"
- " com.google.protobuf.RpcCallback<$output$> done) {\n"
- " channel.callMethod(\n"
- " getDescriptor().getMethods().get($index$),\n"
- " controller,\n"
- " request,\n"
- " $output$.getDefaultInstance(),\n"
- " com.google.protobuf.RpcUtil.generalizeCallback(\n"
- " done,\n"
- " $output$.class,\n"
- " $output$.getDefaultInstance()));\n"
- "}\n");
+ "channel.callMethod(\n"
+ " getDescriptor().getMethods().get($index$),\n"
+ " controller,\n"
+ " request,\n"
+ " $output$.getDefaultInstance(),\n"
+ " com.google.protobuf.RpcUtil.generalizeCallback(\n"
+ " done,\n"
+ " $output$.class,\n"
+ " $output$.getDefaultInstance()));\n");
+
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+}
+
+void ServiceGenerator::GenerateBlockingStub(io::Printer* printer) {
+ printer->Print(
+ "public static BlockingInterface newBlockingStub(\n"
+ " com.google.protobuf.BlockingRpcChannel channel) {\n"
+ " return new BlockingStub(channel);\n"
+ "}\n"
+ "\n");
+
+ printer->Print(
+ "public interface BlockingInterface {");
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ GenerateBlockingMethodSignature(printer, method);
+ printer->Print(";\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+
+ printer->Print(
+ "private static final class BlockingStub implements BlockingInterface {\n");
+ printer->Indent();
+
+ printer->Print(
+ "private BlockingStub(com.google.protobuf.BlockingRpcChannel channel) {\n"
+ " this.channel = channel;\n"
+ "}\n"
+ "\n"
+ "private final com.google.protobuf.BlockingRpcChannel channel;\n");
+
+ for (int i = 0; i < descriptor_->method_count(); i++) {
+ const MethodDescriptor* method = descriptor_->method(i);
+ GenerateBlockingMethodSignature(printer, method);
+ printer->Print(" {\n");
+ printer->Indent();
+
+ map<string, string> vars;
+ vars["index"] = SimpleItoa(i);
+ vars["output"] = ClassName(method->output_type());
+ printer->Print(vars,
+ "return ($output$) channel.callBlockingMethod(\n"
+ " getDescriptor().getMethods().get($index$),\n"
+ " controller,\n"
+ " request,\n"
+ " $output$.getDefaultInstance());\n");
+
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
}
printer->Outdent();
printer->Print("}\n");
}
+void ServiceGenerator::GenerateMethodSignature(io::Printer* printer,
+ const MethodDescriptor* method,
+ IsAbstract is_abstract) {
+ map<string, string> vars;
+ vars["name"] = UnderscoresToCamelCase(method);
+ vars["input"] = ClassName(method->input_type());
+ vars["output"] = ClassName(method->output_type());
+ vars["abstract"] = (is_abstract == IS_ABSTRACT) ? "abstract" : "";
+ printer->Print(vars,
+ "public $abstract$ void $name$(\n"
+ " com.google.protobuf.RpcController controller,\n"
+ " $input$ request,\n"
+ " com.google.protobuf.RpcCallback<$output$> done)");
+}
+
+void ServiceGenerator::GenerateBlockingMethodSignature(
+ io::Printer* printer,
+ const MethodDescriptor* method) {
+ map<string, string> vars;
+ vars["method"] = UnderscoresToCamelCase(method);
+ vars["input"] = ClassName(method->input_type());
+ vars["output"] = ClassName(method->output_type());
+ printer->Print(vars,
+ "\n"
+ "public $output$ $method$(\n"
+ " com.google.protobuf.RpcController controller,\n"
+ " $input$ request)\n"
+ " throws com.google.protobuf.ServiceException");
+}
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_service.h b/src/google/protobuf/compiler/java/java_service.h
index 83404174..e07eebf7 100644
--- a/src/google/protobuf/compiler/java/java_service.h
+++ b/src/google/protobuf/compiler/java/java_service.h
@@ -57,9 +57,28 @@ class ServiceGenerator {
void Generate(io::Printer* printer);
private:
+
+ // Generate the getDescriptorForType() method.
+ void GenerateGetDescriptorForType(io::Printer* printer);
+
+ // Generate a Java interface for the service.
+ void GenerateInterface(io::Printer* printer);
+
+ // Generate newReflectiveService() method.
+ void GenerateNewReflectiveServiceMethod(io::Printer* printer);
+
+ // Generate newReflectiveBlockingService() method.
+ void GenerateNewReflectiveBlockingServiceMethod(io::Printer* printer);
+
+ // Generate abstract method declarations for all methods.
+ void GenerateAbstractMethods(io::Printer* printer);
+
// Generate the implementation of Service.callMethod().
void GenerateCallMethod(io::Printer* printer);
+ // Generate the implementation of BlockingService.callBlockingMethod().
+ void GenerateCallBlockingMethod(io::Printer* printer);
+
// Generate the implementations of Service.get{Request,Response}Prototype().
enum RequestOrResponse { REQUEST, RESPONSE };
void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer);
@@ -67,6 +86,20 @@ class ServiceGenerator {
// Generate a stub implementation of the service.
void GenerateStub(io::Printer* printer);
+ // Generate a method signature, possibly abstract, without body or trailing
+ // semicolon.
+ enum IsAbstract { IS_ABSTRACT, IS_CONCRETE };
+ void GenerateMethodSignature(io::Printer* printer,
+ const MethodDescriptor* method,
+ IsAbstract is_abstract);
+
+ // Generate a blocking stub interface and implementation of the service.
+ void GenerateBlockingStub(io::Printer* printer);
+
+ // Generate the method signature for one method of a blocking stub.
+ void GenerateBlockingMethodSignature(io::Printer* printer,
+ const MethodDescriptor* method);
+
const ServiceDescriptor* descriptor_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator);
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index e1c0d0d1..e9e01545 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -97,7 +97,8 @@ Parser::Parser()
error_collector_(NULL),
source_location_table_(NULL),
had_errors_(false),
- require_syntax_identifier_(false) {
+ require_syntax_identifier_(false),
+ stop_after_syntax_identifier_(false) {
}
Parser::~Parser() {
@@ -309,10 +310,12 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
// identifier.
return false;
}
- } else {
+ } else if (!stop_after_syntax_identifier_) {
syntax_identifier_ = "proto2";
}
+ if (stop_after_syntax_identifier_) return !had_errors_;
+
// Repeatedly parse statements until we reach the end of the file.
while (!AtEnd()) {
if (!ParseTopLevelStatement(file)) {
@@ -341,7 +344,7 @@ bool Parser::ParseSyntaxIdentifier() {
syntax_identifier_ = syntax;
- if (syntax != "proto2") {
+ if (syntax != "proto2" && !stop_after_syntax_identifier_) {
AddError(syntax_token.line, syntax_token.column,
"Unrecognized syntax identifier \"" + syntax + "\". This parser "
"only recognizes \"proto2\".");
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index b670f740..72c96d04 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -90,7 +90,7 @@ class LIBPROTOBUF_EXPORT Parser {
// Returns the identifier used in the "syntax = " declaration, if one was
// seen during the last call to Parse(), or the empty string otherwise.
- const string& GetSyntaxIndentifier() { return syntax_identifier_; }
+ const string& GetSyntaxIdentifier() { return syntax_identifier_; }
// If set true, input files will be required to begin with a syntax
// identifier. Otherwise, files may omit this. If a syntax identifier
@@ -100,6 +100,18 @@ class LIBPROTOBUF_EXPORT Parser {
require_syntax_identifier_ = value;
}
+ // Call SetStopAfterSyntaxIdentifier(true) to tell the parser to stop
+ // parsing as soon as it has seen the syntax identifier, or lack thereof.
+ // This is useful for quickly identifying the syntax of the file without
+ // parsing the whole thing. If this is enabled, no error will be recorded
+ // if the syntax identifier is something other than "proto2" (since
+ // presumably the caller intends to deal with that), but other kinds of
+ // errors (e.g. parse errors) will still be reported. When this is enabled,
+ // you may pass a NULL FileDescriptorProto to Parse().
+ void SetStopAfterSyntaxIdentifier(bool value) {
+ stop_after_syntax_identifier_ = value;
+ }
+
private:
// =================================================================
// Error recovery helpers
@@ -281,6 +293,7 @@ class LIBPROTOBUF_EXPORT Parser {
SourceLocationTable* source_location_table_;
bool had_errors_;
bool require_syntax_identifier_;
+ bool stop_after_syntax_identifier_;
string syntax_identifier_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index 2d48c5ae..c4f08e7f 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -176,6 +176,38 @@ class ParserTest : public testing::Test {
// ===================================================================
+TEST_F(ParserTest, StopAfterSyntaxIdentifier) {
+ SetupParser(
+ "// blah\n"
+ "syntax = \"foobar\";\n"
+ "this line will not be parsed\n");
+ parser_->SetStopAfterSyntaxIdentifier(true);
+ EXPECT_TRUE(parser_->Parse(input_.get(), NULL));
+ EXPECT_EQ("", error_collector_.text_);
+ EXPECT_EQ("foobar", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParserTest, StopAfterOmittedSyntaxIdentifier) {
+ SetupParser(
+ "// blah\n"
+ "this line will not be parsed\n");
+ parser_->SetStopAfterSyntaxIdentifier(true);
+ EXPECT_TRUE(parser_->Parse(input_.get(), NULL));
+ EXPECT_EQ("", error_collector_.text_);
+ EXPECT_EQ("", parser_->GetSyntaxIdentifier());
+}
+
+TEST_F(ParserTest, StopAfterSyntaxIdentifierWithErrors) {
+ SetupParser(
+ "// blah\n"
+ "syntax = error;\n");
+ parser_->SetStopAfterSyntaxIdentifier(true);
+ EXPECT_FALSE(parser_->Parse(input_.get(), NULL));
+ EXPECT_EQ("1:9: Expected syntax identifier.\n", error_collector_.text_);
+}
+
+// ===================================================================
+
typedef ParserTest ParseMessageTest;
TEST_F(ParseMessageTest, SimpleMessage) {
@@ -201,7 +233,7 @@ TEST_F(ParseMessageTest, ImplicitSyntaxIdentifier) {
" name: \"TestMessage\""
" field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
"}");
- EXPECT_EQ("proto2", parser_->GetSyntaxIndentifier());
+ EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
}
TEST_F(ParseMessageTest, ExplicitSyntaxIdentifier) {
@@ -215,7 +247,7 @@ TEST_F(ParseMessageTest, ExplicitSyntaxIdentifier) {
" name: \"TestMessage\""
" field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
"}");
- EXPECT_EQ("proto2", parser_->GetSyntaxIndentifier());
+ EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
}
TEST_F(ParseMessageTest, ExplicitRequiredSyntaxIdentifier) {
@@ -230,7 +262,7 @@ TEST_F(ParseMessageTest, ExplicitRequiredSyntaxIdentifier) {
" name: \"TestMessage\""
" field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
"}");
- EXPECT_EQ("proto2", parser_->GetSyntaxIndentifier());
+ EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
}
TEST_F(ParseMessageTest, SimpleFields) {
@@ -673,7 +705,7 @@ TEST_F(ParseErrorTest, MissingSyntaxIdentifier) {
ExpectHasEarlyExitErrors(
"message TestMessage {}",
"0:0: File must begin with 'syntax = \"proto2\";'.\n");
- EXPECT_EQ("", parser_->GetSyntaxIndentifier());
+ EXPECT_EQ("", parser_->GetSyntaxIdentifier());
}
TEST_F(ParseErrorTest, UnknownSyntaxIdentifier) {
@@ -681,14 +713,14 @@ TEST_F(ParseErrorTest, UnknownSyntaxIdentifier) {
"syntax = \"no_such_syntax\";",
"0:9: Unrecognized syntax identifier \"no_such_syntax\". This parser "
"only recognizes \"proto2\".\n");
- EXPECT_EQ("no_such_syntax", parser_->GetSyntaxIndentifier());
+ EXPECT_EQ("no_such_syntax", parser_->GetSyntaxIdentifier());
}
TEST_F(ParseErrorTest, SimpleSyntaxError) {
ExpectHasErrors(
"message TestMessage @#$ { blah }",
"0:20: Expected \"{\".\n");
- EXPECT_EQ("proto2", parser_->GetSyntaxIndentifier());
+ EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
}
TEST_F(ParseErrorTest, ExpectedTopLevel) {
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index eb5b5937..ecca3293 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -167,14 +167,6 @@ string ToCamelCase(const string& input) {
typedef pair<const void*, const char*> PointerStringPair;
-// Used by GCC/SGI STL only. (Why isn't this provided by the standard
-// library? :( )
-struct CStringEqual {
- inline bool operator()(const char* a, const char* b) const {
- return strcmp(a, b) == 0;
- }
-};
-
struct PointerStringPairEqual {
inline bool operator()(const PointerStringPair& a,
const PointerStringPair& b) const {
@@ -240,6 +232,13 @@ struct Symbol {
inline Symbol() : type(NULL_SYMBOL) { descriptor = NULL; }
inline bool IsNull() const { return type == NULL_SYMBOL; }
+ inline bool IsType() const {
+ return type == MESSAGE || type == ENUM;
+ }
+ inline bool IsAggregate() const {
+ return type == MESSAGE || type == PACKAGE
+ || type == ENUM || type == SERVICE;
+ }
#define CONSTRUCTOR(TYPE, TYPE_CONSTANT, FIELD) \
inline explicit Symbol(const TYPE* value) { \
@@ -274,13 +273,13 @@ struct Symbol {
const Symbol kNullSymbol;
typedef hash_map<const char*, Symbol,
- hash<const char*>, CStringEqual>
+ hash<const char*>, streq>
SymbolsByNameMap;
typedef hash_map<PointerStringPair, Symbol,
PointerStringPairHash, PointerStringPairEqual>
SymbolsByParentMap;
typedef hash_map<const char*, const FileDescriptor*,
- hash<const char*>, CStringEqual>
+ hash<const char*>, streq>
FilesByNameMap;
typedef hash_map<PointerStringPair, const FieldDescriptor*,
PointerStringPairHash, PointerStringPairEqual>
@@ -291,6 +290,12 @@ typedef hash_map<DescriptorIntPair, const FieldDescriptor*,
typedef hash_map<EnumIntPair, const EnumValueDescriptor*,
PointerIntegerPairHash<EnumIntPair> >
EnumValuesByNumberMap;
+// This is a map rather than a hash_map, since we use it to iterate
+// through all the extensions that extend a given Descriptor, and an
+// ordered data structure that implements lower_bound is convenient
+// for that.
+typedef map<DescriptorIntPair, const FieldDescriptor*>
+ ExtensionsGroupedByDescriptorMap;
} // anonymous namespace
@@ -324,17 +329,16 @@ class DescriptorPool::Tables {
// Not used when fallback_database_ == NULL.
hash_set<string> known_bad_files_;
+ // The set of descriptors for which we've already loaded the full
+ // set of extensions numbers from fallback_database_.
+ hash_set<const Descriptor*> extensions_loaded_from_db_;
+
// -----------------------------------------------------------------
// Finding items.
- // Find symbols. These return a null Symbol (symbol.IsNull() is true)
+ // Find symbols. This returns a null Symbol (symbol.IsNull() is true)
// if not found.
inline Symbol FindSymbol(const string& key) const;
- inline Symbol FindNestedSymbol(const void* parent,
- const string& name) const;
- inline Symbol FindNestedSymbolOfType(const void* parent,
- const string& name,
- const Symbol::Type type) const;
// This implements the body of DescriptorPool::Find*ByName(). It should
// really be a private method of DescriptorPool, but that would require
@@ -345,40 +349,21 @@ class DescriptorPool::Tables {
// These return NULL if not found.
inline const FileDescriptor* FindFile(const string& key) const;
- inline const FieldDescriptor* FindFieldByNumber(
- const Descriptor* parent, int number) const;
- inline const FieldDescriptor* FindFieldByLowercaseName(
- const void* parent, const string& lowercase_name) const;
- inline const FieldDescriptor* FindFieldByCamelcaseName(
- const void* parent, const string& camelcase_name) const;
- inline const EnumValueDescriptor* FindEnumValueByNumber(
- const EnumDescriptor* parent, int number) const;
+ inline const FieldDescriptor* FindExtension(const Descriptor* extendee,
+ int number);
+ inline void FindAllExtensions(const Descriptor* extendee,
+ vector<const FieldDescriptor*>* out) const;
// -----------------------------------------------------------------
// Adding items.
// These add items to the corresponding tables. They return false if
- // the key already exists in the table. For AddSymbol(), the strings passed
- // in must be ones that were constructed using AllocateString(), as they will
- // be used as keys in the symbols_by_name_ and symbols_by_parent_ maps
- // without copying. (If parent is NULL, nothing is added to
- // symbols_by_parent_.)
- bool AddSymbol(const string& full_name,
- const void* parent, const string& name,
- Symbol symbol);
+ // the key already exists in the table. For AddSymbol(), the string passed
+ // in must be one that was constructed using AllocateString(), as it will
+ // be used as a key in the symbols_by_name_ map without copying.
+ bool AddSymbol(const string& full_name, Symbol symbol);
bool AddFile(const FileDescriptor* file);
- bool AddFieldByNumber(const FieldDescriptor* field);
- bool AddEnumValueByNumber(const EnumValueDescriptor* value);
-
- // Adds the field to the lowercase_name and camelcase_name maps. Never
- // fails because we allow duplicates; the first field by the name wins.
- void AddFieldByStylizedNames(const FieldDescriptor* field);
-
- // Like AddSymbol(), but only adds to symbols_by_parent_, not
- // symbols_by_name_. Used for enum values, which need to be registered
- // under multiple parents (their type and its parent).
- bool AddAliasUnderParent(const void* parent, const string& name,
- Symbol symbol);
+ bool AddExtension(const FieldDescriptor* field);
// -----------------------------------------------------------------
// Allocating memory.
@@ -397,38 +382,100 @@ class DescriptorPool::Tables {
// The string is initialized to the given value for convenience.
string* AllocateString(const string& value);
- // Allocate a protocol message object.
- template<typename Type> Type* AllocateMessage();
+ // Allocate a protocol message object. Some older versions of GCC have
+ // trouble understanding explicit template instantiations in some cases, so
+ // in those cases we have to pass a dummy pointer of the right type as the
+ // parameter instead of specifying the type explicitly.
+ template<typename Type> Type* AllocateMessage(Type* dummy = NULL);
+
+ // Allocate a FileDescriptorTables object.
+ FileDescriptorTables* AllocateFileTables();
private:
vector<string*> strings_; // All strings in the pool.
vector<Message*> messages_; // All messages in the pool.
+ vector<FileDescriptorTables*> file_tables_; // All file tables in the pool.
vector<void*> allocations_; // All other memory allocated in the pool.
SymbolsByNameMap symbols_by_name_;
- SymbolsByParentMap symbols_by_parent_;
FilesByNameMap files_by_name_;
- FieldsByNameMap fields_by_lowercase_name_;
- FieldsByNameMap fields_by_camelcase_name_;
- FieldsByNumberMap fields_by_number_; // Includes extensions.
- EnumValuesByNumberMap enum_values_by_number_;
+ ExtensionsGroupedByDescriptorMap extensions_;
int strings_before_checkpoint_;
int messages_before_checkpoint_;
+ int file_tables_before_checkpoint_;
int allocations_before_checkpoint_;
vector<const char* > symbols_after_checkpoint_;
- vector<PointerStringPair> symbols_by_parent_after_checkpoint_;
vector<const char* > files_after_checkpoint_;
- vector<PointerStringPair> field_lowercase_names_after_checkpoint_;
- vector<PointerStringPair> field_camelcase_names_after_checkpoint_;
- vector<DescriptorIntPair> field_numbers_after_checkpoint_;
- vector<EnumIntPair > enum_numbers_after_checkpoint_;
+ vector<DescriptorIntPair> extensions_after_checkpoint_;
// Allocate some bytes which will be reclaimed when the pool is
// destroyed.
void* AllocateBytes(int size);
};
+// Contains tables specific to a particular file. These tables are not
+// modified once the file has been constructed, so they need not be
+// protected by a mutex. This makes operations that depend only on the
+// contents of a single file -- e.g. Descriptor::FindFieldByName() --
+// lock-free.
+//
+// For historical reasons, the definitions of the methods of
+// FileDescriptorTables and DescriptorPool::Tables are interleaved below.
+// These used to be a single class.
+class FileDescriptorTables {
+ public:
+ FileDescriptorTables();
+ ~FileDescriptorTables();
+
+ // Empty table, used with placeholder files.
+ static const FileDescriptorTables kEmpty;
+
+ // -----------------------------------------------------------------
+ // Finding items.
+
+ // Find symbols. These return a null Symbol (symbol.IsNull() is true)
+ // if not found.
+ inline Symbol FindNestedSymbol(const void* parent,
+ const string& name) const;
+ inline Symbol FindNestedSymbolOfType(const void* parent,
+ const string& name,
+ const Symbol::Type type) const;
+
+ // These return NULL if not found.
+ inline const FieldDescriptor* FindFieldByNumber(
+ const Descriptor* parent, int number) const;
+ inline const FieldDescriptor* FindFieldByLowercaseName(
+ const void* parent, const string& lowercase_name) const;
+ inline const FieldDescriptor* FindFieldByCamelcaseName(
+ const void* parent, const string& camelcase_name) const;
+ inline const EnumValueDescriptor* FindEnumValueByNumber(
+ const EnumDescriptor* parent, int number) const;
+
+ // -----------------------------------------------------------------
+ // Adding items.
+
+ // These add items to the corresponding tables. They return false if
+ // the key already exists in the table. For AddAliasUnderParent(), the
+ // string passed in must be one that was constructed using AllocateString(),
+ // as it will be used as a key in the symbols_by_parent_ map without copying.
+ bool AddAliasUnderParent(const void* parent, const string& name,
+ Symbol symbol);
+ bool AddFieldByNumber(const FieldDescriptor* field);
+ bool AddEnumValueByNumber(const EnumValueDescriptor* value);
+
+ // Adds the field to the lowercase_name and camelcase_name maps. Never
+ // fails because we allow duplicates; the first field by the name wins.
+ void AddFieldByStylizedNames(const FieldDescriptor* field);
+
+ private:
+ SymbolsByParentMap symbols_by_parent_;
+ FieldsByNameMap fields_by_lowercase_name_;
+ FieldsByNameMap fields_by_camelcase_name_;
+ FieldsByNumberMap fields_by_number_; // Not including extensions.
+ EnumValuesByNumberMap enum_values_by_number_;
+};
+
DescriptorPool::Tables::Tables()
: strings_before_checkpoint_(0),
messages_before_checkpoint_(0),
@@ -442,63 +489,53 @@ DescriptorPool::Tables::~Tables() {
operator delete(allocations_[i]);
}
STLDeleteElements(&strings_);
+ STLDeleteElements(&file_tables_);
}
+FileDescriptorTables::FileDescriptorTables() {}
+FileDescriptorTables::~FileDescriptorTables() {}
+
+const FileDescriptorTables FileDescriptorTables::kEmpty;
+
void DescriptorPool::Tables::Checkpoint() {
strings_before_checkpoint_ = strings_.size();
messages_before_checkpoint_ = messages_.size();
+ file_tables_before_checkpoint_ = file_tables_.size();
allocations_before_checkpoint_ = allocations_.size();
symbols_after_checkpoint_.clear();
- symbols_by_parent_after_checkpoint_.clear();
files_after_checkpoint_.clear();
- field_lowercase_names_after_checkpoint_.clear();
- field_camelcase_names_after_checkpoint_.clear();
- field_numbers_after_checkpoint_.clear();
- enum_numbers_after_checkpoint_.clear();
+ extensions_after_checkpoint_.clear();
}
void DescriptorPool::Tables::Rollback() {
for (int i = 0; i < symbols_after_checkpoint_.size(); i++) {
symbols_by_name_.erase(symbols_after_checkpoint_[i]);
}
- for (int i = 0; i < symbols_by_parent_after_checkpoint_.size(); i++) {
- symbols_by_parent_.erase(symbols_by_parent_after_checkpoint_[i]);
- }
for (int i = 0; i < files_after_checkpoint_.size(); i++) {
files_by_name_.erase(files_after_checkpoint_[i]);
}
- for (int i = 0; i < field_lowercase_names_after_checkpoint_.size(); i++) {
- fields_by_lowercase_name_.erase(field_lowercase_names_after_checkpoint_[i]);
- }
- for (int i = 0; i < field_camelcase_names_after_checkpoint_.size(); i++) {
- fields_by_camelcase_name_.erase(field_camelcase_names_after_checkpoint_[i]);
- }
- for (int i = 0; i < field_numbers_after_checkpoint_.size(); i++) {
- fields_by_number_.erase(field_numbers_after_checkpoint_[i]);
- }
- for (int i = 0; i < enum_numbers_after_checkpoint_.size(); i++) {
- enum_values_by_number_.erase(enum_numbers_after_checkpoint_[i]);
+ for (int i = 0; i < extensions_after_checkpoint_.size(); i++) {
+ extensions_.erase(extensions_after_checkpoint_[i]);
}
symbols_after_checkpoint_.clear();
- symbols_by_parent_after_checkpoint_.clear();
files_after_checkpoint_.clear();
- field_lowercase_names_after_checkpoint_.clear();
- field_camelcase_names_after_checkpoint_.clear();
- field_numbers_after_checkpoint_.clear();
- enum_numbers_after_checkpoint_.clear();
+ extensions_after_checkpoint_.clear();
STLDeleteContainerPointers(
strings_.begin() + strings_before_checkpoint_, strings_.end());
STLDeleteContainerPointers(
messages_.begin() + messages_before_checkpoint_, messages_.end());
+ STLDeleteContainerPointers(
+ file_tables_.begin() + file_tables_before_checkpoint_, file_tables_.end());
for (int i = allocations_before_checkpoint_; i < allocations_.size(); i++) {
operator delete(allocations_[i]);
}
strings_.resize(strings_before_checkpoint_);
messages_.resize(messages_before_checkpoint_);
+ file_tables_.resize(file_tables_before_checkpoint_);
allocations_.resize(allocations_before_checkpoint_);
}
@@ -513,7 +550,7 @@ inline Symbol DescriptorPool::Tables::FindSymbol(const string& key) const {
}
}
-inline Symbol DescriptorPool::Tables::FindNestedSymbol(
+inline Symbol FileDescriptorTables::FindNestedSymbol(
const void* parent, const string& name) const {
const Symbol* result =
FindOrNull(symbols_by_parent_, PointerStringPair(parent, name.c_str()));
@@ -524,7 +561,7 @@ inline Symbol DescriptorPool::Tables::FindNestedSymbol(
}
}
-inline Symbol DescriptorPool::Tables::FindNestedSymbolOfType(
+inline Symbol FileDescriptorTables::FindNestedSymbolOfType(
const void* parent, const string& name, const Symbol::Type type) const {
Symbol result = FindNestedSymbol(parent, name);
if (result.type != type) return kNullSymbol;
@@ -557,59 +594,58 @@ inline const FileDescriptor* DescriptorPool::Tables::FindFile(
return FindPtrOrNull(files_by_name_, key.c_str());
}
-inline const FieldDescriptor* DescriptorPool::Tables::FindFieldByNumber(
+inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
const Descriptor* parent, int number) const {
return FindPtrOrNull(fields_by_number_, make_pair(parent, number));
}
-inline const FieldDescriptor* DescriptorPool::Tables::FindFieldByLowercaseName(
+inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName(
const void* parent, const string& lowercase_name) const {
return FindPtrOrNull(fields_by_lowercase_name_,
PointerStringPair(parent, lowercase_name.c_str()));
}
-inline const FieldDescriptor* DescriptorPool::Tables::FindFieldByCamelcaseName(
+inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName(
const void* parent, const string& camelcase_name) const {
return FindPtrOrNull(fields_by_camelcase_name_,
PointerStringPair(parent, camelcase_name.c_str()));
}
-inline const EnumValueDescriptor* DescriptorPool::Tables::FindEnumValueByNumber(
+inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
const EnumDescriptor* parent, int number) const {
return FindPtrOrNull(enum_values_by_number_, make_pair(parent, number));
}
+inline const FieldDescriptor* DescriptorPool::Tables::FindExtension(
+ const Descriptor* extendee, int number) {
+ return FindPtrOrNull(extensions_, make_pair(extendee, number));
+}
+
+inline void DescriptorPool::Tables::FindAllExtensions(
+ const Descriptor* extendee, vector<const FieldDescriptor*>* out) const {
+ ExtensionsGroupedByDescriptorMap::const_iterator it =
+ extensions_.lower_bound(make_pair(extendee, 0));
+ for (; it != extensions_.end() && it->first.first == extendee; ++it) {
+ out->push_back(it->second);
+ }
+}
+
// -------------------------------------------------------------------
bool DescriptorPool::Tables::AddSymbol(
- const string& full_name,
- const void* parent, const string& name,
- Symbol symbol) {
+ const string& full_name, Symbol symbol) {
if (InsertIfNotPresent(&symbols_by_name_, full_name.c_str(), symbol)) {
symbols_after_checkpoint_.push_back(full_name.c_str());
-
- if (parent != NULL && !AddAliasUnderParent(parent, name, symbol)) {
- GOOGLE_LOG(DFATAL) << "\"" << full_name << "\" not previously defined in "
- "symbols_by_name_, but was defined in symbols_by_parent_; "
- "this shouldn't be possible.";
- return false;
- }
-
return true;
} else {
return false;
}
}
-bool DescriptorPool::Tables::AddAliasUnderParent(
+bool FileDescriptorTables::AddAliasUnderParent(
const void* parent, const string& name, Symbol symbol) {
PointerStringPair by_parent_key(parent, name.c_str());
- if (InsertIfNotPresent(&symbols_by_parent_, by_parent_key, symbol)) {
- symbols_by_parent_after_checkpoint_.push_back(by_parent_key);
- return true;
- } else {
- return false;
- }
+ return InsertIfNotPresent(&symbols_by_parent_, by_parent_key, symbol);
}
bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
@@ -621,7 +657,7 @@ bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
}
}
-void DescriptorPool::Tables::AddFieldByStylizedNames(
+void FileDescriptorTables::AddFieldByStylizedNames(
const FieldDescriptor* field) {
const void* parent;
if (field->is_extension()) {
@@ -635,31 +671,27 @@ void DescriptorPool::Tables::AddFieldByStylizedNames(
}
PointerStringPair lowercase_key(parent, field->lowercase_name().c_str());
- if (InsertIfNotPresent(&fields_by_lowercase_name_, lowercase_key, field)) {
- field_lowercase_names_after_checkpoint_.push_back(lowercase_key);
- }
+ InsertIfNotPresent(&fields_by_lowercase_name_, lowercase_key, field);
PointerStringPair camelcase_key(parent, field->camelcase_name().c_str());
- if (InsertIfNotPresent(&fields_by_camelcase_name_, camelcase_key, field)) {
- field_camelcase_names_after_checkpoint_.push_back(camelcase_key);
- }
+ InsertIfNotPresent(&fields_by_camelcase_name_, camelcase_key, field);
}
-bool DescriptorPool::Tables::AddFieldByNumber(const FieldDescriptor* field) {
+bool FileDescriptorTables::AddFieldByNumber(const FieldDescriptor* field) {
DescriptorIntPair key(field->containing_type(), field->number());
- if (InsertIfNotPresent(&fields_by_number_, key, field)) {
- field_numbers_after_checkpoint_.push_back(key);
- return true;
- } else {
- return false;
- }
+ return InsertIfNotPresent(&fields_by_number_, key, field);
}
-bool DescriptorPool::Tables::AddEnumValueByNumber(
+bool FileDescriptorTables::AddEnumValueByNumber(
const EnumValueDescriptor* value) {
EnumIntPair key(value->type(), value->number());
- if (InsertIfNotPresent(&enum_values_by_number_, key, value)) {
- enum_numbers_after_checkpoint_.push_back(key);
+ return InsertIfNotPresent(&enum_values_by_number_, key, value);
+}
+
+bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) {
+ DescriptorIntPair key(field->containing_type(), field->number());
+ if (InsertIfNotPresent(&extensions_, key, field)) {
+ extensions_after_checkpoint_.push_back(key);
return true;
} else {
return false;
@@ -685,12 +717,18 @@ string* DescriptorPool::Tables::AllocateString(const string& value) {
}
template<typename Type>
-Type* DescriptorPool::Tables::AllocateMessage() {
+Type* DescriptorPool::Tables::AllocateMessage(Type* dummy) {
Type* result = new Type;
messages_.push_back(result);
return result;
}
+FileDescriptorTables* DescriptorPool::Tables::AllocateFileTables() {
+ FileDescriptorTables* result = new FileDescriptorTables;
+ file_tables_.push_back(result);
+ return result;
+}
+
void* DescriptorPool::Tables::AllocateBytes(int size) {
// TODO(kenton): Would it be worthwhile to implement this in some more
// sophisticated way? Probably not for the open source release, but for
@@ -715,7 +753,7 @@ DescriptorPool::DescriptorPool()
underlay_(NULL),
tables_(new Tables),
enforce_dependencies_(true),
- last_internal_build_generated_file_call_(NULL) {}
+ allow_unknown_(false) {}
DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database,
ErrorCollector* error_collector)
@@ -725,7 +763,7 @@ DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database,
underlay_(NULL),
tables_(new Tables),
enforce_dependencies_(true),
- last_internal_build_generated_file_call_(NULL) {
+ allow_unknown_(false) {
}
DescriptorPool::DescriptorPool(const DescriptorPool* underlay)
@@ -734,7 +772,8 @@ DescriptorPool::DescriptorPool(const DescriptorPool* underlay)
default_error_collector_(NULL),
underlay_(underlay),
tables_(new Tables),
- last_internal_build_generated_file_call_(NULL) {}
+ enforce_dependencies_(true),
+ allow_unknown_(false) {}
DescriptorPool::~DescriptorPool() {
if (mutex_ != NULL) delete mutex_;
@@ -742,21 +781,78 @@ DescriptorPool::~DescriptorPool() {
// DescriptorPool::BuildFile() defined later.
// DescriptorPool::BuildFileCollectingErrors() defined later.
-// DescriptorPool::InternalBuildGeneratedFile() defined later.
+
+void DescriptorPool::InternalDontEnforceDependencies() {
+ enforce_dependencies_ = false;
+}
+
+bool DescriptorPool::InternalIsFileLoaded(const string& filename) const {
+ MutexLockMaybe lock(mutex_);
+ return tables_->FindFile(filename) != NULL;
+}
+
+// generated_pool ====================================================
+
+namespace {
+
+EncodedDescriptorDatabase* generated_database_ = NULL;
+DescriptorPool* generated_pool_ = NULL;
+
+void InitGeneratedPool() {
+ GOOGLE_CHECK(generated_pool_ == NULL);
+ generated_database_ = new EncodedDescriptorDatabase;
+ generated_pool_ = new DescriptorPool(generated_database_);
+}
+
+// Force InitGeneratedPool to be called at static init time, before any threads
+// can be created.
+struct Initializer {
+ Initializer() {
+ if (generated_pool_ == NULL) InitGeneratedPool();
+ }
+} initializer;
+
+} // anonymous namespace
const DescriptorPool* DescriptorPool::generated_pool() {
- return internal_generated_pool();
+ if (generated_pool_ == NULL) InitGeneratedPool();
+ return generated_pool_;
}
DescriptorPool* DescriptorPool::internal_generated_pool() {
- static DescriptorPool singleton;
- return &singleton;
+ if (generated_pool_ == NULL) InitGeneratedPool();
+ return generated_pool_;
}
-void DescriptorPool::InternalDontEnforceDependencies() {
- enforce_dependencies_ = false;
+void DescriptorPool::InternalAddGeneratedFile(
+ const void* encoded_file_descriptor, int size) {
+ // So, this function is called in the process of initializing the
+ // descriptors for generated proto classes. Each generated .pb.cc file
+ // has an internal procedure called AddDescriptors() which is called at
+ // process startup, and that function calls this one in order to register
+ // the raw bytes of the FileDescriptorProto representing the file.
+ //
+ // We do not actually construct the descriptor objects right away. We just
+ // hang on to the bytes until they are actually needed. We actually construct
+ // the descriptor the first time one of the following things happens:
+ // * Someone calls a method like descriptor(), GetDescriptor(), or
+ // GetReflection() on the generated types, which requires returning the
+ // descriptor or an object based on it.
+ // * Someone looks up the descriptor in DescriptorPool::generated_pool().
+ //
+ // Once one of these happens, the DescriptorPool actually parses the
+ // FileDescriptorProto and generates a FileDescriptor (and all its children)
+ // based on it.
+ //
+ // Note that FileDescriptorProto is itself a generated protocol message.
+ // Therefore, when we parse one, we have to be very careful to avoid using
+ // any descriptor-based operations, since this might cause infinite recursion
+ // or deadlock.
+ if (generated_pool_ == NULL) InitGeneratedPool();
+ GOOGLE_CHECK(generated_database_->Add(encoded_file_descriptor, size));
}
+
// Find*By* methods ==================================================
// TODO(kenton): There's a lot of repeated code here, but I'm not sure if
@@ -851,8 +947,8 @@ const MethodDescriptor* DescriptorPool::FindMethodByName(
const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
const Descriptor* extendee, int number) const {
MutexLockMaybe lock(mutex_);
- const FieldDescriptor* result = tables_->FindFieldByNumber(extendee, number);
- if (result != NULL && result->is_extension()) {
+ const FieldDescriptor* result = tables_->FindExtension(extendee, number);
+ if (result != NULL) {
return result;
}
if (underlay_ != NULL) {
@@ -861,22 +957,47 @@ const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
if (result != NULL) return result;
}
if (TryFindExtensionInFallbackDatabase(extendee, number)) {
- const FieldDescriptor* result =
- tables_->FindFieldByNumber(extendee, number);
- if (result != NULL && result->is_extension()) {
+ const FieldDescriptor* result = tables_->FindExtension(extendee, number);
+ if (result != NULL) {
return result;
}
}
return NULL;
}
+void DescriptorPool::FindAllExtensions(
+ const Descriptor* extendee, vector<const FieldDescriptor*>* out) const {
+ MutexLockMaybe lock(mutex_);
+
+ // Initialize tables_->extensions_ from the fallback database first
+ // (but do this only once per descriptor).
+ if (fallback_database_ != NULL &&
+ tables_->extensions_loaded_from_db_.count(extendee) == 0) {
+ vector<int> numbers;
+ if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(),
+ &numbers)) {
+ for (int i = 0; i < numbers.size(); ++i) {
+ int number = numbers[i];
+ if (tables_->FindExtension(extendee, number) == NULL) {
+ TryFindExtensionInFallbackDatabase(extendee, number);
+ }
+ }
+ tables_->extensions_loaded_from_db_.insert(extendee);
+ }
+ }
+
+ tables_->FindAllExtensions(extendee, out);
+ if (underlay_ != NULL) {
+ underlay_->FindAllExtensions(extendee, out);
+ }
+}
+
// -------------------------------------------------------------------
const FieldDescriptor*
Descriptor::FindFieldByNumber(int key) const {
- MutexLockMaybe lock(file()->pool()->mutex_);
const FieldDescriptor* result =
- file()->pool()->tables_->FindFieldByNumber(this, key);
+ file()->tables_->FindFieldByNumber(this, key);
if (result == NULL || result->is_extension()) {
return NULL;
} else {
@@ -886,9 +1007,8 @@ Descriptor::FindFieldByNumber(int key) const {
const FieldDescriptor*
Descriptor::FindFieldByLowercaseName(const string& key) const {
- MutexLockMaybe lock(file()->pool()->mutex_);
const FieldDescriptor* result =
- file()->pool()->tables_->FindFieldByLowercaseName(this, key);
+ file()->tables_->FindFieldByLowercaseName(this, key);
if (result == NULL || result->is_extension()) {
return NULL;
} else {
@@ -898,9 +1018,8 @@ Descriptor::FindFieldByLowercaseName(const string& key) const {
const FieldDescriptor*
Descriptor::FindFieldByCamelcaseName(const string& key) const {
- MutexLockMaybe lock(file()->pool()->mutex_);
const FieldDescriptor* result =
- file()->pool()->tables_->FindFieldByCamelcaseName(this, key);
+ file()->tables_->FindFieldByCamelcaseName(this, key);
if (result == NULL || result->is_extension()) {
return NULL;
} else {
@@ -910,9 +1029,8 @@ Descriptor::FindFieldByCamelcaseName(const string& key) const {
const FieldDescriptor*
Descriptor::FindFieldByName(const string& key) const {
- MutexLockMaybe lock(file()->pool()->mutex_);
Symbol result =
- file()->pool()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
+ file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
if (!result.IsNull() && !result.field_descriptor->is_extension()) {
return result.field_descriptor;
} else {
@@ -922,9 +1040,8 @@ Descriptor::FindFieldByName(const string& key) const {
const FieldDescriptor*
Descriptor::FindExtensionByName(const string& key) const {
- MutexLockMaybe lock(file()->pool()->mutex_);
Symbol result =
- file()->pool()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
+ file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
if (!result.IsNull() && result.field_descriptor->is_extension()) {
return result.field_descriptor;
} else {
@@ -934,9 +1051,8 @@ Descriptor::FindExtensionByName(const string& key) const {
const FieldDescriptor*
Descriptor::FindExtensionByLowercaseName(const string& key) const {
- MutexLockMaybe lock(file()->pool()->mutex_);
const FieldDescriptor* result =
- file()->pool()->tables_->FindFieldByLowercaseName(this, key);
+ file()->tables_->FindFieldByLowercaseName(this, key);
if (result == NULL || !result->is_extension()) {
return NULL;
} else {
@@ -946,9 +1062,8 @@ Descriptor::FindExtensionByLowercaseName(const string& key) const {
const FieldDescriptor*
Descriptor::FindExtensionByCamelcaseName(const string& key) const {
- MutexLockMaybe lock(file()->pool()->mutex_);
const FieldDescriptor* result =
- file()->pool()->tables_->FindFieldByCamelcaseName(this, key);
+ file()->tables_->FindFieldByCamelcaseName(this, key);
if (result == NULL || !result->is_extension()) {
return NULL;
} else {
@@ -958,9 +1073,8 @@ Descriptor::FindExtensionByCamelcaseName(const string& key) const {
const Descriptor*
Descriptor::FindNestedTypeByName(const string& key) const {
- MutexLockMaybe lock(file()->pool()->mutex_);
Symbol result =
- file()->pool()->tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
+ file()->tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
if (!result.IsNull()) {
return result.descriptor;
} else {
@@ -970,9 +1084,8 @@ Descriptor::FindNestedTypeByName(const string& key) const {
const EnumDescriptor*
Descriptor::FindEnumTypeByName(const string& key) const {
- MutexLockMaybe lock(file()->pool()->mutex_);
Symbol result =
- file()->pool()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
+ file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
if (!result.IsNull()) {
return result.enum_descriptor;
} else {
@@ -982,10 +1095,8 @@ Descriptor::FindEnumTypeByName(const string& key) const {
const EnumValueDescriptor*
Descriptor::FindEnumValueByName(const string& key) const {
- MutexLockMaybe lock(file()->pool()->mutex_);
Symbol result =
- file()->pool()->tables_->FindNestedSymbolOfType(
- this, key, Symbol::ENUM_VALUE);
+ file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
if (!result.IsNull()) {
return result.enum_value_descriptor;
} else {
@@ -995,10 +1106,8 @@ Descriptor::FindEnumValueByName(const string& key) const {
const EnumValueDescriptor*
EnumDescriptor::FindValueByName(const string& key) const {
- MutexLockMaybe lock(file()->pool()->mutex_);
Symbol result =
- file()->pool()->tables_->FindNestedSymbolOfType(
- this, key, Symbol::ENUM_VALUE);
+ file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
if (!result.IsNull()) {
return result.enum_value_descriptor;
} else {
@@ -1008,15 +1117,13 @@ EnumDescriptor::FindValueByName(const string& key) const {
const EnumValueDescriptor*
EnumDescriptor::FindValueByNumber(int key) const {
- MutexLockMaybe lock(file()->pool()->mutex_);
- return file()->pool()->tables_->FindEnumValueByNumber(this, key);
+ return file()->tables_->FindEnumValueByNumber(this, key);
}
const MethodDescriptor*
ServiceDescriptor::FindMethodByName(const string& key) const {
- MutexLockMaybe lock(file()->pool()->mutex_);
Symbol result =
- file()->pool()->tables_->FindNestedSymbolOfType(this, key, Symbol::METHOD);
+ file()->tables_->FindNestedSymbolOfType(this, key, Symbol::METHOD);
if (!result.IsNull()) {
return result.method_descriptor;
} else {
@@ -1026,9 +1133,7 @@ ServiceDescriptor::FindMethodByName(const string& key) const {
const Descriptor*
FileDescriptor::FindMessageTypeByName(const string& key) const {
- MutexLockMaybe lock(pool()->mutex_);
- Symbol result =
- pool()->tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
+ Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
if (!result.IsNull()) {
return result.descriptor;
} else {
@@ -1038,9 +1143,7 @@ FileDescriptor::FindMessageTypeByName(const string& key) const {
const EnumDescriptor*
FileDescriptor::FindEnumTypeByName(const string& key) const {
- MutexLockMaybe lock(pool()->mutex_);
- Symbol result =
- pool()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
+ Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
if (!result.IsNull()) {
return result.enum_descriptor;
} else {
@@ -1050,9 +1153,8 @@ FileDescriptor::FindEnumTypeByName(const string& key) const {
const EnumValueDescriptor*
FileDescriptor::FindEnumValueByName(const string& key) const {
- MutexLockMaybe lock(pool()->mutex_);
Symbol result =
- pool()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
+ tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
if (!result.IsNull()) {
return result.enum_value_descriptor;
} else {
@@ -1062,9 +1164,7 @@ FileDescriptor::FindEnumValueByName(const string& key) const {
const ServiceDescriptor*
FileDescriptor::FindServiceByName(const string& key) const {
- MutexLockMaybe lock(pool()->mutex_);
- Symbol result =
- pool()->tables_->FindNestedSymbolOfType(this, key, Symbol::SERVICE);
+ Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::SERVICE);
if (!result.IsNull()) {
return result.service_descriptor;
} else {
@@ -1074,9 +1174,7 @@ FileDescriptor::FindServiceByName(const string& key) const {
const FieldDescriptor*
FileDescriptor::FindExtensionByName(const string& key) const {
- MutexLockMaybe lock(pool()->mutex_);
- Symbol result =
- pool()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
+ Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
if (!result.IsNull() && result.field_descriptor->is_extension()) {
return result.field_descriptor;
} else {
@@ -1086,9 +1184,7 @@ FileDescriptor::FindExtensionByName(const string& key) const {
const FieldDescriptor*
FileDescriptor::FindExtensionByLowercaseName(const string& key) const {
- MutexLockMaybe lock(pool()->mutex_);
- const FieldDescriptor* result =
- pool()->tables_->FindFieldByLowercaseName(this, key);
+ const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key);
if (result == NULL || !result->is_extension()) {
return NULL;
} else {
@@ -1098,9 +1194,7 @@ FileDescriptor::FindExtensionByLowercaseName(const string& key) const {
const FieldDescriptor*
FileDescriptor::FindExtensionByCamelcaseName(const string& key) const {
- MutexLockMaybe lock(pool()->mutex_);
- const FieldDescriptor* result =
- pool()->tables_->FindFieldByCamelcaseName(this, key);
+ const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key);
if (result == NULL || !result->is_extension()) {
return NULL;
} else {
@@ -1297,15 +1391,27 @@ void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const {
implicit_cast<int>(type())));
if (is_extension()) {
- proto->set_extendee(".");
+ if (!containing_type()->is_unqualified_placeholder_) {
+ proto->set_extendee(".");
+ }
proto->mutable_extendee()->append(containing_type()->full_name());
}
if (cpp_type() == CPPTYPE_MESSAGE) {
- proto->set_type_name(".");
+ if (message_type()->is_placeholder_) {
+ // We don't actually know if the type is a message type. It could be
+ // an enum.
+ proto->clear_type();
+ }
+
+ if (!message_type()->is_unqualified_placeholder_) {
+ proto->set_type_name(".");
+ }
proto->mutable_type_name()->append(message_type()->full_name());
} else if (cpp_type() == CPPTYPE_ENUM) {
- proto->set_type_name(".");
+ if (!enum_type()->is_unqualified_placeholder_) {
+ proto->set_type_name(".");
+ }
proto->mutable_type_name()->append(enum_type()->full_name());
}
@@ -1354,9 +1460,14 @@ void ServiceDescriptor::CopyTo(ServiceDescriptorProto* proto) const {
void MethodDescriptor::CopyTo(MethodDescriptorProto* proto) const {
proto->set_name(name());
- proto->set_input_type(".");
+ if (!input_type()->is_unqualified_placeholder_) {
+ proto->set_input_type(".");
+ }
proto->mutable_input_type()->append(input_type()->full_name());
- proto->set_output_type(".");
+
+ if (!output_type()->is_unqualified_placeholder_) {
+ proto->set_output_type(".");
+ }
proto->mutable_output_type()->append(output_type()->full_name());
if (&options() != &MethodOptions::default_instance()) {
@@ -1720,8 +1831,7 @@ class DescriptorBuilder {
DescriptorPool::ErrorCollector* error_collector);
~DescriptorBuilder();
- const FileDescriptor* BuildFile(const FileDescriptorProto& proto,
- DescriptorPool::InternalDescriptorAssigner descriptor_assigner);
+ const FileDescriptor* BuildFile(const FileDescriptorProto& proto);
private:
friend class OptionInterpreter;
@@ -1738,6 +1848,7 @@ class DescriptorBuilder {
bool had_errors_;
string filename_;
FileDescriptor* file_;
+ FileDescriptorTables* file_tables_;
// If LookupSymbol() finds a symbol that is in a file which is not a declared
// dependency of this file, it will fail, but will set
@@ -1778,8 +1889,40 @@ class DescriptorBuilder {
// parents, etc. For example, LookupSymbol("foo.bar", "baz.qux.corge") makes
// the following calls, returning the first non-null result:
// FindSymbol("baz.qux.foo.bar"), FindSymbol("baz.foo.bar"),
- // FindSymbol("foo.bar").
- Symbol LookupSymbol(const string& name, const string& relative_to);
+ // FindSymbol("foo.bar"). If AllowUnknownDependencies() has been called
+ // on the DescriptorPool, this will generate a placeholder type if
+ // the name is not found (unless the name itself is malformed). The
+ // placeholder_type parameter indicates what kind of placeholder should be
+ // constructed in this case. The resolve_mode parameter determines whether
+ // any symbol is returned, or only symbols that are types. Note, however,
+ // that LookupSymbol may still return a non-type symbol in LOOKUP_TYPES mode,
+ // if it believes that's all it could refer to. The caller should always
+ // check that it receives the type of symbol it was expecting.
+ enum PlaceholderType {
+ PLACEHOLDER_MESSAGE,
+ PLACEHOLDER_ENUM,
+ PLACEHOLDER_EXTENDABLE_MESSAGE
+ };
+ enum ResolveMode {
+ LOOKUP_ALL, LOOKUP_TYPES
+ };
+ Symbol LookupSymbol(const string& name, const string& relative_to,
+ PlaceholderType placeholder_type = PLACEHOLDER_MESSAGE,
+ ResolveMode resolve_mode = LOOKUP_ALL);
+
+ // Like LookupSymbol() but will not return a placeholder even if
+ // AllowUnknownDependencies() has been used.
+ Symbol LookupSymbolNoPlaceholder(const string& name,
+ const string& relative_to,
+ ResolveMode resolve_mode = LOOKUP_ALL);
+
+ // Creates a placeholder type suitable for return from LookupSymbol(). May
+ // return kNullSymbol if the name is not a valid type name.
+ Symbol NewPlaceholder(const string& name, PlaceholderType placeholder_type);
+
+ // Creates a placeholder file. Never returns NULL. This is used when an
+ // import is not found and AllowUnknownDependencies() is enabled.
+ const FileDescriptor* NewPlaceholderFile(const string& name);
// Calls tables_->AddSymbol() and records an error if it fails. Returns
// true if successful or false if failed, though most callers can ignore
@@ -1801,6 +1944,10 @@ class DescriptorBuilder {
void ValidateSymbolName(const string& name, const string& full_name,
const Message& proto);
+ // Like ValidateSymbolName(), but the name is allowed to contain periods and
+ // an error is indicated by returning false (not recording the error).
+ bool ValidateQualifiedName(const string& name);
+
// Used by BUILD_ARRAY macro (below) to avoid having to have the type
// specified as a macro parameter.
template <typename Type>
@@ -1903,6 +2050,12 @@ class DescriptorBuilder {
// uninterpreted_option_ belongs.
bool InterpretSingleOption(Message* options);
+ // Adds the uninterpreted_option to the given options message verbatim.
+ // Used when AllowUnknownDependencies() is in effect and we can't find
+ // the option's definition.
+ void AddWithoutInterpreting(const UninterpretedOption& uninterpreted_option,
+ Message* options);
+
// A recursive helper function that drills into the intermediate fields
// in unknown_fields to check if field #field_number is set on the
// innermost message. Returns false and sets an error if so.
@@ -1915,18 +2068,18 @@ class DescriptorBuilder {
// Validates the value for the option field of the currently interpreted
// option and then sets it on the unknown_field.
bool SetOptionValue(const FieldDescriptor* option_field,
- UnknownField* unknown_field);
+ UnknownFieldSet* unknown_fields);
// Convenience functions to set an int field the right way, depending on
// its wire type (a single int CppType can represent multiple wire types).
- void SetInt32(int32 value, FieldDescriptor::Type type,
- UnknownField* unknown_field);
- void SetInt64(int64 value, FieldDescriptor::Type type,
- UnknownField* unknown_field);
- void SetUInt32(uint32 value, FieldDescriptor::Type type,
- UnknownField* unknown_field);
- void SetUInt64(uint64 value, FieldDescriptor::Type type,
- UnknownField* unknown_field);
+ void SetInt32(int number, int32 value, FieldDescriptor::Type type,
+ UnknownFieldSet* unknown_fields);
+ void SetInt64(int number, int64 value, FieldDescriptor::Type type,
+ UnknownFieldSet* unknown_fields);
+ void SetUInt32(int number, uint32 value, FieldDescriptor::Type type,
+ UnknownFieldSet* unknown_fields);
+ void SetUInt64(int number, uint64 value, FieldDescriptor::Type type,
+ UnknownFieldSet* unknown_fields);
// A helper function that adds an error at the specified location of the
// option we're currently interpreting, and returns false.
@@ -1966,6 +2119,21 @@ class DescriptorBuilder {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OptionInterpreter);
};
+ // Work-around for broken compilers: According to the C++ standard,
+ // OptionInterpreter should have access to the private members of any class
+ // which has declared DescriptorBuilder as a friend. Unfortunately some old
+ // versions of GCC and other compilers do not implement this correctly. So,
+ // we have to have these intermediate methods to provide access. We also
+ // redundantly declare OptionInterpreter a friend just to make things extra
+ // clear for these bad compilers.
+ friend class OptionInterpreter;
+ static inline bool get_allow_unknown(const DescriptorPool* pool) {
+ return pool->allow_unknown_;
+ }
+ static inline bool get_is_placeholder(const Descriptor* descriptor) {
+ return descriptor->is_placeholder_;
+ }
+
// Must be run only after options have been interpreted.
//
// NOTE: Validation code must only reference the options in the mutable
@@ -1998,7 +2166,7 @@ const FileDescriptor* DescriptorPool::BuildFile(
"DescriptorDatabase. You must instead find a way to get your file "
"into the underlying database.";
GOOGLE_CHECK(mutex_ == NULL); // Implied by the above GOOGLE_CHECK.
- return DescriptorBuilder(this, tables_.get(), NULL).BuildFile(proto, NULL);
+ return DescriptorBuilder(this, tables_.get(), NULL).BuildFile(proto);
}
const FileDescriptor* DescriptorPool::BuildFileCollectingErrors(
@@ -2010,73 +2178,14 @@ const FileDescriptor* DescriptorPool::BuildFileCollectingErrors(
"into the underlying database.";
GOOGLE_CHECK(mutex_ == NULL); // Implied by the above GOOGLE_CHECK.
return DescriptorBuilder(this, tables_.get(),
- error_collector).BuildFile(proto, NULL);
+ error_collector).BuildFile(proto);
}
const FileDescriptor* DescriptorPool::BuildFileFromDatabase(
const FileDescriptorProto& proto) const {
mutex_->AssertHeld();
return DescriptorBuilder(this, tables_.get(),
- default_error_collector_).BuildFile(proto, NULL);
-}
-
-const FileDescriptor* DescriptorPool::InternalBuildGeneratedFile(
- const void* data, int size,
- InternalDescriptorAssigner descriptor_assigner) {
- // So, this function is called in the process of initializing the
- // descriptors for generated proto classes. Each generated .pb.cc file
- // has an internal procedure called BuildDescriptors() which is called the
- // first time one of its descriptors is accessed, and that function calls
- // this one in order to parse the raw bytes of the FileDescriptorProto
- // representing the file.
- //
- // Note, though, that FileDescriptorProto is itself a generated protocol
- // message. So, when we attempt to construct one below, it will attempt
- // to initialize its own descriptors via its own BuildDescriptors() method.
- // This will in turn cause InternalBuildGeneratedFile() to build
- // descriptor.proto's descriptors.
- //
- // We are saved from an infinite loop by the fact that BuildDescriptors()
- // only does anything the first time it is called. That is, the first few
- // lines of any BuildDescriptors() procedure look like this:
- // void BuildDescriptors() {
- // static bool already_here = false;
- // if (already_here) return;
- // already_here = true;
- // ...
- // So, when descriptor.pb.cc's BuildDescriptors() is called recursively, it
- // will end up just returning without doing anything. The result is that
- // all of the descriptors for FileDescriptorProto and friends will just be
- // NULL.
- //
- // Luckily, it turns out that our limited use of FileDescriptorProto within
- // InternalBuildGeneratedFile() does not require that its descriptors be
- // initialized. So, this ends up working. As soon as
- // InternalBuildGeneratedFile() returns, the descriptors will be initialized
- // by the original call to BuildDescriptors(), and everything will be happy
- // again.
- //
- // If this turns out to be too fragile a hack, there are other ways we
- // can accomplish bootstrapping here (like building the descriptor for
- // descriptor.proto manually), but if this works then it's a lot easier.
- //
- // Note that because this is only triggered at static initialization time,
- // there are no thread-safety concerns here.
- GOOGLE_CHECK(fallback_database_ == NULL)
- << "Cannot call BuildFile on a DescriptorPool that uses a "
- "DescriptorDatabase. You must instead find a way to get your file "
- "into the underlying database.";
- GOOGLE_CHECK(mutex_ == NULL); // Implied by the above GOOGLE_CHECK.
-
- FileDescriptorProto proto;
- GOOGLE_CHECK(proto.ParseFromArray(data, size));
- const FileDescriptor* result =
- DescriptorBuilder(this, tables_.get(), NULL).BuildFile(
- proto, descriptor_assigner);
-
- GOOGLE_CHECK(result != NULL);
-
- return result;
+ default_error_collector_).BuildFile(proto);
}
DescriptorBuilder::DescriptorBuilder(
@@ -2189,8 +2298,8 @@ Symbol DescriptorBuilder::FindSymbol(const string& name) {
return kNullSymbol;
}
-Symbol DescriptorBuilder::LookupSymbol(
- const string& name, const string& relative_to) {
+Symbol DescriptorBuilder::LookupSymbolNoPlaceholder(
+ const string& name, const string& relative_to, ResolveMode resolve_mode) {
possible_undeclared_dependency_ = NULL;
if (name.size() > 0 && name[0] == '.') {
@@ -2237,11 +2346,20 @@ Symbol DescriptorBuilder::LookupSymbol(
if (first_part_of_name.size() < name.size()) {
// name is a compound symbol, of which we only found the first part.
// Now try to look up the rest of it.
- scope_to_try.append(name, first_part_of_name.size(),
- name.size() - first_part_of_name.size());
- result = FindSymbol(scope_to_try);
+ if (result.IsAggregate()) {
+ scope_to_try.append(name, first_part_of_name.size(),
+ name.size() - first_part_of_name.size());
+ return FindSymbol(scope_to_try);
+ } else {
+ // We found a symbol but it's not an aggregate. Continue the loop.
+ }
+ } else {
+ if (resolve_mode == LOOKUP_TYPES && !result.IsType()) {
+ // We found a symbol but it's not a type. Continue the loop.
+ } else {
+ return result;
+ }
}
- return result;
}
// Not found. Remove the name so we can try again.
@@ -2249,6 +2367,134 @@ Symbol DescriptorBuilder::LookupSymbol(
}
}
+Symbol DescriptorBuilder::LookupSymbol(
+ const string& name, const string& relative_to,
+ PlaceholderType placeholder_type, ResolveMode resolve_mode) {
+ Symbol result = LookupSymbolNoPlaceholder(
+ name, relative_to, resolve_mode);
+ if (result.IsNull() && pool_->allow_unknown_) {
+ // Not found, but AllowUnknownDependencies() is enabled. Return a
+ // placeholder instead.
+ result = NewPlaceholder(name, placeholder_type);
+ }
+ return result;
+}
+
+Symbol DescriptorBuilder::NewPlaceholder(const string& name,
+ PlaceholderType placeholder_type) {
+ // Compute names.
+ const string* placeholder_full_name;
+ const string* placeholder_name;
+ const string* placeholder_package;
+
+ if (!ValidateQualifiedName(name)) return kNullSymbol;
+ if (name[0] == '.') {
+ // Fully-qualified.
+ placeholder_full_name = tables_->AllocateString(name.substr(1));
+ } else {
+ placeholder_full_name = tables_->AllocateString(name);
+ }
+
+ string::size_type dotpos = placeholder_full_name->find_last_of('.');
+ if (dotpos != string::npos) {
+ placeholder_package = tables_->AllocateString(
+ placeholder_full_name->substr(0, dotpos));
+ placeholder_name = tables_->AllocateString(
+ placeholder_full_name->substr(dotpos + 1));
+ } else {
+ placeholder_package = &kEmptyString;
+ placeholder_name = placeholder_full_name;
+ }
+
+ // Create the placeholders.
+ FileDescriptor* placeholder_file = tables_->Allocate<FileDescriptor>();
+ memset(placeholder_file, 0, sizeof(*placeholder_file));
+
+ placeholder_file->name_ =
+ tables_->AllocateString(*placeholder_full_name + ".placeholder.proto");
+ placeholder_file->package_ = placeholder_package;
+ placeholder_file->pool_ = pool_;
+ placeholder_file->options_ = &FileOptions::default_instance();
+ placeholder_file->tables_ = &FileDescriptorTables::kEmpty;
+ // All other fields are zero or NULL.
+
+ if (placeholder_type == PLACEHOLDER_ENUM) {
+ placeholder_file->enum_type_count_ = 1;
+ placeholder_file->enum_types_ =
+ tables_->AllocateArray<EnumDescriptor>(1);
+
+ EnumDescriptor* placeholder_enum = &placeholder_file->enum_types_[0];
+ memset(placeholder_enum, 0, sizeof(*placeholder_enum));
+
+ placeholder_enum->full_name_ = placeholder_full_name;
+ placeholder_enum->name_ = placeholder_name;
+ placeholder_enum->file_ = placeholder_file;
+ placeholder_enum->options_ = &EnumOptions::default_instance();
+ placeholder_enum->is_placeholder_ = true;
+ placeholder_enum->is_unqualified_placeholder_ = (name[0] != '.');
+
+ // Enums must have at least one value.
+ placeholder_enum->value_count_ = 1;
+ placeholder_enum->values_ = tables_->AllocateArray<EnumValueDescriptor>(1);
+
+ EnumValueDescriptor* placeholder_value = &placeholder_enum->values_[0];
+ memset(placeholder_value, 0, sizeof(*placeholder_value));
+
+ placeholder_value->name_ = tables_->AllocateString("PLACEHOLDER_VALUE");
+ // Note that enum value names are siblings of their type, not children.
+ placeholder_value->full_name_ =
+ placeholder_package->empty() ? placeholder_value->name_ :
+ tables_->AllocateString(*placeholder_package + ".PLACEHOLDER_VALUE");
+
+ placeholder_value->number_ = 0;
+ placeholder_value->type_ = placeholder_enum;
+ placeholder_value->options_ = &EnumValueOptions::default_instance();
+
+ return Symbol(placeholder_enum);
+ } else {
+ placeholder_file->message_type_count_ = 1;
+ placeholder_file->message_types_ =
+ tables_->AllocateArray<Descriptor>(1);
+
+ Descriptor* placeholder_message = &placeholder_file->message_types_[0];
+ memset(placeholder_message, 0, sizeof(*placeholder_message));
+
+ placeholder_message->full_name_ = placeholder_full_name;
+ placeholder_message->name_ = placeholder_name;
+ placeholder_message->file_ = placeholder_file;
+ placeholder_message->options_ = &MessageOptions::default_instance();
+ placeholder_message->is_placeholder_ = true;
+ placeholder_message->is_unqualified_placeholder_ = (name[0] != '.');
+
+ if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) {
+ placeholder_message->extension_range_count_ = 1;
+ placeholder_message->extension_ranges_ =
+ tables_->AllocateArray<Descriptor::ExtensionRange>(1);
+ placeholder_message->extension_ranges_->start = 1;
+ // kMaxNumber + 1 because ExtensionRange::end is exclusive.
+ placeholder_message->extension_ranges_->end =
+ FieldDescriptor::kMaxNumber + 1;
+ }
+
+ return Symbol(placeholder_message);
+ }
+}
+
+const FileDescriptor* DescriptorBuilder::NewPlaceholderFile(
+ const string& name) {
+ FileDescriptor* placeholder = tables_->Allocate<FileDescriptor>();
+ memset(placeholder, 0, sizeof(*placeholder));
+
+ placeholder->name_ = tables_->AllocateString(name);
+ placeholder->package_ = &kEmptyString;
+ placeholder->pool_ = pool_;
+ placeholder->options_ = &FileOptions::default_instance();
+ placeholder->tables_ = &FileDescriptorTables::kEmpty;
+ // All other fields are zero or NULL.
+
+ return placeholder;
+}
+
bool DescriptorBuilder::AddSymbol(
const string& full_name, const void* parent, const string& name,
const Message& proto, Symbol symbol) {
@@ -2256,7 +2502,13 @@ bool DescriptorBuilder::AddSymbol(
// Use its file as the parent instead.
if (parent == NULL) parent = file_;
- if (tables_->AddSymbol(full_name, parent, name, symbol)) {
+ if (tables_->AddSymbol(full_name, symbol)) {
+ if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) {
+ GOOGLE_LOG(DFATAL) << "\"" << full_name << "\" not previously defined in "
+ "symbols_by_name_, but was defined in symbols_by_parent_; "
+ "this shouldn't be possible.";
+ return false;
+ }
return true;
} else {
const FileDescriptor* other_file = tables_->FindSymbol(full_name).GetFile();
@@ -2283,7 +2535,7 @@ bool DescriptorBuilder::AddSymbol(
void DescriptorBuilder::AddPackage(
const string& name, const Message& proto, const FileDescriptor* file) {
- if (tables_->AddSymbol(name, NULL, name, Symbol(file))) {
+ if (tables_->AddSymbol(name, Symbol(file))) {
// Success. Also add parent package, if any.
string::size_type dot_pos = name.find_last_of('.');
if (dot_pos == string::npos) {
@@ -2327,6 +2579,27 @@ void DescriptorBuilder::ValidateSymbolName(
}
}
+bool DescriptorBuilder::ValidateQualifiedName(const string& name) {
+ bool last_was_period = false;
+
+ for (int i = 0; i < name.size(); i++) {
+ // I don't trust isalnum() due to locales. :(
+ if (('a' <= name[i] && name[i] <= 'z') ||
+ ('A' <= name[i] && name[i] <= 'Z') ||
+ ('0' <= name[i] && name[i] <= '9') ||
+ (name[i] == '_')) {
+ last_was_period = false;
+ } else if (name[i] == '.') {
+ if (last_was_period) return false;
+ last_was_period = true;
+ } else {
+ return false;
+ }
+ }
+
+ return !name.empty() && !last_was_period;
+}
+
// -------------------------------------------------------------------
// This generic implementation is good for all descriptors except
@@ -2351,12 +2624,26 @@ template<class DescriptorT> void DescriptorBuilder::AllocateOptionsImpl(
const string& element_name,
const typename DescriptorT::OptionsType& orig_options,
DescriptorT* descriptor) {
- typename DescriptorT::OptionsType* options =
- tables_->AllocateMessage<typename DescriptorT::OptionsType>();
+ // We need to use a dummy pointer to work around a bug in older versions of
+ // GCC. Otherwise, the following two lines could be replaced with:
+ // typename DescriptorT::OptionsType* options =
+ // tables_->AllocateMessage<typename DescriptorT::OptionsType>();
+ typename DescriptorT::OptionsType* const dummy = NULL;
+ typename DescriptorT::OptionsType* options = tables_->AllocateMessage(dummy);
options->CopyFrom(orig_options);
- options_to_interpret_.push_back(
- OptionsToInterpret(name_scope, element_name, &orig_options, options));
descriptor->options_ = options;
+
+ // Don't add to options_to_interpret_ unless there were uninterpreted
+ // options. This not only avoids unnecessary work, but prevents a
+ // bootstrapping problem when building descriptors for descriptor.proto.
+ // descriptor.proto does not contain any uninterpreted options, but
+ // attempting to interpret options anyway will cause
+ // OptionsType::GetDescriptor() to be called which may then deadlock since
+ // we're still trying to build it.
+ if (options->uninterpreted_option_size() > 0) {
+ options_to_interpret_.push_back(
+ OptionsToInterpret(name_scope, element_name, &orig_options, options));
+ }
}
@@ -2370,10 +2657,27 @@ template<class DescriptorT> void DescriptorBuilder::AllocateOptionsImpl(
}
const FileDescriptor* DescriptorBuilder::BuildFile(
- const FileDescriptorProto& proto,
- DescriptorPool::InternalDescriptorAssigner descriptor_assigner) {
+ const FileDescriptorProto& proto) {
filename_ = proto.name();
+ // Check if the file already exists and is identical to the one being built.
+ // Note: This only works if the input is canonical -- that is, it
+ // fully-qualifies all type names, has no UninterpretedOptions, etc.
+ // This is fine, because this idempotency "feature" really only exists to
+ // accomodate one hack in the proto1->proto2 migration layer.
+ const FileDescriptor* existing_file = tables_->FindFile(filename_);
+ if (existing_file != NULL) {
+ // File already in pool. Compare the existing one to the input.
+ FileDescriptorProto existing_proto;
+ existing_file->CopyTo(&existing_proto);
+ if (existing_proto.SerializeAsString() == proto.SerializeAsString()) {
+ // They're identical. Return the existing descriptor.
+ return existing_file;
+ }
+
+ // Not a match. The error will be detected and handled later.
+ }
+
// Check to see if this file is already on the pending files list.
// TODO(kenton): Allow recursive imports? It may not work with some
// (most?) programming languages. E.g., in C++, a forward declaration
@@ -2420,6 +2724,9 @@ const FileDescriptor* DescriptorBuilder::BuildFile(
FileDescriptor* result = tables_->Allocate<FileDescriptor>();
file_ = result;
+ file_tables_ = tables_->AllocateFileTables();
+ file_->tables_ = file_tables_;
+
if (!proto.has_name()) {
AddError("", proto, DescriptorPool::ErrorCollector::OTHER,
"Missing field: FileDescriptorProto.name.");
@@ -2468,17 +2775,21 @@ const FileDescriptor* DescriptorBuilder::BuildFile(
}
if (dependency == NULL) {
- string message;
- if (pool_->fallback_database_ == NULL) {
- message = "Import \"" + proto.dependency(i) +
- "\" has not been loaded.";
+ if (pool_->allow_unknown_) {
+ dependency = NewPlaceholderFile(proto.dependency(i));
} else {
- message = "Import \"" + proto.dependency(i) +
- "\" was not found or had errors.";
+ string message;
+ if (pool_->fallback_database_ == NULL) {
+ message = "Import \"" + proto.dependency(i) +
+ "\" has not been loaded.";
+ } else {
+ message = "Import \"" + proto.dependency(i) +
+ "\" was not found or had errors.";
+ }
+ AddError(proto.name(), proto,
+ DescriptorPool::ErrorCollector::OTHER,
+ message);
}
- AddError(proto.name(), proto,
- DescriptorPool::ErrorCollector::OTHER,
- message);
}
result->dependencies_[i] = dependency;
@@ -2499,11 +2810,6 @@ const FileDescriptor* DescriptorBuilder::BuildFile(
// Note that the following steps must occur in exactly the specified order.
- // Assign descriptors, if needed.
- if (descriptor_assigner != NULL) {
- (*descriptor_assigner)(result);
- }
-
// Cross-link.
CrossLinkFile(result, proto);
@@ -2549,6 +2855,8 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
result->full_name_ = full_name;
result->file_ = file_;
result->containing_type_ = parent;
+ result->is_placeholder_ = false;
+ result->is_unqualified_placeholder_ = false;
BUILD_ARRAY(proto, result, field , BuildField , result);
BUILD_ARRAY(proto, result, nested_type , BuildMessage , result);
@@ -2648,6 +2956,12 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
result->enum_type_ = NULL;
result->has_default_value_ = proto.has_default_value();
+ if (proto.has_default_value() && result->is_repeated()) {
+ AddError(result->full_name(), proto,
+ DescriptorPool::ErrorCollector::DEFAULT_VALUE,
+ "Repeated fields can't have default values.");
+ }
+
if (proto.has_type()) {
if (proto.has_default_value()) {
char* end_pos = NULL;
@@ -2842,6 +3156,8 @@ void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto,
result->full_name_ = full_name;
result->file_ = file_;
result->containing_type_ = parent;
+ result->is_placeholder_ = false;
+ result->is_unqualified_placeholder_ = false;
if (proto.value_size() == 0) {
// We cannot allow enums with no values because this would mean there
@@ -2899,7 +3215,7 @@ void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto,
// Note: This could fail, but if it does, the error has already been
// reported by the above AddSymbol() call, so we ignore the return code.
bool added_to_inner_scope =
- tables_->AddAliasUnderParent(parent, result->name(), Symbol(result));
+ file_tables_->AddAliasUnderParent(parent, result->name(), Symbol(result));
if (added_to_inner_scope && !added_to_outer_scope) {
// This value did not conflict with any values defined in the same enum,
@@ -2929,7 +3245,7 @@ void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto,
// An enum is allowed to define two numbers that refer to the same value.
// FindValueByNumber() should return the first such value, so we simply
// ignore AddEnumValueByNumber()'s return code.
- tables_->AddEnumValueByNumber(result);
+ file_tables_->AddEnumValueByNumber(result);
}
void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto,
@@ -3043,7 +3359,8 @@ void DescriptorBuilder::CrossLinkField(
}
if (proto.has_extendee()) {
- Symbol extendee = LookupSymbol(proto.extendee(), field->full_name());
+ Symbol extendee = LookupSymbol(proto.extendee(), field->full_name(),
+ PLACEHOLDER_EXTENDABLE_MESSAGE);
if (extendee.IsNull()) {
AddNotDefinedError(field->full_name(), proto,
DescriptorPool::ErrorCollector::EXTENDEE,
@@ -3068,7 +3385,17 @@ void DescriptorBuilder::CrossLinkField(
}
if (proto.has_type_name()) {
- Symbol type = LookupSymbol(proto.type_name(), field->full_name());
+ // Assume we are expecting a message type unless the proto contains some
+ // evidence that it expects an enum type. This only makes a difference if
+ // we end up creating a placeholder.
+ bool expecting_enum = (proto.type() == FieldDescriptorProto::TYPE_ENUM) ||
+ proto.has_default_value();
+
+ Symbol type =
+ LookupSymbol(proto.type_name(), field->full_name(),
+ expecting_enum ? PLACEHOLDER_ENUM : PLACEHOLDER_MESSAGE,
+ LOOKUP_TYPES);
+
if (type.IsNull()) {
AddNotDefinedError(field->full_name(), proto,
DescriptorPool::ErrorCollector::TYPE,
@@ -3113,12 +3440,19 @@ void DescriptorBuilder::CrossLinkField(
}
field->enum_type_ = type.enum_descriptor;
+ if (field->enum_type()->is_placeholder_) {
+ // We can't look up default values for placeholder types. We'll have
+ // to just drop them.
+ field->has_default_value_ = false;
+ }
+
if (field->has_default_value()) {
// We can't just use field->enum_type()->FindValueByName() here
// because that locks the pool's mutex, which we have already locked
// at this point.
Symbol default_value =
- LookupSymbol(proto.default_value(), field->enum_type()->full_name());
+ LookupSymbolNoPlaceholder(proto.default_value(),
+ field->enum_type()->full_name());
if (default_value.type == Symbol::ENUM_VALUE &&
default_value.enum_value_descriptor->type() == field->enum_type()) {
@@ -3150,9 +3484,10 @@ void DescriptorBuilder::CrossLinkField(
// Add the field to the fields-by-number table.
// Note: We have to do this *after* cross-linking because extensions do not
// know their containing type until now.
- if (!tables_->AddFieldByNumber(field)) {
+ if (!file_tables_->AddFieldByNumber(field)) {
const FieldDescriptor* conflicting_field =
- tables_->FindFieldByNumber(field->containing_type(), field->number());
+ file_tables_->FindFieldByNumber(field->containing_type(),
+ field->number());
if (field->is_extension()) {
AddError(field->full_name(), proto,
DescriptorPool::ErrorCollector::NUMBER,
@@ -3172,8 +3507,14 @@ void DescriptorBuilder::CrossLinkField(
}
}
+ if (field->is_extension()) {
+ // No need for error checking: if the extension number collided,
+ // we've already been informed of it by the if() above.
+ tables_->AddExtension(field);
+ }
+
// Add the field to the lowercase-name and camelcase-name tables.
- tables_->AddFieldByStylizedNames(field);
+ file_tables_->AddFieldByStylizedNames(field);
}
void DescriptorBuilder::CrossLinkEnum(
@@ -3397,6 +3738,14 @@ bool DescriptorBuilder::OptionInterpreter::InterpretOptions(
bool failed = false;
options_to_interpret_ = options_to_interpret;
+ // Find the uninterpreted_option field in the mutable copy of the options
+ // and clear them, since we're about to interpret them.
+ const FieldDescriptor* uninterpreted_options_field =
+ options->GetDescriptor()->FindFieldByName("uninterpreted_option");
+ GOOGLE_CHECK(uninterpreted_options_field != NULL)
+ << "No field named \"uninterpreted_option\" in the Options proto.";
+ options->GetReflection()->ClearField(options, uninterpreted_options_field);
+
// Find the uninterpreted_option field in the original options.
const FieldDescriptor* original_uninterpreted_options_field =
original_options->GetDescriptor()->
@@ -3421,17 +3770,6 @@ bool DescriptorBuilder::OptionInterpreter::InterpretOptions(
options_to_interpret_ = NULL;
if (!failed) {
- // Find the uninterpreted_option field in the mutable copy of the options.
- const FieldDescriptor* uninterpreted_options_field =
- options->GetDescriptor()->FindFieldByName("uninterpreted_option");
- GOOGLE_CHECK(uninterpreted_options_field != NULL)
- << "No field named \"uninterpreted_option\" in the Options proto.";
-
- // We don't want to carry around the uninterpreted options, now that we've
- // interpreted them.
- options->GetReflection()->ClearField(options, uninterpreted_options_field);
-
-
// InterpretSingleOption() added the interpreted options in the
// UnknownFieldSet, in case the option isn't yet known to us. Now we
// serialize the options message and deserialize it back. That way, any
@@ -3517,36 +3855,36 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
// you use, so they must be present in the builder's pool.
} else {
debug_msg_name += name_part;
- // Search for the field's descriptor as a regular field in the builder's
- // pool. First we must qualify it by its message name. Note that we use
- // DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
- // DescriptorPool::FindFieldByName() because we're already holding the
- // pool's mutex, and the latter method locks it again. We must not
- // enforce dependencies here because we did not enforce dependencies
- // when looking up |descriptor|, and we need the two to match.
- string fully_qualified_name = descriptor->full_name() + "." + name_part;
- Symbol symbol =
- builder_->FindSymbolNotEnforcingDeps(fully_qualified_name);
- if (!symbol.IsNull() && symbol.type == Symbol::FIELD) {
- field = symbol.field_descriptor;
- } else {
- // The field's descriptor was not in the builder's pool, so search for
- // the standard version from the generated pool. We're not holding the
- // generated pool's mutex, so we can search it the straightforward way.
- field = DescriptorPool::generated_pool()->FindFieldByName(
- fully_qualified_name);
- }
+ // Search for the field's descriptor as a regular field.
+ field = descriptor->FindFieldByName(name_part);
}
if (field == NULL) {
- return AddNameError("Option \"" + debug_msg_name + "\" unknown.");
+ if (get_allow_unknown(builder_->pool_)) {
+ // We can't find the option, but AllowUnknownDependencies() is enabled,
+ // so we will just leave it as uninterpreted.
+ AddWithoutInterpreting(*uninterpreted_option_, options);
+ return true;
+ } else {
+ return AddNameError("Option \"" + debug_msg_name + "\" unknown.");
+ }
} else if (field->containing_type() != descriptor) {
- // This can only happen if, due to some insane misconfiguration of the
- // pools, we find the options message in one pool but the field in
- // another. This would probably imply a hefty bug somewhere.
- return AddNameError("Option field \"" + debug_msg_name +
- "\" is not a field or extension of message \"" +
- descriptor->name() + "\".");
+ if (get_is_placeholder(field->containing_type())) {
+ // The field is an extension of a placeholder type, so we can't
+ // reliably verify whether it is a valid extension to use here (e.g.
+ // we don't know if it is an extension of the correct *Options message,
+ // or if it has a valid field number, etc.). Just leave it as
+ // uninterpreted instead.
+ AddWithoutInterpreting(*uninterpreted_option_, options);
+ return true;
+ } else {
+ // This can only happen if, due to some insane misconfiguration of the
+ // pools, we find the options message in one pool but the field in
+ // another. This would probably imply a hefty bug somewhere.
+ return AddNameError("Option field \"" + debug_msg_name +
+ "\" is not a field or extension of message \"" +
+ descriptor->name() + "\".");
+ }
} else if (field->is_repeated()) {
return AddNameError("Option field \"" + debug_msg_name +
"\" is repeated. Repeated options are not "
@@ -3586,7 +3924,7 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
// First set the value on the UnknownFieldSet corresponding to the
// innermost message.
scoped_ptr<UnknownFieldSet> unknown_fields(new UnknownFieldSet());
- if (!SetOptionValue(field, unknown_fields.get()->AddField(field->number()))) {
+ if (!SetOptionValue(field, unknown_fields.get())) {
return false; // SetOptionValue() already added the error.
}
@@ -3599,19 +3937,18 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
switch ((*iter)->type()) {
case FieldDescriptor::TYPE_MESSAGE: {
io::StringOutputStream outstr(
- parent_unknown_fields->AddField((*iter)->number())->
- add_length_delimited());
+ parent_unknown_fields->AddLengthDelimited((*iter)->number()));
io::CodedOutputStream out(&outstr);
- GOOGLE_CHECK(internal::WireFormat::SerializeUnknownFields(*unknown_fields,
- &out))
+ internal::WireFormat::SerializeUnknownFields(*unknown_fields, &out);
+ GOOGLE_CHECK(!out.HadError())
<< "Unexpected failure while serializing option submessage "
<< debug_msg_name << "\".";
break;
}
case FieldDescriptor::TYPE_GROUP: {
- parent_unknown_fields->AddField((*iter)->number())->
- add_group()->MergeFrom(*unknown_fields);
+ parent_unknown_fields->AddGroup((*iter)->number())
+ ->MergeFrom(*unknown_fields);
break;
}
@@ -3631,56 +3968,73 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
return true;
}
+void DescriptorBuilder::OptionInterpreter::AddWithoutInterpreting(
+ const UninterpretedOption& uninterpreted_option, Message* options) {
+ const FieldDescriptor* field =
+ options->GetDescriptor()->FindFieldByName("uninterpreted_option");
+ GOOGLE_CHECK(field != NULL);
+
+ options->GetReflection()->AddMessage(options, field)
+ ->CopyFrom(uninterpreted_option);
+}
+
bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet(
vector<const FieldDescriptor*>::const_iterator intermediate_fields_iter,
vector<const FieldDescriptor*>::const_iterator intermediate_fields_end,
const FieldDescriptor* innermost_field, const string& debug_msg_name,
const UnknownFieldSet& unknown_fields) {
+ // We do linear searches of the UnknownFieldSet and its sub-groups. This
+ // should be fine since it's unlikely that any one options structure will
+ // contain more than a handful of options.
+
if (intermediate_fields_iter == intermediate_fields_end) {
// We're at the innermost submessage.
- if (unknown_fields.FindFieldByNumber(innermost_field->number()) != NULL) {
- return AddNameError("Option \"" + debug_msg_name +
- "\" was already set.");
- } else {
- return true;
+ for (int i = 0; i < unknown_fields.field_count(); i++) {
+ if (unknown_fields.field(i).number() == innermost_field->number()) {
+ return AddNameError("Option \"" + debug_msg_name +
+ "\" was already set.");
+ }
}
+ return true;
}
- const UnknownField* unknown_field = unknown_fields.FindFieldByNumber(
- (*intermediate_fields_iter)->number());
- if (unknown_field != NULL) {
- FieldDescriptor::Type type = (*intermediate_fields_iter)->type();
- // Recurse into the next submessage.
- ++intermediate_fields_iter;
- switch (type) {
- case FieldDescriptor::TYPE_MESSAGE:
- for (int i = 0; i < unknown_field->length_delimited_size(); ++i) {
- UnknownFieldSet intermediate_unknown_fields;
- if (intermediate_unknown_fields.ParseFromString(
- unknown_field->length_delimited(i)) &&
- !ExamineIfOptionIsSet(intermediate_fields_iter,
- intermediate_fields_end,
- innermost_field, debug_msg_name,
- intermediate_unknown_fields)) {
- return false; // Error already added.
+ for (int i = 0; i < unknown_fields.field_count(); i++) {
+ if (unknown_fields.field(i).number() ==
+ (*intermediate_fields_iter)->number()) {
+ const UnknownField* unknown_field = &unknown_fields.field(i);
+ FieldDescriptor::Type type = (*intermediate_fields_iter)->type();
+ // Recurse into the next submessage.
+ ++intermediate_fields_iter;
+ switch (type) {
+ case FieldDescriptor::TYPE_MESSAGE:
+ if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) {
+ UnknownFieldSet intermediate_unknown_fields;
+ if (intermediate_unknown_fields.ParseFromString(
+ unknown_field->length_delimited()) &&
+ !ExamineIfOptionIsSet(intermediate_fields_iter,
+ intermediate_fields_end,
+ innermost_field, debug_msg_name,
+ intermediate_unknown_fields)) {
+ return false; // Error already added.
+ }
}
- }
- break;
+ break;
- case FieldDescriptor::TYPE_GROUP:
- for (int i = 0; i < unknown_field->group_size(); ++i) {
- if (!ExamineIfOptionIsSet(intermediate_fields_iter,
- intermediate_fields_end,
- innermost_field, debug_msg_name,
- unknown_field->group(i))) {
- return false; // Error already added.
+ case FieldDescriptor::TYPE_GROUP:
+ if (unknown_field->type() == UnknownField::TYPE_GROUP) {
+ if (!ExamineIfOptionIsSet(intermediate_fields_iter,
+ intermediate_fields_end,
+ innermost_field, debug_msg_name,
+ unknown_field->group())) {
+ return false; // Error already added.
+ }
}
- }
- break;
+ break;
- default:
- GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: " << type;
- return false;
+ default:
+ GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: " << type;
+ return false;
+ }
}
}
return true;
@@ -3688,7 +4042,7 @@ bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet(
bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
const FieldDescriptor* option_field,
- UnknownField* unknown_field) {
+ UnknownFieldSet* unknown_fields) {
// We switch on the CppType to validate.
switch (option_field->cpp_type()) {
@@ -3699,8 +4053,9 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
return AddValueError("Value out of range for int32 option \"" +
option_field->full_name() + "\".");
} else {
- SetInt32(uninterpreted_option_->positive_int_value(),
- option_field->type(), unknown_field);
+ SetInt32(option_field->number(),
+ uninterpreted_option_->positive_int_value(),
+ option_field->type(), unknown_fields);
}
} else if (uninterpreted_option_->has_negative_int_value()) {
if (uninterpreted_option_->negative_int_value() <
@@ -3708,8 +4063,9 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
return AddValueError("Value out of range for int32 option \"" +
option_field->full_name() + "\".");
} else {
- SetInt32(uninterpreted_option_->negative_int_value(),
- option_field->type(), unknown_field);
+ SetInt32(option_field->number(),
+ uninterpreted_option_->negative_int_value(),
+ option_field->type(), unknown_fields);
}
} else {
return AddValueError("Value must be integer for int32 option \"" +
@@ -3724,12 +4080,14 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
return AddValueError("Value out of range for int64 option \"" +
option_field->full_name() + "\".");
} else {
- SetInt64(uninterpreted_option_->positive_int_value(),
- option_field->type(), unknown_field);
+ SetInt64(option_field->number(),
+ uninterpreted_option_->positive_int_value(),
+ option_field->type(), unknown_fields);
}
} else if (uninterpreted_option_->has_negative_int_value()) {
- SetInt64(uninterpreted_option_->negative_int_value(),
- option_field->type(), unknown_field);
+ SetInt64(option_field->number(),
+ uninterpreted_option_->negative_int_value(),
+ option_field->type(), unknown_fields);
} else {
return AddValueError("Value must be integer for int64 option \"" +
option_field->full_name() + "\".");
@@ -3742,8 +4100,9 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
return AddValueError("Value out of range for uint32 option \"" +
option_field->name() + "\".");
} else {
- SetUInt32(uninterpreted_option_->positive_int_value(),
- option_field->type(), unknown_field);
+ SetUInt32(option_field->number(),
+ uninterpreted_option_->positive_int_value(),
+ option_field->type(), unknown_fields);
}
} else {
return AddValueError("Value must be non-negative integer for uint32 "
@@ -3753,8 +4112,9 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
case FieldDescriptor::CPPTYPE_UINT64:
if (uninterpreted_option_->has_positive_int_value()) {
- SetUInt64(uninterpreted_option_->positive_int_value(),
- option_field->type(), unknown_field);
+ SetUInt64(option_field->number(),
+ uninterpreted_option_->positive_int_value(),
+ option_field->type(), unknown_fields);
} else {
return AddValueError("Value must be non-negative integer for uint64 "
"option \"" + option_field->full_name() + "\".");
@@ -3773,7 +4133,7 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
return AddValueError("Value must be number for float option \"" +
option_field->full_name() + "\".");
}
- unknown_field->add_fixed32(
+ unknown_fields->AddFixed32(option_field->number(),
google::protobuf::internal::WireFormat::EncodeFloat(value));
break;
}
@@ -3790,7 +4150,7 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
return AddValueError("Value must be number for double option \"" +
option_field->full_name() + "\".");
}
- unknown_field->add_fixed64(
+ unknown_fields->AddFixed64(option_field->number(),
google::protobuf::internal::WireFormat::EncodeDouble(value));
break;
}
@@ -3809,7 +4169,7 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
return AddValueError("Value must be \"true\" or \"false\" for boolean "
"option \"" + option_field->full_name() + "\".");
}
- unknown_field->add_varint(value);
+ unknown_fields->AddVarint(option_field->number(), value);
break;
case FieldDescriptor::CPPTYPE_ENUM: {
@@ -3859,8 +4219,8 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
} else {
// Sign-extension is not a problem, since we cast directly from int32 to
// uint64, without first going through uint32.
- unknown_field->add_varint(static_cast<uint64>(
- static_cast<int64>(enum_value->number())));
+ unknown_fields->AddVarint(option_field->number(),
+ static_cast<uint64>(static_cast<int64>(enum_value->number())));
}
break;
}
@@ -3871,7 +4231,7 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
"\"" + option_field->full_name() + "\".");
}
// The string has already been unquoted and unescaped by the parser.
- unknown_field->add_length_delimited(
+ unknown_fields->AddLengthDelimited(option_field->number(),
uninterpreted_option_->string_value());
break;
@@ -3888,19 +4248,20 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
return true;
}
-void DescriptorBuilder::OptionInterpreter::SetInt32(int32 value,
- FieldDescriptor::Type type, UnknownField* unknown_field) {
+void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value,
+ FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
switch (type) {
case FieldDescriptor::TYPE_INT32:
- unknown_field->add_varint(static_cast<uint64>(static_cast<int64>(value)));
+ unknown_fields->AddVarint(number,
+ static_cast<uint64>(static_cast<int64>(value)));
break;
case FieldDescriptor::TYPE_SFIXED32:
- unknown_field->add_fixed32(static_cast<uint32>(value));
+ unknown_fields->AddFixed32(number, static_cast<uint32>(value));
break;
case FieldDescriptor::TYPE_SINT32:
- unknown_field->add_varint(
+ unknown_fields->AddVarint(number,
google::protobuf::internal::WireFormat::ZigZagEncode32(value));
break;
@@ -3910,19 +4271,19 @@ void DescriptorBuilder::OptionInterpreter::SetInt32(int32 value,
}
}
-void DescriptorBuilder::OptionInterpreter::SetInt64(int64 value,
- FieldDescriptor::Type type, UnknownField* unknown_field) {
+void DescriptorBuilder::OptionInterpreter::SetInt64(int number, int64 value,
+ FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
switch (type) {
case FieldDescriptor::TYPE_INT64:
- unknown_field->add_varint(static_cast<uint64>(value));
+ unknown_fields->AddVarint(number, static_cast<uint64>(value));
break;
case FieldDescriptor::TYPE_SFIXED64:
- unknown_field->add_fixed64(static_cast<uint64>(value));
+ unknown_fields->AddFixed64(number, static_cast<uint64>(value));
break;
case FieldDescriptor::TYPE_SINT64:
- unknown_field->add_varint(
+ unknown_fields->AddVarint(number,
google::protobuf::internal::WireFormat::ZigZagEncode64(value));
break;
@@ -3932,15 +4293,15 @@ void DescriptorBuilder::OptionInterpreter::SetInt64(int64 value,
}
}
-void DescriptorBuilder::OptionInterpreter::SetUInt32(uint32 value,
- FieldDescriptor::Type type, UnknownField* unknown_field) {
+void DescriptorBuilder::OptionInterpreter::SetUInt32(int number, uint32 value,
+ FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
switch (type) {
case FieldDescriptor::TYPE_UINT32:
- unknown_field->add_varint(static_cast<uint64>(value));
+ unknown_fields->AddVarint(number, static_cast<uint64>(value));
break;
case FieldDescriptor::TYPE_FIXED32:
- unknown_field->add_fixed32(static_cast<uint32>(value));
+ unknown_fields->AddFixed32(number, static_cast<uint32>(value));
break;
default:
@@ -3949,15 +4310,15 @@ void DescriptorBuilder::OptionInterpreter::SetUInt32(uint32 value,
}
}
-void DescriptorBuilder::OptionInterpreter::SetUInt64(uint64 value,
- FieldDescriptor::Type type, UnknownField* unknown_field) {
+void DescriptorBuilder::OptionInterpreter::SetUInt64(int number, uint64 value,
+ FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) {
switch (type) {
case FieldDescriptor::TYPE_UINT64:
- unknown_field->add_varint(value);
+ unknown_fields->AddVarint(number, value);
break;
case FieldDescriptor::TYPE_FIXED64:
- unknown_field->add_fixed64(value);
+ unknown_fields->AddFixed64(number, value);
break;
default:
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 918aafbc..5b629a5d 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -55,6 +55,7 @@
#define GOOGLE_PROTOBUF_DESCRIPTOR_H__
#include <string>
+#include <vector>
#include <google/protobuf/stubs/common.h>
@@ -94,6 +95,7 @@ class Message;
// Defined in descriptor.cc
class DescriptorBuilder;
+class FileDescriptorTables;
// Defined in unknown_field_set.h.
class UnknownField;
@@ -246,6 +248,12 @@ class LIBPROTOBUF_EXPORT Descriptor {
const FileDescriptor* file_;
const Descriptor* containing_type_;
const MessageOptions* options_;
+
+ // True if this is a placeholder for an unknown type.
+ bool is_placeholder_;
+ // True if this is a placeholder and the type name wasn't fully-qualified.
+ bool is_unqualified_placeholder_;
+
int field_count_;
FieldDescriptor* fields_;
int nested_type_count_;
@@ -256,12 +264,16 @@ class LIBPROTOBUF_EXPORT Descriptor {
ExtensionRange* extension_ranges_;
int extension_count_;
FieldDescriptor* extensions_;
+ // IMPORTANT: If you add a new field, make sure to search for all instances
+ // of Allocate<Descriptor>() and AllocateArray<Descriptor>() in descriptor.cc
+ // and update them to initialize the field.
// Must be constructed using DescriptorPool.
Descriptor() {}
friend class DescriptorBuilder;
friend class EnumDescriptor;
friend class FieldDescriptor;
+ friend class MethodDescriptor;
friend class FileDescriptor;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Descriptor);
};
@@ -458,6 +470,10 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
// See Descriptor::DebugString().
string DebugString() const;
+
+ // Helper method to get the CppType for a particular Type.
+ static CppType TypeToCppType(Type type);
+
private:
typedef FieldOptions OptionsType;
@@ -484,6 +500,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
const EnumDescriptor* enum_type_;
const FieldDescriptor* experimental_map_key_;
const FieldOptions* options_;
+ // IMPORTANT: If you add a new field, make sure to search for all instances
+ // of Allocate<FieldDescriptor>() and AllocateArray<FieldDescriptor>() in
+ // descriptor.cc and update them to initialize the field.
bool has_default_value_;
union {
@@ -568,15 +587,25 @@ class LIBPROTOBUF_EXPORT EnumDescriptor {
const string* name_;
const string* full_name_;
const FileDescriptor* file_;
- int value_count_;
- EnumValueDescriptor* values_;
const Descriptor* containing_type_;
const EnumOptions* options_;
+ // True if this is a placeholder for an unknown type.
+ bool is_placeholder_;
+ // True if this is a placeholder and the type name wasn't fully-qualified.
+ bool is_unqualified_placeholder_;
+
+ int value_count_;
+ EnumValueDescriptor* values_;
+ // IMPORTANT: If you add a new field, make sure to search for all instances
+ // of Allocate<EnumDescriptor>() and AllocateArray<EnumDescriptor>() in
+ // descriptor.cc and update them to initialize the field.
+
// Must be constructed using DescriptorPool.
EnumDescriptor() {}
friend class DescriptorBuilder;
friend class Descriptor;
+ friend class FieldDescriptor;
friend class EnumValueDescriptor;
friend class FileDescriptor;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumDescriptor);
@@ -627,6 +656,9 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptor {
int number_;
const EnumDescriptor* type_;
const EnumValueOptions* options_;
+ // IMPORTANT: If you add a new field, make sure to search for all instances
+ // of Allocate<EnumValueDescriptor>() and AllocateArray<EnumValueDescriptor>()
+ // in descriptor.cc and update them to initialize the field.
// Must be constructed using DescriptorPool.
EnumValueDescriptor() {}
@@ -685,6 +717,9 @@ class LIBPROTOBUF_EXPORT ServiceDescriptor {
const ServiceOptions* options_;
int method_count_;
MethodDescriptor* methods_;
+ // IMPORTANT: If you add a new field, make sure to search for all instances
+ // of Allocate<ServiceDescriptor>() and AllocateArray<ServiceDescriptor>() in
+ // descriptor.cc and update them to initialize the field.
// Must be constructed using DescriptorPool.
ServiceDescriptor() {}
@@ -740,6 +775,9 @@ class LIBPROTOBUF_EXPORT MethodDescriptor {
const Descriptor* input_type_;
const Descriptor* output_type_;
const MethodOptions* options_;
+ // IMPORTANT: If you add a new field, make sure to search for all instances
+ // of Allocate<MethodDescriptor>() and AllocateArray<MethodDescriptor>() in
+ // descriptor.cc and update them to initialize the field.
// Must be constructed using DescriptorPool.
MethodDescriptor() {}
@@ -846,6 +884,11 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
FieldDescriptor* extensions_;
const FileOptions* options_;
+ const FileDescriptorTables* tables_;
+ // IMPORTANT: If you add a new field, make sure to search for all instances
+ // of Allocate<FileDescriptor>() and AllocateArray<FileDescriptor>() in
+ // descriptor.cc and update them to initialize the field.
+
FileDescriptor() {}
friend class DescriptorBuilder;
friend class Descriptor;
@@ -945,6 +988,14 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
const FieldDescriptor* FindExtensionByNumber(const Descriptor* extendee,
int number) const;
+ // Finds extensions of extendee. The extensions will be appended to
+ // out in an undefined order. Only extensions defined directly in
+ // this DescriptorPool or one of its underlays are guaranteed to be
+ // found: extensions defined in the fallback database might not be found
+ // depending on the database implementation.
+ void FindAllExtensions(const Descriptor* extendee,
+ vector<const FieldDescriptor*>* out) const;
+
// Building descriptors --------------------------------------------
// When converting a FileDescriptorProto to a FileDescriptor, various
@@ -996,6 +1047,23 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
const FileDescriptorProto& proto,
ErrorCollector* error_collector);
+ // By default, it is an error if a FileDescriptorProto contains references
+ // to types or other files that are not found in the DescriptorPool (or its
+ // backing DescriptorDatabase, if any). If you call
+ // AllowUnknownDependencies(), however, then unknown types and files
+ // will be replaced by placeholder descriptors. This can allow you to
+ // perform some useful operations with a .proto file even if you do not
+ // have access to other .proto files on which it depends. However, some
+ // heuristics must be used to fill in the gaps in information, and these
+ // can lead to descriptors which are inaccurate. For example, the
+ // DescriptorPool may be forced to guess whether an unknown type is a message
+ // or an enum, as well as what package it resides in. Furthermore,
+ // placeholder types will not be discoverable via FindMessageTypeByName()
+ // and similar methods, which could confuse some descriptor-based algorithms.
+ // Generally, the results of this option should only be relied upon for
+ // debugging purposes.
+ void AllowUnknownDependencies() { allow_unknown_ = true; }
+
// Internal stuff --------------------------------------------------
// These methods MUST NOT be called from outside the proto2 library.
// These methods may contain hidden pitfalls and may be removed in a
@@ -1024,12 +1092,12 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
// underlay for a new DescriptorPool in which you add only the new file.
explicit DescriptorPool(const DescriptorPool* underlay);
- // Called by generated classes at init time. Do NOT call this in your own
- // code! descriptor_assigner, if not NULL, is used to assign global
- // descriptor pointers at the appropriate point during building.
- typedef void (*InternalDescriptorAssigner)(const FileDescriptor*);
- const FileDescriptor* InternalBuildGeneratedFile(
- const void* data, int size, InternalDescriptorAssigner descriptor_assigner);
+ // Called by generated classes at init time to add their descriptors to
+ // generated_pool. Do NOT call this in your own code! filename must be a
+ // permanent string (e.g. a string literal).
+ static void InternalAddGeneratedFile(
+ const void* encoded_file_descriptor, int size);
+
// For internal use only: Gets a non-const pointer to the generated pool.
// This is called at static-initialization time only, so thread-safety is
@@ -1047,6 +1115,11 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
underlay_ = underlay;
}
+ // For internal (unit test) use only: Returns true if a FileDescriptor has
+ // been constructed for the given file, false otherwise. Useful for testing
+ // lazy descriptor initialization behavior.
+ bool InternalIsFileLoaded(const string& filename) const;
+
private:
friend class Descriptor;
friend class FieldDescriptor;
@@ -1085,9 +1158,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
scoped_ptr<Tables> tables_;
bool enforce_dependencies_;
-
- // See InternalBuildGeneratedFile().
- const void* last_internal_build_generated_file_call_;
+ bool allow_unknown_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPool);
};
@@ -1267,6 +1338,10 @@ inline FieldDescriptor::CppType FieldDescriptor::cpp_type() const {
return kTypeToCppTypeMap[type_];
}
+inline FieldDescriptor::CppType FieldDescriptor::TypeToCppType(Type type) {
+ return kTypeToCppTypeMap[type];
+}
+
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 8d1b7e3e..6f0b5b54 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -1,6 +1,7 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
#include "google/protobuf/descriptor.pb.h"
+#include <google/protobuf/stubs/once.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/reflection_ops.h>
@@ -73,9 +74,13 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
} // namespace
-void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(const ::google::protobuf::FileDescriptor* file) {
+void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
+ protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ const ::google::protobuf::FileDescriptor* file =
+ ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+ "google/protobuf/descriptor.proto");
+ GOOGLE_CHECK(file != NULL);
FileDescriptorSet_descriptor_ = file->message_type(0);
- FileDescriptorSet::default_instance_ = new FileDescriptorSet();
static const int FileDescriptorSet_offsets_[1] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, file_),
};
@@ -88,11 +93,9 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(FileDescriptorSet));
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- FileDescriptorSet_descriptor_, FileDescriptorSet::default_instance_);
FileDescriptorProto_descriptor_ = file->message_type(1);
- FileDescriptorProto::default_instance_ = new FileDescriptorProto();
static const int FileDescriptorProto_offsets_[8] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, package_),
@@ -112,11 +115,9 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(FileDescriptorProto));
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- FileDescriptorProto_descriptor_, FileDescriptorProto::default_instance_);
DescriptorProto_descriptor_ = file->message_type(2);
- DescriptorProto::default_instance_ = new DescriptorProto();
static const int DescriptorProto_offsets_[7] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, field_),
@@ -135,9 +136,9 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(DescriptorProto));
DescriptorProto_ExtensionRange_descriptor_ = DescriptorProto_descriptor_->nested_type(0);
- DescriptorProto_ExtensionRange::default_instance_ = new DescriptorProto_ExtensionRange();
static const int DescriptorProto_ExtensionRange_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, start_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, end_),
@@ -151,13 +152,9 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(DescriptorProto_ExtensionRange));
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- DescriptorProto_ExtensionRange_descriptor_, DescriptorProto_ExtensionRange::default_instance_);
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- DescriptorProto_descriptor_, DescriptorProto::default_instance_);
FieldDescriptorProto_descriptor_ = file->message_type(3);
- FieldDescriptorProto::default_instance_ = new FieldDescriptorProto();
static const int FieldDescriptorProto_offsets_[8] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, number_),
@@ -177,13 +174,11 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(FieldDescriptorProto));
FieldDescriptorProto_Type_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(0);
FieldDescriptorProto_Label_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(1);
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- FieldDescriptorProto_descriptor_, FieldDescriptorProto::default_instance_);
EnumDescriptorProto_descriptor_ = file->message_type(4);
- EnumDescriptorProto::default_instance_ = new EnumDescriptorProto();
static const int EnumDescriptorProto_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, value_),
@@ -198,11 +193,9 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(EnumDescriptorProto));
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- EnumDescriptorProto_descriptor_, EnumDescriptorProto::default_instance_);
EnumValueDescriptorProto_descriptor_ = file->message_type(5);
- EnumValueDescriptorProto::default_instance_ = new EnumValueDescriptorProto();
static const int EnumValueDescriptorProto_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, number_),
@@ -217,11 +210,9 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(EnumValueDescriptorProto));
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- EnumValueDescriptorProto_descriptor_, EnumValueDescriptorProto::default_instance_);
ServiceDescriptorProto_descriptor_ = file->message_type(6);
- ServiceDescriptorProto::default_instance_ = new ServiceDescriptorProto();
static const int ServiceDescriptorProto_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, method_),
@@ -236,11 +227,9 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(ServiceDescriptorProto));
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- ServiceDescriptorProto_descriptor_, ServiceDescriptorProto::default_instance_);
MethodDescriptorProto_descriptor_ = file->message_type(7);
- MethodDescriptorProto::default_instance_ = new MethodDescriptorProto();
static const int MethodDescriptorProto_offsets_[4] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, input_type_),
@@ -256,11 +245,9 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(MethodDescriptorProto));
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- MethodDescriptorProto_descriptor_, MethodDescriptorProto::default_instance_);
FileOptions_descriptor_ = file->message_type(8);
- FileOptions::default_instance_ = new FileOptions();
static const int FileOptions_offsets_[5] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_),
@@ -277,12 +264,10 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _unknown_fields_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _extensions_),
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(FileOptions));
FileOptions_OptimizeMode_descriptor_ = FileOptions_descriptor_->enum_type(0);
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- FileOptions_descriptor_, FileOptions::default_instance_);
MessageOptions_descriptor_ = file->message_type(9);
- MessageOptions::default_instance_ = new MessageOptions();
static const int MessageOptions_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, message_set_wire_format_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, uninterpreted_option_),
@@ -296,14 +281,13 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _unknown_fields_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _extensions_),
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(MessageOptions));
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- MessageOptions_descriptor_, MessageOptions::default_instance_);
FieldOptions_descriptor_ = file->message_type(10);
- FieldOptions::default_instance_ = new FieldOptions();
- static const int FieldOptions_offsets_[4] = {
+ static const int FieldOptions_offsets_[5] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, packed_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, deprecated_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, experimental_map_key_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, uninterpreted_option_),
};
@@ -316,12 +300,10 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _unknown_fields_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _extensions_),
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(FieldOptions));
FieldOptions_CType_descriptor_ = FieldOptions_descriptor_->enum_type(0);
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- FieldOptions_descriptor_, FieldOptions::default_instance_);
EnumOptions_descriptor_ = file->message_type(11);
- EnumOptions::default_instance_ = new EnumOptions();
static const int EnumOptions_offsets_[1] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, uninterpreted_option_),
};
@@ -334,11 +316,9 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _unknown_fields_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _extensions_),
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(EnumOptions));
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- EnumOptions_descriptor_, EnumOptions::default_instance_);
EnumValueOptions_descriptor_ = file->message_type(12);
- EnumValueOptions::default_instance_ = new EnumValueOptions();
static const int EnumValueOptions_offsets_[1] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, uninterpreted_option_),
};
@@ -351,11 +331,9 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _unknown_fields_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _extensions_),
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(EnumValueOptions));
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- EnumValueOptions_descriptor_, EnumValueOptions::default_instance_);
ServiceOptions_descriptor_ = file->message_type(13);
- ServiceOptions::default_instance_ = new ServiceOptions();
static const int ServiceOptions_offsets_[1] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, uninterpreted_option_),
};
@@ -368,11 +346,9 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _unknown_fields_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _extensions_),
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(ServiceOptions));
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- ServiceOptions_descriptor_, ServiceOptions::default_instance_);
MethodOptions_descriptor_ = file->message_type(14);
- MethodOptions::default_instance_ = new MethodOptions();
static const int MethodOptions_offsets_[1] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, uninterpreted_option_),
};
@@ -385,11 +361,9 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _unknown_fields_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _extensions_),
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(MethodOptions));
- ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- MethodOptions_descriptor_, MethodOptions::default_instance_);
UninterpretedOption_descriptor_ = file->message_type(15);
- UninterpretedOption::default_instance_ = new UninterpretedOption();
static const int UninterpretedOption_offsets_[6] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, identifier_value_),
@@ -407,9 +381,9 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(UninterpretedOption));
UninterpretedOption_NamePart_descriptor_ = UninterpretedOption_descriptor_->nested_type(0);
- UninterpretedOption_NamePart::default_instance_ = new UninterpretedOption_NamePart();
static const int UninterpretedOption_NamePart_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, name_part_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, is_extension_),
@@ -423,40 +397,67 @@ void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescr
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, _unknown_fields_),
-1,
::google::protobuf::DescriptorPool::generated_pool(),
+ ::google::protobuf::MessageFactory::generated_factory(),
sizeof(UninterpretedOption_NamePart));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+ &protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto);
+}
+
+void protobuf_RegisterTypes() {
+ protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- UninterpretedOption_NamePart_descriptor_, UninterpretedOption_NamePart::default_instance_);
+ FileDescriptorSet_descriptor_, &FileDescriptorSet::default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- UninterpretedOption_descriptor_, UninterpretedOption::default_instance_);
- FileDescriptorSet::default_instance_->InitAsDefaultInstance();
- FileDescriptorProto::default_instance_->InitAsDefaultInstance();
- DescriptorProto::default_instance_->InitAsDefaultInstance();
- DescriptorProto_ExtensionRange::default_instance_->InitAsDefaultInstance();
- FieldDescriptorProto::default_instance_->InitAsDefaultInstance();
- EnumDescriptorProto::default_instance_->InitAsDefaultInstance();
- EnumValueDescriptorProto::default_instance_->InitAsDefaultInstance();
- ServiceDescriptorProto::default_instance_->InitAsDefaultInstance();
- MethodDescriptorProto::default_instance_->InitAsDefaultInstance();
- FileOptions::default_instance_->InitAsDefaultInstance();
- MessageOptions::default_instance_->InitAsDefaultInstance();
- FieldOptions::default_instance_->InitAsDefaultInstance();
- EnumOptions::default_instance_->InitAsDefaultInstance();
- EnumValueOptions::default_instance_->InitAsDefaultInstance();
- ServiceOptions::default_instance_->InitAsDefaultInstance();
- MethodOptions::default_instance_->InitAsDefaultInstance();
- UninterpretedOption::default_instance_->InitAsDefaultInstance();
- UninterpretedOption_NamePart::default_instance_->InitAsDefaultInstance();
+ FileDescriptorProto_descriptor_, &FileDescriptorProto::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ DescriptorProto_descriptor_, &DescriptorProto::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ DescriptorProto_ExtensionRange_descriptor_, &DescriptorProto_ExtensionRange::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ FieldDescriptorProto_descriptor_, &FieldDescriptorProto::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ EnumDescriptorProto_descriptor_, &EnumDescriptorProto::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ EnumValueDescriptorProto_descriptor_, &EnumValueDescriptorProto::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ ServiceDescriptorProto_descriptor_, &ServiceDescriptorProto::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ MethodDescriptorProto_descriptor_, &MethodDescriptorProto::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ FileOptions_descriptor_, &FileOptions::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ MessageOptions_descriptor_, &MessageOptions::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ FieldOptions_descriptor_, &FieldOptions::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ EnumOptions_descriptor_, &EnumOptions::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ EnumValueOptions_descriptor_, &EnumValueOptions::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ ServiceOptions_descriptor_, &ServiceOptions::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ MethodOptions_descriptor_, &MethodOptions::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ UninterpretedOption_descriptor_, &UninterpretedOption::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ UninterpretedOption_NamePart_descriptor_, &UninterpretedOption_NamePart::default_instance());
}
-void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto() {
+} // namespace
+
+void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
static bool already_here = false;
if (already_here) return;
already_here = true;
GOOGLE_PROTOBUF_VERIFY_VERSION;
- ::google::protobuf::DescriptorPool* pool =
- ::google::protobuf::DescriptorPool::internal_generated_pool();
- pool->InternalBuildGeneratedFile(
+ ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n google/protobuf/descriptor.proto\022\017goog"
"le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file"
"\030\001 \003(\0132$.google.protobuf.FileDescriptorP"
@@ -509,48 +510,86 @@ void protobuf_BuildDesc_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\"\253\002\n\013FileOptions\022\024\n\014java_"
+ "f.MethodOptions\"\247\002\n\013FileOptions\022\024\n\014java_"
"package\030\001 \001(\t\022\034\n\024java_outer_classname\030\010 "
"\001(\t\022\"\n\023java_multiple_files\030\n \001(\010:\005false\022"
- "J\n\014optimize_for\030\t \001(\0162).google.protobuf."
- "FileOptions.OptimizeMode:\tCODE_SIZE\022C\n\024u"
- "ninterpreted_option\030\347\007 \003(\0132$.google.prot"
- "obuf.UninterpretedOption\"(\n\014OptimizeMode"
- "\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002*\t\010\350\007\020\200\200\200\200\002\"\210\001"
- "\n\016MessageOptions\022&\n\027message_set_wire_for"
- "mat\030\001 \001(\010:\005false\022C\n\024uninterpreted_option"
- "\030\347\007 \003(\0132$.google.protobuf.UninterpretedO"
- "ption*\t\010\350\007\020\200\200\200\200\002\"\345\001\n\014FieldOptions\0222\n\005cty"
- "pe\030\001 \001(\0162#.google.protobuf.FieldOptions."
- "CType\022\016\n\006packed\030\002 \001(\010\022\034\n\024experimental_ma"
- "p_key\030\t \001(\t\022C\n\024uninterpreted_option\030\347\007 \003"
- "(\0132$.google.protobuf.UninterpretedOption"
- "\"#\n\005CType\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*\t\010"
- "\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022C\n\024uninterpreted"
- "_option\030\347\007 \003(\0132$.google.protobuf.Uninter"
- "pretedOption*\t\010\350\007\020\200\200\200\200\002\"b\n\020EnumValueOpti"
- "ons\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo"
- "gle.protobuf.UninterpretedOption*\t\010\350\007\020\200\200"
- "\200\200\002\"`\n\016ServiceOptions\022C\n\024uninterpreted_o"
+ "F\n\014optimize_for\030\t \001(\0162).google.protobuf."
+ "FileOptions.OptimizeMode:\005SPEED\022C\n\024unint"
+ "erpreted_option\030\347\007 \003(\0132$.google.protobuf"
+ ".UninterpretedOption\"(\n\014OptimizeMode\022\t\n\005"
+ "SPEED\020\001\022\r\n\tCODE_SIZE\020\002*\t\010\350\007\020\200\200\200\200\002\"\210\001\n\016Me"
+ "ssageOptions\022&\n\027message_set_wire_format\030"
+ "\001 \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 "
+ "\003(\0132$.google.protobuf.UninterpretedOptio"
+ "n*\t\010\350\007\020\200\200\200\200\002\"\200\002\n\014FieldOptions\0222\n\005ctype\030\001"
+ " \001(\0162#.google.protobuf.FieldOptions.CTyp"
+ "e\022\016\n\006packed\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005f"
+ "alse\022\034\n\024experimental_map_key\030\t \001(\t\022C\n\024un"
+ "interpreted_option\030\347\007 \003(\0132$.google.proto"
+ "buf.UninterpretedOption\"#\n\005CType\022\010\n\004CORD"
+ "\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumO"
+ "ptions\022C\n\024uninterpreted_option\030\347\007 \003(\0132$."
+ "google.protobuf.UninterpretedOption*\t\010\350\007"
+ "\020\200\200\200\200\002\"b\n\020EnumValueOptions\022C\n\024uninterpre"
+ "ted_option\030\347\007 \003(\0132$.google.protobuf.Unin"
+ "terpretedOption*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceOpt"
+ "ions\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go"
+ "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200"
+ "\200\200\200\002\"_\n\rMethodOptions\022C\n\024uninterpreted_o"
"ption\030\347\007 \003(\0132$.google.protobuf.Uninterpr"
- "etedOption*\t\010\350\007\020\200\200\200\200\002\"_\n\rMethodOptions\022C"
- "\n\024uninterpreted_option\030\347\007 \003(\0132$.google.p"
- "rotobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\205"
- "\002\n\023UninterpretedOption\022;\n\004name\030\002 \003(\0132-.g"
- "oogle.protobuf.UninterpretedOption.NameP"
- "art\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022positiv"
- "e_int_value\030\004 \001(\004\022\032\n\022negative_int_value\030"
- "\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_va"
- "lue\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.pro"
- "tobufB\020DescriptorProtosH\001", 3465,
- &protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors);
-}
-
-// Force BuildDescriptors() to be called at static initialization time.
+ "etedOption*\t\010\350\007\020\200\200\200\200\002\"\205\002\n\023UninterpretedO"
+ "ption\022;\n\004name\030\002 \003(\0132-.google.protobuf.Un"
+ "interpretedOption.NamePart\022\030\n\020identifier"
+ "_value\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004"
+ "\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014double_v"
+ "alue\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\0323\n\010Name"
+ "Part\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension\030"
+ "\002 \002(\010B)\n\023com.google.protobufB\020Descriptor"
+ "ProtosH\001", 3488);
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+ "google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
+ FileDescriptorSet::default_instance_ = new FileDescriptorSet();
+ FileDescriptorProto::default_instance_ = new FileDescriptorProto();
+ DescriptorProto::default_instance_ = new DescriptorProto();
+ DescriptorProto_ExtensionRange::default_instance_ = new DescriptorProto_ExtensionRange();
+ FieldDescriptorProto::default_instance_ = new FieldDescriptorProto();
+ EnumDescriptorProto::default_instance_ = new EnumDescriptorProto();
+ EnumValueDescriptorProto::default_instance_ = new EnumValueDescriptorProto();
+ ServiceDescriptorProto::default_instance_ = new ServiceDescriptorProto();
+ MethodDescriptorProto::default_instance_ = new MethodDescriptorProto();
+ FileOptions::default_instance_ = new FileOptions();
+ MessageOptions::default_instance_ = new MessageOptions();
+ FieldOptions::default_instance_ = new FieldOptions();
+ EnumOptions::default_instance_ = new EnumOptions();
+ EnumValueOptions::default_instance_ = new EnumValueOptions();
+ ServiceOptions::default_instance_ = new ServiceOptions();
+ MethodOptions::default_instance_ = new MethodOptions();
+ UninterpretedOption::default_instance_ = new UninterpretedOption();
+ UninterpretedOption_NamePart::default_instance_ = new UninterpretedOption_NamePart();
+ FileDescriptorSet::default_instance_->InitAsDefaultInstance();
+ FileDescriptorProto::default_instance_->InitAsDefaultInstance();
+ DescriptorProto::default_instance_->InitAsDefaultInstance();
+ DescriptorProto_ExtensionRange::default_instance_->InitAsDefaultInstance();
+ FieldDescriptorProto::default_instance_->InitAsDefaultInstance();
+ EnumDescriptorProto::default_instance_->InitAsDefaultInstance();
+ EnumValueDescriptorProto::default_instance_->InitAsDefaultInstance();
+ ServiceDescriptorProto::default_instance_->InitAsDefaultInstance();
+ MethodDescriptorProto::default_instance_->InitAsDefaultInstance();
+ FileOptions::default_instance_->InitAsDefaultInstance();
+ MessageOptions::default_instance_->InitAsDefaultInstance();
+ FieldOptions::default_instance_->InitAsDefaultInstance();
+ EnumOptions::default_instance_->InitAsDefaultInstance();
+ EnumValueOptions::default_instance_->InitAsDefaultInstance();
+ ServiceOptions::default_instance_->InitAsDefaultInstance();
+ MethodOptions::default_instance_->InitAsDefaultInstance();
+ UninterpretedOption::default_instance_->InitAsDefaultInstance();
+ UninterpretedOption_NamePart::default_instance_->InitAsDefaultInstance();
+}
+
+// Force AddDescriptors() to be called at static initialization time.
struct StaticDescriptorInitializer_google_2fprotobuf_2fdescriptor_2eproto {
StaticDescriptorInitializer_google_2fprotobuf_2fdescriptor_2eproto() {
- protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
}
} static_descriptor_initializer_google_2fprotobuf_2fdescriptor_2eproto_;
@@ -562,37 +601,39 @@ const int FileDescriptorSet::kFileFieldNumber;
#endif // !_MSC_VER
FileDescriptorSet::FileDescriptorSet()
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- file_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void FileDescriptorSet::InitAsDefaultInstance() {}
FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from)
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- file_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void FileDescriptorSet::SharedCtor() {
+ _cached_size_ = 0;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
FileDescriptorSet::~FileDescriptorSet() {
+ SharedDtor();
+}
+
+void FileDescriptorSet::SharedDtor() {
if (this != default_instance_) {
}
}
const ::google::protobuf::Descriptor* FileDescriptorSet::descriptor() {
- if (FileDescriptorSet_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return FileDescriptorSet_descriptor_;
}
const FileDescriptorSet& FileDescriptorSet::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
FileDescriptorSet* FileDescriptorSet::default_instance_ = NULL;
@@ -643,20 +684,37 @@ bool FileDescriptorSet::MergePartialFromCodedStream(
#undef DO_
}
-bool FileDescriptorSet::SerializeWithCachedSizes(
+void FileDescriptorSet::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(1, this->file(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(1, this->file(i), output);
}
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* FileDescriptorSet::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // repeated .google.protobuf.FileDescriptorProto file = 1;
+ for (int i = 0; i < this->file_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(1, this->file(i), target);
+ }
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int FileDescriptorSet::ByteSize() const {
@@ -731,7 +789,7 @@ const ::google::protobuf::Descriptor* FileDescriptorSet::GetDescriptor() const {
}
const ::google::protobuf::Reflection* FileDescriptorSet::GetReflection() const {
- if (FileDescriptorSet_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return FileDescriptorSet_reflection_;
}
@@ -751,40 +809,32 @@ const int FileDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
FileDescriptorProto::FileDescriptorProto()
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(const_cast< ::std::string*>(&_default_name_)),
- package_(const_cast< ::std::string*>(&_default_package_)),
- dependency_(),
- message_type_(),
- enum_type_(),
- service_(),
- extension_(),
- options_(NULL) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void FileDescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::FileOptions*>(&::google::protobuf::FileOptions::default_instance());
}
FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from)
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(const_cast< ::std::string*>(&_default_name_)),
- package_(const_cast< ::std::string*>(&_default_package_)),
- dependency_(),
- message_type_(),
- enum_type_(),
- service_(),
- extension_(),
- options_(NULL) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void FileDescriptorProto::SharedCtor() {
+ _cached_size_ = 0;
+ name_ = const_cast< ::std::string*>(&_default_name_);
+ package_ = const_cast< ::std::string*>(&_default_package_);
+ options_ = NULL;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
FileDescriptorProto::~FileDescriptorProto() {
+ SharedDtor();
+}
+
+void FileDescriptorProto::SharedDtor() {
if (name_ != &_default_name_) {
delete name_;
}
@@ -797,13 +847,12 @@ FileDescriptorProto::~FileDescriptorProto() {
}
const ::google::protobuf::Descriptor* FileDescriptorProto::descriptor() {
- if (FileDescriptorProto_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return FileDescriptorProto_descriptor_;
}
const FileDescriptorProto& FileDescriptorProto::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
FileDescriptorProto* FileDescriptorProto::default_instance_ = NULL;
@@ -965,55 +1014,107 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
#undef DO_
}
-bool FileDescriptorProto::SerializeWithCachedSizes(
+void FileDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output);
}
// optional string package = 2;
if (_has_bit(1)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(2, this->package(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(2, this->package(), output);
}
// repeated string dependency = 3;
for (int i = 0; i < this->dependency_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(3, this->dependency(i), output));
+ ::google::protobuf::internal::WireFormat::WriteString(3, this->dependency(i), output);
}
// repeated .google.protobuf.DescriptorProto message_type = 4;
for (int i = 0; i < this->message_type_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(4, this->message_type(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(4, this->message_type(i), output);
}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
for (int i = 0; i < this->enum_type_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(5, this->enum_type(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(5, this->enum_type(i), output);
}
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
for (int i = 0; i < this->service_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(6, this->service(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(6, this->service(i), output);
}
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
for (int i = 0; i < this->extension_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(7, this->extension(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(7, this->extension(i), output);
}
// optional .google.protobuf.FileOptions options = 8;
if (_has_bit(7)) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(8, this->options(), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(8, this->options(), output);
}
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* FileDescriptorProto::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // optional string name = 1;
+ if (_has_bit(0)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target);
+ }
+
+ // optional string package = 2;
+ if (_has_bit(1)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(2, this->package(), target);
+ }
+
+ // repeated string dependency = 3;
+ for (int i = 0; i < this->dependency_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(3, this->dependency(i), target);
+ }
+
+ // repeated .google.protobuf.DescriptorProto message_type = 4;
+ for (int i = 0; i < this->message_type_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(4, this->message_type(i), target);
+ }
+
+ // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
+ for (int i = 0; i < this->enum_type_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(5, this->enum_type(i), target);
+ }
+
+ // repeated .google.protobuf.ServiceDescriptorProto service = 6;
+ for (int i = 0; i < this->service_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(6, this->service(i), target);
+ }
+
+ // repeated .google.protobuf.FieldDescriptorProto extension = 7;
+ for (int i = 0; i < this->extension_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(7, this->extension(i), target);
+ }
+
+ // optional .google.protobuf.FileOptions options = 8;
+ if (_has_bit(7)) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(8, this->options(), target);
+ }
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int FileDescriptorProto::ByteSize() const {
@@ -1174,7 +1275,7 @@ const ::google::protobuf::Descriptor* FileDescriptorProto::GetDescriptor() const
}
const ::google::protobuf::Reflection* FileDescriptorProto::GetReflection() const {
- if (FileDescriptorProto_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return FileDescriptorProto_reflection_;
}
@@ -1186,39 +1287,41 @@ const int DescriptorProto_ExtensionRange::kEndFieldNumber;
#endif // !_MSC_VER
DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange()
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- start_(0),
- end_(0) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void DescriptorProto_ExtensionRange::InitAsDefaultInstance() {}
DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from)
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- start_(0),
- end_(0) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void DescriptorProto_ExtensionRange::SharedCtor() {
+ _cached_size_ = 0;
+ start_ = 0;
+ end_ = 0;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
DescriptorProto_ExtensionRange::~DescriptorProto_ExtensionRange() {
+ SharedDtor();
+}
+
+void DescriptorProto_ExtensionRange::SharedDtor() {
if (this != default_instance_) {
}
}
const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange::descriptor() {
- if (DescriptorProto_ExtensionRange_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return DescriptorProto_ExtensionRange_descriptor_;
}
const DescriptorProto_ExtensionRange& DescriptorProto_ExtensionRange::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::default_instance_ = NULL;
@@ -1285,25 +1388,47 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream(
#undef DO_
}
-bool DescriptorProto_ExtensionRange::SerializeWithCachedSizes(
+void DescriptorProto_ExtensionRange::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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)) {
- DO_(::google::protobuf::internal::WireFormat::WriteInt32(1, this->start(), output));
+ ::google::protobuf::internal::WireFormat::WriteInt32(1, this->start(), output);
}
// optional int32 end = 2;
if (_has_bit(1)) {
- DO_(::google::protobuf::internal::WireFormat::WriteInt32(2, this->end(), output));
+ ::google::protobuf::internal::WireFormat::WriteInt32(2, this->end(), output);
}
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* DescriptorProto_ExtensionRange::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // optional int32 start = 1;
+ if (_has_bit(0)) {
+ target = ::google::protobuf::internal::WireFormat::WriteInt32ToArray(1, this->start(), target);
+ }
+
+ // optional int32 end = 2;
+ if (_has_bit(1)) {
+ target = ::google::protobuf::internal::WireFormat::WriteInt32ToArray(2, this->end(), target);
+ }
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int DescriptorProto_ExtensionRange::ByteSize() const {
@@ -1391,7 +1516,7 @@ const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange::GetDescrip
}
const ::google::protobuf::Reflection* DescriptorProto_ExtensionRange::GetReflection() const {
- if (DescriptorProto_ExtensionRange_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return DescriptorProto_ExtensionRange_reflection_;
}
@@ -1409,38 +1534,31 @@ const int DescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
DescriptorProto::DescriptorProto()
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(const_cast< ::std::string*>(&_default_name_)),
- field_(),
- extension_(),
- nested_type_(),
- enum_type_(),
- extension_range_(),
- options_(NULL) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void DescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::MessageOptions*>(&::google::protobuf::MessageOptions::default_instance());
}
DescriptorProto::DescriptorProto(const DescriptorProto& from)
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(const_cast< ::std::string*>(&_default_name_)),
- field_(),
- extension_(),
- nested_type_(),
- enum_type_(),
- extension_range_(),
- options_(NULL) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void DescriptorProto::SharedCtor() {
+ _cached_size_ = 0;
+ name_ = const_cast< ::std::string*>(&_default_name_);
+ options_ = NULL;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
DescriptorProto::~DescriptorProto() {
+ SharedDtor();
+}
+
+void DescriptorProto::SharedDtor() {
if (name_ != &_default_name_) {
delete name_;
}
@@ -1450,13 +1568,12 @@ DescriptorProto::~DescriptorProto() {
}
const ::google::protobuf::Descriptor* DescriptorProto::descriptor() {
- if (DescriptorProto_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return DescriptorProto_descriptor_;
}
const DescriptorProto& DescriptorProto::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
DescriptorProto* DescriptorProto::default_instance_ = NULL;
@@ -1601,50 +1718,97 @@ bool DescriptorProto::MergePartialFromCodedStream(
#undef DO_
}
-bool DescriptorProto::SerializeWithCachedSizes(
+void DescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output);
}
// repeated .google.protobuf.FieldDescriptorProto field = 2;
for (int i = 0; i < this->field_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->field(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->field(i), output);
}
// repeated .google.protobuf.DescriptorProto nested_type = 3;
for (int i = 0; i < this->nested_type_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->nested_type(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->nested_type(i), output);
}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
for (int i = 0; i < this->enum_type_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(4, this->enum_type(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(4, this->enum_type(i), output);
}
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
for (int i = 0; i < this->extension_range_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(5, this->extension_range(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(5, this->extension_range(i), output);
}
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
for (int i = 0; i < this->extension_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(6, this->extension(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(6, this->extension(i), output);
}
// optional .google.protobuf.MessageOptions options = 7;
if (_has_bit(6)) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(7, this->options(), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(7, this->options(), output);
}
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* DescriptorProto::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // optional string name = 1;
+ if (_has_bit(0)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target);
+ }
+
+ // repeated .google.protobuf.FieldDescriptorProto field = 2;
+ for (int i = 0; i < this->field_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(2, this->field(i), target);
+ }
+
+ // repeated .google.protobuf.DescriptorProto nested_type = 3;
+ for (int i = 0; i < this->nested_type_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(3, this->nested_type(i), target);
+ }
+
+ // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
+ for (int i = 0; i < this->enum_type_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(4, this->enum_type(i), target);
+ }
+
+ // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
+ for (int i = 0; i < this->extension_range_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(5, this->extension_range(i), target);
+ }
+
+ // repeated .google.protobuf.FieldDescriptorProto extension = 6;
+ for (int i = 0; i < this->extension_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(6, this->extension(i), target);
+ }
+
+ // optional .google.protobuf.MessageOptions options = 7;
+ if (_has_bit(6)) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(7, this->options(), target);
+ }
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int DescriptorProto::ByteSize() const {
@@ -1796,14 +1960,14 @@ const ::google::protobuf::Descriptor* DescriptorProto::GetDescriptor() const {
}
const ::google::protobuf::Reflection* DescriptorProto::GetReflection() const {
- if (DescriptorProto_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return DescriptorProto_reflection_;
}
// ===================================================================
const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor() {
- if (FieldDescriptorProto_Type_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return FieldDescriptorProto_Type_descriptor_;
}
bool FieldDescriptorProto_Type_IsValid(int value) {
@@ -1855,7 +2019,7 @@ const FieldDescriptorProto_Type FieldDescriptorProto::Type_MIN;
const FieldDescriptorProto_Type FieldDescriptorProto::Type_MAX;
#endif // _MSC_VER
const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor() {
- if (FieldDescriptorProto_Label_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return FieldDescriptorProto_Label_descriptor_;
}
bool FieldDescriptorProto_Label_IsValid(int value) {
@@ -1892,40 +2056,37 @@ const int FieldDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
FieldDescriptorProto::FieldDescriptorProto()
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(const_cast< ::std::string*>(&_default_name_)),
- number_(0),
- label_(1),
- type_(1),
- type_name_(const_cast< ::std::string*>(&_default_type_name_)),
- extendee_(const_cast< ::std::string*>(&_default_extendee_)),
- default_value_(const_cast< ::std::string*>(&_default_default_value_)),
- options_(NULL) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void FieldDescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::FieldOptions*>(&::google::protobuf::FieldOptions::default_instance());
}
FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from)
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(const_cast< ::std::string*>(&_default_name_)),
- number_(0),
- label_(1),
- type_(1),
- type_name_(const_cast< ::std::string*>(&_default_type_name_)),
- extendee_(const_cast< ::std::string*>(&_default_extendee_)),
- default_value_(const_cast< ::std::string*>(&_default_default_value_)),
- options_(NULL) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void FieldDescriptorProto::SharedCtor() {
+ _cached_size_ = 0;
+ name_ = const_cast< ::std::string*>(&_default_name_);
+ number_ = 0;
+ label_ = 1;
+ type_ = 1;
+ type_name_ = const_cast< ::std::string*>(&_default_type_name_);
+ extendee_ = const_cast< ::std::string*>(&_default_extendee_);
+ default_value_ = const_cast< ::std::string*>(&_default_default_value_);
+ options_ = NULL;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
FieldDescriptorProto::~FieldDescriptorProto() {
+ SharedDtor();
+}
+
+void FieldDescriptorProto::SharedDtor() {
if (name_ != &_default_name_) {
delete name_;
}
@@ -1944,13 +2105,12 @@ FieldDescriptorProto::~FieldDescriptorProto() {
}
const ::google::protobuf::Descriptor* FieldDescriptorProto::descriptor() {
- if (FieldDescriptorProto_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return FieldDescriptorProto_descriptor_;
}
const FieldDescriptorProto& FieldDescriptorProto::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
FieldDescriptorProto* FieldDescriptorProto::default_instance_ = NULL;
@@ -2047,7 +2207,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
if (::google::protobuf::FieldDescriptorProto_Label_IsValid(value)) {
set_label(static_cast< ::google::protobuf::FieldDescriptorProto_Label >(value));
} else {
- mutable_unknown_fields()->AddField(4)->add_varint(value);
+ mutable_unknown_fields()->AddVarint(4, value);
}
if (input->ExpectTag(40)) goto parse_type;
break;
@@ -2065,7 +2225,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
if (::google::protobuf::FieldDescriptorProto_Type_IsValid(value)) {
set_type(static_cast< ::google::protobuf::FieldDescriptorProto_Type >(value));
} else {
- mutable_unknown_fields()->AddField(5)->add_varint(value);
+ mutable_unknown_fields()->AddVarint(5, value);
}
if (input->ExpectTag(50)) goto parse_type_name;
break;
@@ -2124,55 +2284,107 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
#undef DO_
}
-bool FieldDescriptorProto::SerializeWithCachedSizes(
+void FieldDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output);
}
// optional string extendee = 2;
if (_has_bit(5)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(2, this->extendee(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(2, this->extendee(), output);
}
// optional int32 number = 3;
if (_has_bit(1)) {
- DO_(::google::protobuf::internal::WireFormat::WriteInt32(3, this->number(), output));
+ ::google::protobuf::internal::WireFormat::WriteInt32(3, this->number(), output);
}
// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
if (_has_bit(2)) {
- DO_(::google::protobuf::internal::WireFormat::WriteEnum(4, this->label(), output));
+ ::google::protobuf::internal::WireFormat::WriteEnum(4, this->label(), output);
}
// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
if (_has_bit(3)) {
- DO_(::google::protobuf::internal::WireFormat::WriteEnum(5, this->type(), output));
+ ::google::protobuf::internal::WireFormat::WriteEnum(5, this->type(), output);
}
// optional string type_name = 6;
if (_has_bit(4)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(6, this->type_name(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(6, this->type_name(), output);
}
// optional string default_value = 7;
if (_has_bit(6)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(7, this->default_value(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(7, this->default_value(), output);
}
// optional .google.protobuf.FieldOptions options = 8;
if (_has_bit(7)) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(8, this->options(), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(8, this->options(), output);
}
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* FieldDescriptorProto::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // optional string name = 1;
+ if (_has_bit(0)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target);
+ }
+
+ // optional string extendee = 2;
+ if (_has_bit(5)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(2, this->extendee(), target);
+ }
+
+ // optional int32 number = 3;
+ if (_has_bit(1)) {
+ target = ::google::protobuf::internal::WireFormat::WriteInt32ToArray(3, this->number(), target);
+ }
+
+ // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
+ if (_has_bit(2)) {
+ target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(4, this->label(), target);
+ }
+
+ // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
+ if (_has_bit(3)) {
+ target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(5, this->type(), target);
+ }
+
+ // optional string type_name = 6;
+ if (_has_bit(4)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(6, this->type_name(), target);
+ }
+
+ // optional string default_value = 7;
+ if (_has_bit(6)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(7, this->default_value(), target);
+ }
+
+ // optional .google.protobuf.FieldOptions options = 8;
+ if (_has_bit(7)) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(8, this->options(), target);
+ }
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int FieldDescriptorProto::ByteSize() const {
@@ -2323,7 +2535,7 @@ const ::google::protobuf::Descriptor* FieldDescriptorProto::GetDescriptor() cons
}
const ::google::protobuf::Reflection* FieldDescriptorProto::GetReflection() const {
- if (FieldDescriptorProto_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return FieldDescriptorProto_reflection_;
}
@@ -2337,30 +2549,31 @@ const int EnumDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
EnumDescriptorProto::EnumDescriptorProto()
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(const_cast< ::std::string*>(&_default_name_)),
- value_(),
- options_(NULL) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void EnumDescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::EnumOptions*>(&::google::protobuf::EnumOptions::default_instance());
}
EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from)
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(const_cast< ::std::string*>(&_default_name_)),
- value_(),
- options_(NULL) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void EnumDescriptorProto::SharedCtor() {
+ _cached_size_ = 0;
+ name_ = const_cast< ::std::string*>(&_default_name_);
+ options_ = NULL;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
EnumDescriptorProto::~EnumDescriptorProto() {
+ SharedDtor();
+}
+
+void EnumDescriptorProto::SharedDtor() {
if (name_ != &_default_name_) {
delete name_;
}
@@ -2370,13 +2583,12 @@ EnumDescriptorProto::~EnumDescriptorProto() {
}
const ::google::protobuf::Descriptor* EnumDescriptorProto::descriptor() {
- if (EnumDescriptorProto_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return EnumDescriptorProto_descriptor_;
}
const EnumDescriptorProto& EnumDescriptorProto::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
EnumDescriptorProto* EnumDescriptorProto::default_instance_ = NULL;
@@ -2461,30 +2673,57 @@ bool EnumDescriptorProto::MergePartialFromCodedStream(
#undef DO_
}
-bool EnumDescriptorProto::SerializeWithCachedSizes(
+void EnumDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output);
}
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
for (int i = 0; i < this->value_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->value(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->value(i), output);
}
// optional .google.protobuf.EnumOptions options = 3;
if (_has_bit(2)) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->options(), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->options(), output);
}
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* EnumDescriptorProto::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // optional string name = 1;
+ if (_has_bit(0)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target);
+ }
+
+ // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
+ for (int i = 0; i < this->value_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(2, this->value(i), target);
+ }
+
+ // optional .google.protobuf.EnumOptions options = 3;
+ if (_has_bit(2)) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(3, this->options(), target);
+ }
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int EnumDescriptorProto::ByteSize() const {
@@ -2587,7 +2826,7 @@ const ::google::protobuf::Descriptor* EnumDescriptorProto::GetDescriptor() const
}
const ::google::protobuf::Reflection* EnumDescriptorProto::GetReflection() const {
- if (EnumDescriptorProto_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return EnumDescriptorProto_reflection_;
}
@@ -2601,30 +2840,32 @@ const int EnumValueDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
EnumValueDescriptorProto::EnumValueDescriptorProto()
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(const_cast< ::std::string*>(&_default_name_)),
- number_(0),
- options_(NULL) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void EnumValueDescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::EnumValueOptions*>(&::google::protobuf::EnumValueOptions::default_instance());
}
EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProto& from)
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(const_cast< ::std::string*>(&_default_name_)),
- number_(0),
- options_(NULL) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void EnumValueDescriptorProto::SharedCtor() {
+ _cached_size_ = 0;
+ name_ = const_cast< ::std::string*>(&_default_name_);
+ number_ = 0;
+ options_ = NULL;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
EnumValueDescriptorProto::~EnumValueDescriptorProto() {
+ SharedDtor();
+}
+
+void EnumValueDescriptorProto::SharedDtor() {
if (name_ != &_default_name_) {
delete name_;
}
@@ -2634,13 +2875,12 @@ EnumValueDescriptorProto::~EnumValueDescriptorProto() {
}
const ::google::protobuf::Descriptor* EnumValueDescriptorProto::descriptor() {
- if (EnumValueDescriptorProto_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return EnumValueDescriptorProto_descriptor_;
}
const EnumValueDescriptorProto& EnumValueDescriptorProto::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
EnumValueDescriptorProto* EnumValueDescriptorProto::default_instance_ = NULL;
@@ -2725,30 +2965,57 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream(
#undef DO_
}
-bool EnumValueDescriptorProto::SerializeWithCachedSizes(
+void EnumValueDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output);
}
// optional int32 number = 2;
if (_has_bit(1)) {
- DO_(::google::protobuf::internal::WireFormat::WriteInt32(2, this->number(), output));
+ ::google::protobuf::internal::WireFormat::WriteInt32(2, this->number(), output);
}
// optional .google.protobuf.EnumValueOptions options = 3;
if (_has_bit(2)) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->options(), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->options(), output);
}
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* EnumValueDescriptorProto::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // optional string name = 1;
+ if (_has_bit(0)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target);
+ }
+
+ // optional int32 number = 2;
+ if (_has_bit(1)) {
+ target = ::google::protobuf::internal::WireFormat::WriteInt32ToArray(2, this->number(), target);
+ }
+
+ // optional .google.protobuf.EnumValueOptions options = 3;
+ if (_has_bit(2)) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(3, this->options(), target);
+ }
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int EnumValueDescriptorProto::ByteSize() const {
@@ -2849,7 +3116,7 @@ const ::google::protobuf::Descriptor* EnumValueDescriptorProto::GetDescriptor()
}
const ::google::protobuf::Reflection* EnumValueDescriptorProto::GetReflection() const {
- if (EnumValueDescriptorProto_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return EnumValueDescriptorProto_reflection_;
}
@@ -2863,30 +3130,31 @@ const int ServiceDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
ServiceDescriptorProto::ServiceDescriptorProto()
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(const_cast< ::std::string*>(&_default_name_)),
- method_(),
- options_(NULL) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void ServiceDescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::ServiceOptions*>(&::google::protobuf::ServiceOptions::default_instance());
}
ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& from)
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(const_cast< ::std::string*>(&_default_name_)),
- method_(),
- options_(NULL) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void ServiceDescriptorProto::SharedCtor() {
+ _cached_size_ = 0;
+ name_ = const_cast< ::std::string*>(&_default_name_);
+ options_ = NULL;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
ServiceDescriptorProto::~ServiceDescriptorProto() {
+ SharedDtor();
+}
+
+void ServiceDescriptorProto::SharedDtor() {
if (name_ != &_default_name_) {
delete name_;
}
@@ -2896,13 +3164,12 @@ ServiceDescriptorProto::~ServiceDescriptorProto() {
}
const ::google::protobuf::Descriptor* ServiceDescriptorProto::descriptor() {
- if (ServiceDescriptorProto_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return ServiceDescriptorProto_descriptor_;
}
const ServiceDescriptorProto& ServiceDescriptorProto::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
ServiceDescriptorProto* ServiceDescriptorProto::default_instance_ = NULL;
@@ -2987,30 +3254,57 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream(
#undef DO_
}
-bool ServiceDescriptorProto::SerializeWithCachedSizes(
+void ServiceDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output);
}
// repeated .google.protobuf.MethodDescriptorProto method = 2;
for (int i = 0; i < this->method_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->method(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->method(i), output);
}
// optional .google.protobuf.ServiceOptions options = 3;
if (_has_bit(2)) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->options(), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(3, this->options(), output);
}
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* ServiceDescriptorProto::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // optional string name = 1;
+ if (_has_bit(0)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target);
+ }
+
+ // repeated .google.protobuf.MethodDescriptorProto method = 2;
+ for (int i = 0; i < this->method_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(2, this->method(i), target);
+ }
+
+ // optional .google.protobuf.ServiceOptions options = 3;
+ if (_has_bit(2)) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(3, this->options(), target);
+ }
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int ServiceDescriptorProto::ByteSize() const {
@@ -3113,7 +3407,7 @@ const ::google::protobuf::Descriptor* ServiceDescriptorProto::GetDescriptor() co
}
const ::google::protobuf::Reflection* ServiceDescriptorProto::GetReflection() const {
- if (ServiceDescriptorProto_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return ServiceDescriptorProto_reflection_;
}
@@ -3130,32 +3424,33 @@ const int MethodDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
MethodDescriptorProto::MethodDescriptorProto()
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(const_cast< ::std::string*>(&_default_name_)),
- input_type_(const_cast< ::std::string*>(&_default_input_type_)),
- output_type_(const_cast< ::std::string*>(&_default_output_type_)),
- options_(NULL) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void MethodDescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::MethodOptions*>(&::google::protobuf::MethodOptions::default_instance());
}
MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from)
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(const_cast< ::std::string*>(&_default_name_)),
- input_type_(const_cast< ::std::string*>(&_default_input_type_)),
- output_type_(const_cast< ::std::string*>(&_default_output_type_)),
- options_(NULL) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void MethodDescriptorProto::SharedCtor() {
+ _cached_size_ = 0;
+ name_ = const_cast< ::std::string*>(&_default_name_);
+ input_type_ = const_cast< ::std::string*>(&_default_input_type_);
+ output_type_ = const_cast< ::std::string*>(&_default_output_type_);
+ options_ = NULL;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
MethodDescriptorProto::~MethodDescriptorProto() {
+ SharedDtor();
+}
+
+void MethodDescriptorProto::SharedDtor() {
if (name_ != &_default_name_) {
delete name_;
}
@@ -3171,13 +3466,12 @@ MethodDescriptorProto::~MethodDescriptorProto() {
}
const ::google::protobuf::Descriptor* MethodDescriptorProto::descriptor() {
- if (MethodDescriptorProto_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return MethodDescriptorProto_descriptor_;
}
const MethodDescriptorProto& MethodDescriptorProto::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
MethodDescriptorProto* MethodDescriptorProto::default_instance_ = NULL;
@@ -3281,35 +3575,67 @@ bool MethodDescriptorProto::MergePartialFromCodedStream(
#undef DO_
}
-bool MethodDescriptorProto::SerializeWithCachedSizes(
+void MethodDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(1, this->name(), output);
}
// optional string input_type = 2;
if (_has_bit(1)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(2, this->input_type(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(2, this->input_type(), output);
}
// optional string output_type = 3;
if (_has_bit(2)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(3, this->output_type(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(3, this->output_type(), output);
}
// optional .google.protobuf.MethodOptions options = 4;
if (_has_bit(3)) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(4, this->options(), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(4, this->options(), output);
}
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* MethodDescriptorProto::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // optional string name = 1;
+ if (_has_bit(0)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name(), target);
+ }
+
+ // optional string input_type = 2;
+ if (_has_bit(1)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(2, this->input_type(), target);
+ }
+
+ // optional string output_type = 3;
+ if (_has_bit(2)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(3, this->output_type(), target);
+ }
+
+ // optional .google.protobuf.MethodOptions options = 4;
+ if (_has_bit(3)) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(4, this->options(), target);
+ }
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int MethodDescriptorProto::ByteSize() const {
@@ -3419,14 +3745,14 @@ const ::google::protobuf::Descriptor* MethodDescriptorProto::GetDescriptor() con
}
const ::google::protobuf::Reflection* MethodDescriptorProto::GetReflection() const {
- if (MethodDescriptorProto_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return MethodDescriptorProto_reflection_;
}
// ===================================================================
const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor() {
- if (FileOptions_OptimizeMode_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return FileOptions_OptimizeMode_descriptor_;
}
bool FileOptions_OptimizeMode_IsValid(int value) {
@@ -3456,39 +3782,32 @@ const int FileOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
FileOptions::FileOptions()
- : ::google::protobuf::Message(),
- _extensions_(&FileOptions_descriptor_,
- ::google::protobuf::DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory()),
- _unknown_fields_(),
- _cached_size_(0),
- java_package_(const_cast< ::std::string*>(&_default_java_package_)),
- java_outer_classname_(const_cast< ::std::string*>(&_default_java_outer_classname_)),
- java_multiple_files_(false),
- optimize_for_(2),
- uninterpreted_option_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void FileOptions::InitAsDefaultInstance() {}
FileOptions::FileOptions(const FileOptions& from)
- : ::google::protobuf::Message(),
- _extensions_(&FileOptions_descriptor_,
- ::google::protobuf::DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory()),
- _unknown_fields_(),
- _cached_size_(0),
- java_package_(const_cast< ::std::string*>(&_default_java_package_)),
- java_outer_classname_(const_cast< ::std::string*>(&_default_java_outer_classname_)),
- java_multiple_files_(false),
- optimize_for_(2),
- uninterpreted_option_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void FileOptions::SharedCtor() {
+ _cached_size_ = 0;
+ java_package_ = const_cast< ::std::string*>(&_default_java_package_);
+ java_outer_classname_ = const_cast< ::std::string*>(&_default_java_outer_classname_);
+ java_multiple_files_ = false;
+ optimize_for_ = 1;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
FileOptions::~FileOptions() {
+ SharedDtor();
+}
+
+void FileOptions::SharedDtor() {
if (java_package_ != &_default_java_package_) {
delete java_package_;
}
@@ -3500,13 +3819,12 @@ FileOptions::~FileOptions() {
}
const ::google::protobuf::Descriptor* FileOptions::descriptor() {
- if (FileOptions_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return FileOptions_descriptor_;
}
const FileOptions& FileOptions::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
FileOptions* FileOptions::default_instance_ = NULL;
@@ -3529,7 +3847,7 @@ void FileOptions::Clear() {
}
}
java_multiple_files_ = false;
- optimize_for_ = 2;
+ optimize_for_ = 1;
}
uninterpreted_option_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -3565,7 +3883,7 @@ bool FileOptions::MergePartialFromCodedStream(
break;
}
- // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = CODE_SIZE];
+ // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
case 9: {
if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=
::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
@@ -3577,7 +3895,7 @@ bool FileOptions::MergePartialFromCodedStream(
if (::google::protobuf::FileOptions_OptimizeMode_IsValid(value)) {
set_optimize_for(static_cast< ::google::protobuf::FileOptions_OptimizeMode >(value));
} else {
- mutable_unknown_fields()->AddField(9)->add_varint(value);
+ mutable_unknown_fields()->AddVarint(9, value);
}
if (input->ExpectTag(80)) goto parse_java_multiple_files;
break;
@@ -3618,7 +3936,8 @@ bool FileOptions::MergePartialFromCodedStream(
return true;
}
if ((8000u <= tag)) {
- DO_(_extensions_.ParseField(tag, input, this));
+ DO_(_extensions_.ParseField(tag, input, default_instance_,
+ mutable_unknown_fields()));
continue;
}
DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -3631,44 +3950,85 @@ bool FileOptions::MergePartialFromCodedStream(
#undef DO_
}
-bool FileOptions::SerializeWithCachedSizes(
+void FileOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(1, this->java_package(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(1, this->java_package(), output);
}
// optional string java_outer_classname = 8;
if (_has_bit(1)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(8, this->java_outer_classname(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(8, this->java_outer_classname(), output);
}
- // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = CODE_SIZE];
+ // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
if (_has_bit(3)) {
- DO_(::google::protobuf::internal::WireFormat::WriteEnum(9, this->optimize_for(), output));
+ ::google::protobuf::internal::WireFormat::WriteEnum(9, this->optimize_for(), output);
}
// optional bool java_multiple_files = 10 [default = false];
if (_has_bit(2)) {
- DO_(::google::protobuf::internal::WireFormat::WriteBool(10, this->java_multiple_files(), output));
+ ::google::protobuf::internal::WireFormat::WriteBool(10, this->java_multiple_files(), output);
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output);
}
// Extension range [1000, 536870912)
- DO_(_extensions_.SerializeWithCachedSizes(
- 1000, 536870912, *this, output));
+ _extensions_.SerializeWithCachedSizes(
+ 1000, 536870912, output);
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* FileOptions::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // optional string java_package = 1;
+ if (_has_bit(0)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->java_package(), target);
+ }
+
+ // optional string java_outer_classname = 8;
+ if (_has_bit(1)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(8, this->java_outer_classname(), target);
+ }
+
+ // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
+ if (_has_bit(3)) {
+ target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(9, this->optimize_for(), target);
+ }
+
+ // optional bool java_multiple_files = 10 [default = false];
+ if (_has_bit(2)) {
+ target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(10, this->java_multiple_files(), target);
+ }
+
+ // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target);
+ }
+
+ // Extension range [1000, 536870912)
+ target = _extensions_.SerializeWithCachedSizesToArray(
+ 1000, 536870912, target);
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int FileOptions::ByteSize() const {
@@ -3692,7 +4052,7 @@ int FileOptions::ByteSize() const {
total_size += 1 + 1;
}
- // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = CODE_SIZE];
+ // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
if (has_optimize_for()) {
total_size += 1 +
::google::protobuf::internal::WireFormat::EnumSize(this->optimize_for());
@@ -3707,7 +4067,7 @@ int FileOptions::ByteSize() const {
this->uninterpreted_option(i));
}
- total_size += _extensions_.ByteSize(*this);
+ total_size += _extensions_.ByteSize();
if (!unknown_fields().empty()) {
total_size +=
@@ -3791,7 +4151,7 @@ const ::google::protobuf::Descriptor* FileOptions::GetDescriptor() const {
}
const ::google::protobuf::Reflection* FileOptions::GetReflection() const {
- if (FileOptions_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return FileOptions_reflection_;
}
@@ -3803,45 +4163,40 @@ const int MessageOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
MessageOptions::MessageOptions()
- : ::google::protobuf::Message(),
- _extensions_(&MessageOptions_descriptor_,
- ::google::protobuf::DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory()),
- _unknown_fields_(),
- _cached_size_(0),
- message_set_wire_format_(false),
- uninterpreted_option_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void MessageOptions::InitAsDefaultInstance() {}
MessageOptions::MessageOptions(const MessageOptions& from)
- : ::google::protobuf::Message(),
- _extensions_(&MessageOptions_descriptor_,
- ::google::protobuf::DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory()),
- _unknown_fields_(),
- _cached_size_(0),
- message_set_wire_format_(false),
- uninterpreted_option_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void MessageOptions::SharedCtor() {
+ _cached_size_ = 0;
+ message_set_wire_format_ = false;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
MessageOptions::~MessageOptions() {
+ SharedDtor();
+}
+
+void MessageOptions::SharedDtor() {
if (this != default_instance_) {
}
}
const ::google::protobuf::Descriptor* MessageOptions::descriptor() {
- if (MessageOptions_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return MessageOptions_descriptor_;
}
const MessageOptions& MessageOptions::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
MessageOptions* MessageOptions::default_instance_ = NULL;
@@ -3900,7 +4255,8 @@ bool MessageOptions::MergePartialFromCodedStream(
return true;
}
if ((8000u <= tag)) {
- DO_(_extensions_.ParseField(tag, input, this));
+ DO_(_extensions_.ParseField(tag, input, default_instance_,
+ mutable_unknown_fields()));
continue;
}
DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -3913,29 +4269,55 @@ bool MessageOptions::MergePartialFromCodedStream(
#undef DO_
}
-bool MessageOptions::SerializeWithCachedSizes(
+void MessageOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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)) {
- DO_(::google::protobuf::internal::WireFormat::WriteBool(1, this->message_set_wire_format(), output));
+ ::google::protobuf::internal::WireFormat::WriteBool(1, this->message_set_wire_format(), output);
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output);
}
// Extension range [1000, 536870912)
- DO_(_extensions_.SerializeWithCachedSizes(
- 1000, 536870912, *this, output));
+ _extensions_.SerializeWithCachedSizes(
+ 1000, 536870912, output);
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* MessageOptions::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // optional bool message_set_wire_format = 1 [default = false];
+ if (_has_bit(0)) {
+ target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(1, this->message_set_wire_format(), target);
+ }
+
+ // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target);
+ }
+
+ // Extension range [1000, 536870912)
+ target = _extensions_.SerializeWithCachedSizesToArray(
+ 1000, 536870912, target);
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int MessageOptions::ByteSize() const {
@@ -3956,7 +4338,7 @@ int MessageOptions::ByteSize() const {
this->uninterpreted_option(i));
}
- total_size += _extensions_.ByteSize(*this);
+ total_size += _extensions_.ByteSize();
if (!unknown_fields().empty()) {
total_size +=
@@ -4028,14 +4410,14 @@ const ::google::protobuf::Descriptor* MessageOptions::GetDescriptor() const {
}
const ::google::protobuf::Reflection* MessageOptions::GetReflection() const {
- if (MessageOptions_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return MessageOptions_reflection_;
}
// ===================================================================
const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor() {
- if (FieldOptions_CType_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return FieldOptions_CType_descriptor_;
}
bool FieldOptions_CType_IsValid(int value) {
@@ -4058,42 +4440,38 @@ const ::std::string FieldOptions::_default_experimental_map_key_;
#ifndef _MSC_VER
const int FieldOptions::kCtypeFieldNumber;
const int FieldOptions::kPackedFieldNumber;
+const int FieldOptions::kDeprecatedFieldNumber;
const int FieldOptions::kExperimentalMapKeyFieldNumber;
const int FieldOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
FieldOptions::FieldOptions()
- : ::google::protobuf::Message(),
- _extensions_(&FieldOptions_descriptor_,
- ::google::protobuf::DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory()),
- _unknown_fields_(),
- _cached_size_(0),
- ctype_(1),
- packed_(false),
- experimental_map_key_(const_cast< ::std::string*>(&_default_experimental_map_key_)),
- uninterpreted_option_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void FieldOptions::InitAsDefaultInstance() {}
FieldOptions::FieldOptions(const FieldOptions& from)
- : ::google::protobuf::Message(),
- _extensions_(&FieldOptions_descriptor_,
- ::google::protobuf::DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory()),
- _unknown_fields_(),
- _cached_size_(0),
- ctype_(1),
- packed_(false),
- experimental_map_key_(const_cast< ::std::string*>(&_default_experimental_map_key_)),
- uninterpreted_option_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void FieldOptions::SharedCtor() {
+ _cached_size_ = 0;
+ ctype_ = 1;
+ packed_ = false;
+ deprecated_ = false;
+ experimental_map_key_ = const_cast< ::std::string*>(&_default_experimental_map_key_);
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
FieldOptions::~FieldOptions() {
+ SharedDtor();
+}
+
+void FieldOptions::SharedDtor() {
if (experimental_map_key_ != &_default_experimental_map_key_) {
delete experimental_map_key_;
}
@@ -4102,13 +4480,12 @@ FieldOptions::~FieldOptions() {
}
const ::google::protobuf::Descriptor* FieldOptions::descriptor() {
- if (FieldOptions_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return FieldOptions_descriptor_;
}
const FieldOptions& FieldOptions::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
FieldOptions* FieldOptions::default_instance_ = NULL;
@@ -4122,7 +4499,8 @@ void FieldOptions::Clear() {
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
ctype_ = 1;
packed_ = false;
- if (_has_bit(2)) {
+ deprecated_ = false;
+ if (_has_bit(3)) {
if (experimental_map_key_ != &_default_experimental_map_key_) {
experimental_map_key_->clear();
}
@@ -4150,7 +4528,7 @@ bool FieldOptions::MergePartialFromCodedStream(
if (::google::protobuf::FieldOptions_CType_IsValid(value)) {
set_ctype(static_cast< ::google::protobuf::FieldOptions_CType >(value));
} else {
- mutable_unknown_fields()->AddField(1)->add_varint(value);
+ mutable_unknown_fields()->AddVarint(1, value);
}
if (input->ExpectTag(16)) goto parse_packed;
break;
@@ -4166,6 +4544,20 @@ bool FieldOptions::MergePartialFromCodedStream(
DO_(::google::protobuf::internal::WireFormat::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::WireFormat::GetTagWireType(tag) !=
+ ::google::protobuf::internal::WireFormat::WIRETYPE_VARINT) {
+ goto handle_uninterpreted;
+ }
+ parse_deprecated:
+ DO_(::google::protobuf::internal::WireFormat::ReadBool(
+ input, &deprecated_));
+ _set_bit(2);
if (input->ExpectTag(74)) goto parse_experimental_map_key;
break;
}
@@ -4203,7 +4595,8 @@ bool FieldOptions::MergePartialFromCodedStream(
return true;
}
if ((8000u <= tag)) {
- DO_(_extensions_.ParseField(tag, input, this));
+ DO_(_extensions_.ParseField(tag, input, default_instance_,
+ mutable_unknown_fields()));
continue;
}
DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -4216,39 +4609,85 @@ bool FieldOptions::MergePartialFromCodedStream(
#undef DO_
}
-bool FieldOptions::SerializeWithCachedSizes(
+void FieldOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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;
if (_has_bit(0)) {
- DO_(::google::protobuf::internal::WireFormat::WriteEnum(1, this->ctype(), output));
+ ::google::protobuf::internal::WireFormat::WriteEnum(1, this->ctype(), output);
}
// optional bool packed = 2;
if (_has_bit(1)) {
- DO_(::google::protobuf::internal::WireFormat::WriteBool(2, this->packed(), output));
+ ::google::protobuf::internal::WireFormat::WriteBool(2, this->packed(), output);
+ }
+
+ // optional bool deprecated = 3 [default = false];
+ if (_has_bit(2)) {
+ ::google::protobuf::internal::WireFormat::WriteBool(3, this->deprecated(), output);
}
// optional string experimental_map_key = 9;
+ if (_has_bit(3)) {
+ ::google::protobuf::internal::WireFormat::WriteString(9, this->experimental_map_key(), output);
+ }
+
+ // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output);
+ }
+
+ // Extension range [1000, 536870912)
+ _extensions_.SerializeWithCachedSizes(
+ 1000, 536870912, output);
+
+ if (!unknown_fields().empty()) {
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
+ }
+}
+
+::google::protobuf::uint8* FieldOptions::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // optional .google.protobuf.FieldOptions.CType ctype = 1;
+ if (_has_bit(0)) {
+ target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(1, this->ctype(), target);
+ }
+
+ // optional bool packed = 2;
+ if (_has_bit(1)) {
+ target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(2, this->packed(), target);
+ }
+
+ // optional bool deprecated = 3 [default = false];
if (_has_bit(2)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(9, this->experimental_map_key(), output));
+ target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(3, this->deprecated(), target);
+ }
+
+ // optional string experimental_map_key = 9;
+ if (_has_bit(3)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(9, this->experimental_map_key(), target);
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output));
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target);
}
// Extension range [1000, 536870912)
- DO_(_extensions_.SerializeWithCachedSizes(
- 1000, 536870912, *this, output));
+ target = _extensions_.SerializeWithCachedSizesToArray(
+ 1000, 536870912, target);
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
}
- return true;
-#undef DO_
+ return target;
}
int FieldOptions::ByteSize() const {
@@ -4266,6 +4705,11 @@ int FieldOptions::ByteSize() const {
total_size += 1 + 1;
}
+ // optional bool deprecated = 3 [default = false];
+ if (has_deprecated()) {
+ total_size += 1 + 1;
+ }
+
// optional string experimental_map_key = 9;
if (has_experimental_map_key()) {
total_size += 1 +
@@ -4281,7 +4725,7 @@ int FieldOptions::ByteSize() const {
this->uninterpreted_option(i));
}
- total_size += _extensions_.ByteSize(*this);
+ total_size += _extensions_.ByteSize();
if (!unknown_fields().empty()) {
total_size +=
@@ -4315,6 +4759,9 @@ void FieldOptions::MergeFrom(const FieldOptions& from) {
set_packed(from.packed());
}
if (from._has_bit(2)) {
+ set_deprecated(from.deprecated());
+ }
+ if (from._has_bit(3)) {
set_experimental_map_key(from.experimental_map_key());
}
}
@@ -4338,6 +4785,7 @@ void FieldOptions::Swap(FieldOptions* other) {
if (other != this) {
std::swap(ctype_, other->ctype_);
std::swap(packed_, other->packed_);
+ std::swap(deprecated_, other->deprecated_);
std::swap(experimental_map_key_, other->experimental_map_key_);
uninterpreted_option_.Swap(&other->uninterpreted_option_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
@@ -4361,7 +4809,7 @@ const ::google::protobuf::Descriptor* FieldOptions::GetDescriptor() const {
}
const ::google::protobuf::Reflection* FieldOptions::GetReflection() const {
- if (FieldOptions_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return FieldOptions_reflection_;
}
@@ -4372,43 +4820,39 @@ const int EnumOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
EnumOptions::EnumOptions()
- : ::google::protobuf::Message(),
- _extensions_(&EnumOptions_descriptor_,
- ::google::protobuf::DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory()),
- _unknown_fields_(),
- _cached_size_(0),
- uninterpreted_option_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void EnumOptions::InitAsDefaultInstance() {}
EnumOptions::EnumOptions(const EnumOptions& from)
- : ::google::protobuf::Message(),
- _extensions_(&EnumOptions_descriptor_,
- ::google::protobuf::DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory()),
- _unknown_fields_(),
- _cached_size_(0),
- uninterpreted_option_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void EnumOptions::SharedCtor() {
+ _cached_size_ = 0;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
EnumOptions::~EnumOptions() {
+ SharedDtor();
+}
+
+void EnumOptions::SharedDtor() {
if (this != default_instance_) {
}
}
const ::google::protobuf::Descriptor* EnumOptions::descriptor() {
- if (EnumOptions_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return EnumOptions_descriptor_;
}
const EnumOptions& EnumOptions::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
EnumOptions* EnumOptions::default_instance_ = NULL;
@@ -4451,7 +4895,8 @@ bool EnumOptions::MergePartialFromCodedStream(
return true;
}
if ((8000u <= tag)) {
- DO_(_extensions_.ParseField(tag, input, this));
+ DO_(_extensions_.ParseField(tag, input, default_instance_,
+ mutable_unknown_fields()));
continue;
}
DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -4464,24 +4909,45 @@ bool EnumOptions::MergePartialFromCodedStream(
#undef DO_
}
-bool EnumOptions::SerializeWithCachedSizes(
+void EnumOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output);
}
// Extension range [1000, 536870912)
- DO_(_extensions_.SerializeWithCachedSizes(
- 1000, 536870912, *this, output));
+ _extensions_.SerializeWithCachedSizes(
+ 1000, 536870912, output);
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* EnumOptions::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target);
+ }
+
+ // Extension range [1000, 536870912)
+ target = _extensions_.SerializeWithCachedSizesToArray(
+ 1000, 536870912, target);
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int EnumOptions::ByteSize() const {
@@ -4495,7 +4961,7 @@ int EnumOptions::ByteSize() const {
this->uninterpreted_option(i));
}
- total_size += _extensions_.ByteSize(*this);
+ total_size += _extensions_.ByteSize();
if (!unknown_fields().empty()) {
total_size +=
@@ -4561,7 +5027,7 @@ const ::google::protobuf::Descriptor* EnumOptions::GetDescriptor() const {
}
const ::google::protobuf::Reflection* EnumOptions::GetReflection() const {
- if (EnumOptions_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return EnumOptions_reflection_;
}
@@ -4572,43 +5038,39 @@ const int EnumValueOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
EnumValueOptions::EnumValueOptions()
- : ::google::protobuf::Message(),
- _extensions_(&EnumValueOptions_descriptor_,
- ::google::protobuf::DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory()),
- _unknown_fields_(),
- _cached_size_(0),
- uninterpreted_option_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void EnumValueOptions::InitAsDefaultInstance() {}
EnumValueOptions::EnumValueOptions(const EnumValueOptions& from)
- : ::google::protobuf::Message(),
- _extensions_(&EnumValueOptions_descriptor_,
- ::google::protobuf::DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory()),
- _unknown_fields_(),
- _cached_size_(0),
- uninterpreted_option_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void EnumValueOptions::SharedCtor() {
+ _cached_size_ = 0;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
EnumValueOptions::~EnumValueOptions() {
+ SharedDtor();
+}
+
+void EnumValueOptions::SharedDtor() {
if (this != default_instance_) {
}
}
const ::google::protobuf::Descriptor* EnumValueOptions::descriptor() {
- if (EnumValueOptions_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return EnumValueOptions_descriptor_;
}
const EnumValueOptions& EnumValueOptions::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
EnumValueOptions* EnumValueOptions::default_instance_ = NULL;
@@ -4651,7 +5113,8 @@ bool EnumValueOptions::MergePartialFromCodedStream(
return true;
}
if ((8000u <= tag)) {
- DO_(_extensions_.ParseField(tag, input, this));
+ DO_(_extensions_.ParseField(tag, input, default_instance_,
+ mutable_unknown_fields()));
continue;
}
DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -4664,24 +5127,45 @@ bool EnumValueOptions::MergePartialFromCodedStream(
#undef DO_
}
-bool EnumValueOptions::SerializeWithCachedSizes(
+void EnumValueOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output);
}
// Extension range [1000, 536870912)
- DO_(_extensions_.SerializeWithCachedSizes(
- 1000, 536870912, *this, output));
+ _extensions_.SerializeWithCachedSizes(
+ 1000, 536870912, output);
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* EnumValueOptions::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target);
+ }
+
+ // Extension range [1000, 536870912)
+ target = _extensions_.SerializeWithCachedSizesToArray(
+ 1000, 536870912, target);
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int EnumValueOptions::ByteSize() const {
@@ -4695,7 +5179,7 @@ int EnumValueOptions::ByteSize() const {
this->uninterpreted_option(i));
}
- total_size += _extensions_.ByteSize(*this);
+ total_size += _extensions_.ByteSize();
if (!unknown_fields().empty()) {
total_size +=
@@ -4761,7 +5245,7 @@ const ::google::protobuf::Descriptor* EnumValueOptions::GetDescriptor() const {
}
const ::google::protobuf::Reflection* EnumValueOptions::GetReflection() const {
- if (EnumValueOptions_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return EnumValueOptions_reflection_;
}
@@ -4772,43 +5256,39 @@ const int ServiceOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
ServiceOptions::ServiceOptions()
- : ::google::protobuf::Message(),
- _extensions_(&ServiceOptions_descriptor_,
- ::google::protobuf::DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory()),
- _unknown_fields_(),
- _cached_size_(0),
- uninterpreted_option_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void ServiceOptions::InitAsDefaultInstance() {}
ServiceOptions::ServiceOptions(const ServiceOptions& from)
- : ::google::protobuf::Message(),
- _extensions_(&ServiceOptions_descriptor_,
- ::google::protobuf::DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory()),
- _unknown_fields_(),
- _cached_size_(0),
- uninterpreted_option_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void ServiceOptions::SharedCtor() {
+ _cached_size_ = 0;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
ServiceOptions::~ServiceOptions() {
+ SharedDtor();
+}
+
+void ServiceOptions::SharedDtor() {
if (this != default_instance_) {
}
}
const ::google::protobuf::Descriptor* ServiceOptions::descriptor() {
- if (ServiceOptions_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return ServiceOptions_descriptor_;
}
const ServiceOptions& ServiceOptions::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
ServiceOptions* ServiceOptions::default_instance_ = NULL;
@@ -4851,7 +5331,8 @@ bool ServiceOptions::MergePartialFromCodedStream(
return true;
}
if ((8000u <= tag)) {
- DO_(_extensions_.ParseField(tag, input, this));
+ DO_(_extensions_.ParseField(tag, input, default_instance_,
+ mutable_unknown_fields()));
continue;
}
DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -4864,24 +5345,45 @@ bool ServiceOptions::MergePartialFromCodedStream(
#undef DO_
}
-bool ServiceOptions::SerializeWithCachedSizes(
+void ServiceOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output);
}
// Extension range [1000, 536870912)
- DO_(_extensions_.SerializeWithCachedSizes(
- 1000, 536870912, *this, output));
+ _extensions_.SerializeWithCachedSizes(
+ 1000, 536870912, output);
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* ServiceOptions::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target);
+ }
+
+ // Extension range [1000, 536870912)
+ target = _extensions_.SerializeWithCachedSizesToArray(
+ 1000, 536870912, target);
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int ServiceOptions::ByteSize() const {
@@ -4895,7 +5397,7 @@ int ServiceOptions::ByteSize() const {
this->uninterpreted_option(i));
}
- total_size += _extensions_.ByteSize(*this);
+ total_size += _extensions_.ByteSize();
if (!unknown_fields().empty()) {
total_size +=
@@ -4961,7 +5463,7 @@ const ::google::protobuf::Descriptor* ServiceOptions::GetDescriptor() const {
}
const ::google::protobuf::Reflection* ServiceOptions::GetReflection() const {
- if (ServiceOptions_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return ServiceOptions_reflection_;
}
@@ -4972,43 +5474,39 @@ const int MethodOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
MethodOptions::MethodOptions()
- : ::google::protobuf::Message(),
- _extensions_(&MethodOptions_descriptor_,
- ::google::protobuf::DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory()),
- _unknown_fields_(),
- _cached_size_(0),
- uninterpreted_option_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void MethodOptions::InitAsDefaultInstance() {}
MethodOptions::MethodOptions(const MethodOptions& from)
- : ::google::protobuf::Message(),
- _extensions_(&MethodOptions_descriptor_,
- ::google::protobuf::DescriptorPool::generated_pool(),
- ::google::protobuf::MessageFactory::generated_factory()),
- _unknown_fields_(),
- _cached_size_(0),
- uninterpreted_option_() {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void MethodOptions::SharedCtor() {
+ _cached_size_ = 0;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
MethodOptions::~MethodOptions() {
+ SharedDtor();
+}
+
+void MethodOptions::SharedDtor() {
if (this != default_instance_) {
}
}
const ::google::protobuf::Descriptor* MethodOptions::descriptor() {
- if (MethodOptions_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return MethodOptions_descriptor_;
}
const MethodOptions& MethodOptions::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
MethodOptions* MethodOptions::default_instance_ = NULL;
@@ -5051,7 +5549,8 @@ bool MethodOptions::MergePartialFromCodedStream(
return true;
}
if ((8000u <= tag)) {
- DO_(_extensions_.ParseField(tag, input, this));
+ DO_(_extensions_.ParseField(tag, input, default_instance_,
+ mutable_unknown_fields()));
continue;
}
DO_(::google::protobuf::internal::WireFormat::SkipField(
@@ -5064,24 +5563,45 @@ bool MethodOptions::MergePartialFromCodedStream(
#undef DO_
}
-bool MethodOptions::SerializeWithCachedSizes(
+void MethodOptions::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(999, this->uninterpreted_option(i), output);
}
// Extension range [1000, 536870912)
- DO_(_extensions_.SerializeWithCachedSizes(
- 1000, 536870912, *this, output));
+ _extensions_.SerializeWithCachedSizes(
+ 1000, 536870912, output);
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* MethodOptions::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ for (int i = 0; i < this->uninterpreted_option_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(999, this->uninterpreted_option(i), target);
+ }
+
+ // Extension range [1000, 536870912)
+ target = _extensions_.SerializeWithCachedSizesToArray(
+ 1000, 536870912, target);
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int MethodOptions::ByteSize() const {
@@ -5095,7 +5615,7 @@ int MethodOptions::ByteSize() const {
this->uninterpreted_option(i));
}
- total_size += _extensions_.ByteSize(*this);
+ total_size += _extensions_.ByteSize();
if (!unknown_fields().empty()) {
total_size +=
@@ -5161,7 +5681,7 @@ const ::google::protobuf::Descriptor* MethodOptions::GetDescriptor() const {
}
const ::google::protobuf::Reflection* MethodOptions::GetReflection() const {
- if (MethodOptions_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return MethodOptions_reflection_;
}
@@ -5174,27 +5694,30 @@ const int UninterpretedOption_NamePart::kIsExtensionFieldNumber;
#endif // !_MSC_VER
UninterpretedOption_NamePart::UninterpretedOption_NamePart()
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_part_(const_cast< ::std::string*>(&_default_name_part_)),
- is_extension_(false) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void UninterpretedOption_NamePart::InitAsDefaultInstance() {}
UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from)
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_part_(const_cast< ::std::string*>(&_default_name_part_)),
- is_extension_(false) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void UninterpretedOption_NamePart::SharedCtor() {
+ _cached_size_ = 0;
+ name_part_ = const_cast< ::std::string*>(&_default_name_part_);
+ is_extension_ = false;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
UninterpretedOption_NamePart::~UninterpretedOption_NamePart() {
+ SharedDtor();
+}
+
+void UninterpretedOption_NamePart::SharedDtor() {
if (name_part_ != &_default_name_part_) {
delete name_part_;
}
@@ -5203,13 +5726,12 @@ UninterpretedOption_NamePart::~UninterpretedOption_NamePart() {
}
const ::google::protobuf::Descriptor* UninterpretedOption_NamePart::descriptor() {
- if (UninterpretedOption_NamePart_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return UninterpretedOption_NamePart_descriptor_;
}
const UninterpretedOption_NamePart& UninterpretedOption_NamePart::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
UninterpretedOption_NamePart* UninterpretedOption_NamePart::default_instance_ = NULL;
@@ -5278,25 +5800,47 @@ bool UninterpretedOption_NamePart::MergePartialFromCodedStream(
#undef DO_
}
-bool UninterpretedOption_NamePart::SerializeWithCachedSizes(
+void UninterpretedOption_NamePart::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(1, this->name_part(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(1, this->name_part(), output);
}
// required bool is_extension = 2;
if (_has_bit(1)) {
- DO_(::google::protobuf::internal::WireFormat::WriteBool(2, this->is_extension(), output));
+ ::google::protobuf::internal::WireFormat::WriteBool(2, this->is_extension(), output);
}
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* UninterpretedOption_NamePart::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // required string name_part = 1;
+ if (_has_bit(0)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(1, this->name_part(), target);
+ }
+
+ // required bool is_extension = 2;
+ if (_has_bit(1)) {
+ target = ::google::protobuf::internal::WireFormat::WriteBoolToArray(2, this->is_extension(), target);
+ }
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int UninterpretedOption_NamePart::ByteSize() const {
@@ -5382,7 +5926,7 @@ const ::google::protobuf::Descriptor* UninterpretedOption_NamePart::GetDescripto
}
const ::google::protobuf::Reflection* UninterpretedOption_NamePart::GetReflection() const {
- if (UninterpretedOption_NamePart_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return UninterpretedOption_NamePart_reflection_;
}
@@ -5400,35 +5944,33 @@ const int UninterpretedOption::kStringValueFieldNumber;
#endif // !_MSC_VER
UninterpretedOption::UninterpretedOption()
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(),
- identifier_value_(const_cast< ::std::string*>(&_default_identifier_value_)),
- positive_int_value_(GOOGLE_ULONGLONG(0)),
- negative_int_value_(GOOGLE_LONGLONG(0)),
- double_value_(0),
- string_value_(const_cast< ::std::string*>(&_default_string_value_)) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
}
void UninterpretedOption::InitAsDefaultInstance() {}
UninterpretedOption::UninterpretedOption(const UninterpretedOption& from)
- : ::google::protobuf::Message(),
- _unknown_fields_(),
- _cached_size_(0),
- name_(),
- identifier_value_(const_cast< ::std::string*>(&_default_identifier_value_)),
- positive_int_value_(GOOGLE_ULONGLONG(0)),
- negative_int_value_(GOOGLE_LONGLONG(0)),
- double_value_(0),
- string_value_(const_cast< ::std::string*>(&_default_string_value_)) {
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ : ::google::protobuf::Message() {
+ SharedCtor();
MergeFrom(from);
}
+void UninterpretedOption::SharedCtor() {
+ _cached_size_ = 0;
+ identifier_value_ = const_cast< ::std::string*>(&_default_identifier_value_);
+ positive_int_value_ = GOOGLE_ULONGLONG(0);
+ negative_int_value_ = GOOGLE_LONGLONG(0);
+ double_value_ = 0;
+ string_value_ = const_cast< ::std::string*>(&_default_string_value_);
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
UninterpretedOption::~UninterpretedOption() {
+ SharedDtor();
+}
+
+void UninterpretedOption::SharedDtor() {
if (identifier_value_ != &_default_identifier_value_) {
delete identifier_value_;
}
@@ -5440,13 +5982,12 @@ UninterpretedOption::~UninterpretedOption() {
}
const ::google::protobuf::Descriptor* UninterpretedOption::descriptor() {
- if (UninterpretedOption_descriptor_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return UninterpretedOption_descriptor_;
}
const UninterpretedOption& UninterpretedOption::default_instance() {
- if (default_instance_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
- return *default_instance_;
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_;
}
UninterpretedOption* UninterpretedOption::default_instance_ = NULL;
@@ -5578,45 +6119,87 @@ bool UninterpretedOption::MergePartialFromCodedStream(
#undef DO_
}
-bool UninterpretedOption::SerializeWithCachedSizes(
+void UninterpretedOption::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
-#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+ ::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++) {
- DO_(::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->name(i), output));
+ ::google::protobuf::internal::WireFormat::WriteMessageNoVirtual(2, this->name(i), output);
}
// optional string identifier_value = 3;
if (_has_bit(1)) {
- DO_(::google::protobuf::internal::WireFormat::WriteString(3, this->identifier_value(), output));
+ ::google::protobuf::internal::WireFormat::WriteString(3, this->identifier_value(), output);
}
// optional uint64 positive_int_value = 4;
if (_has_bit(2)) {
- DO_(::google::protobuf::internal::WireFormat::WriteUInt64(4, this->positive_int_value(), output));
+ ::google::protobuf::internal::WireFormat::WriteUInt64(4, this->positive_int_value(), output);
}
// optional int64 negative_int_value = 5;
if (_has_bit(3)) {
- DO_(::google::protobuf::internal::WireFormat::WriteInt64(5, this->negative_int_value(), output));
+ ::google::protobuf::internal::WireFormat::WriteInt64(5, this->negative_int_value(), output);
}
// optional double double_value = 6;
if (_has_bit(4)) {
- DO_(::google::protobuf::internal::WireFormat::WriteDouble(6, this->double_value(), output));
+ ::google::protobuf::internal::WireFormat::WriteDouble(6, this->double_value(), output);
}
// optional bytes string_value = 7;
if (_has_bit(5)) {
- DO_(::google::protobuf::internal::WireFormat::WriteBytes(7, this->string_value(), output));
+ ::google::protobuf::internal::WireFormat::WriteBytes(7, this->string_value(), output);
}
if (!unknown_fields().empty()) {
- DO_(::google::protobuf::internal::WireFormat::SerializeUnknownFields(
- unknown_fields(), output));
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
}
- return true;
-#undef DO_
+}
+
+::google::protobuf::uint8* UninterpretedOption::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
+ for (int i = 0; i < this->name_size(); i++) {
+ target = ::google::protobuf::internal::WireFormat::WriteMessageNoVirtualToArray(2, this->name(i), target);
+ }
+
+ // optional string identifier_value = 3;
+ if (_has_bit(1)) {
+ target = ::google::protobuf::internal::WireFormat::WriteStringToArray(3, this->identifier_value(), target);
+ }
+
+ // optional uint64 positive_int_value = 4;
+ if (_has_bit(2)) {
+ target = ::google::protobuf::internal::WireFormat::WriteUInt64ToArray(4, this->positive_int_value(), target);
+ }
+
+ // optional int64 negative_int_value = 5;
+ if (_has_bit(3)) {
+ target = ::google::protobuf::internal::WireFormat::WriteInt64ToArray(5, this->negative_int_value(), target);
+ }
+
+ // optional double double_value = 6;
+ if (_has_bit(4)) {
+ target = ::google::protobuf::internal::WireFormat::WriteDoubleToArray(6, this->double_value(), target);
+ }
+
+ // optional bytes string_value = 7;
+ if (_has_bit(5)) {
+ target = ::google::protobuf::internal::WireFormat::WriteBytesToArray(7, this->string_value(), target);
+ }
+
+ if (!unknown_fields().empty()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ return target;
}
int UninterpretedOption::ByteSize() const {
@@ -5746,7 +6329,7 @@ const ::google::protobuf::Descriptor* UninterpretedOption::GetDescriptor() const
}
const ::google::protobuf::Reflection* UninterpretedOption::GetReflection() const {
- if (UninterpretedOption_reflection_ == NULL) protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ protobuf_AssignDescriptorsOnce();
return UninterpretedOption_reflection_;
}
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index c073db51..96ccdea0 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -26,9 +26,8 @@ namespace google {
namespace protobuf {
// Internal implementation detail -- do not call these.
-void LIBPROTOBUF_EXPORT protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto();
-void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- ::google::protobuf::FileDescriptor* file);
+void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
class FileDescriptorSet;
class FileDescriptorProto;
@@ -74,6 +73,15 @@ 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;
+inline const ::std::string& FieldDescriptorProto_Type_Name(FieldDescriptorProto_Type value) {
+ return ::google::protobuf::internal::NameOfEnum(
+ FieldDescriptorProto_Type_descriptor(), value);
+}
+inline bool FieldDescriptorProto_Type_Parse(
+ const ::std::string& name, FieldDescriptorProto_Type* value) {
+ return ::google::protobuf::internal::ParseNamedEnum<FieldDescriptorProto_Type>(
+ FieldDescriptorProto_Type_descriptor(), name, value);
+}
enum FieldDescriptorProto_Label {
FieldDescriptorProto_Label_LABEL_OPTIONAL = 1,
FieldDescriptorProto_Label_LABEL_REQUIRED = 2,
@@ -84,6 +92,15 @@ 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;
+inline const ::std::string& FieldDescriptorProto_Label_Name(FieldDescriptorProto_Label value) {
+ return ::google::protobuf::internal::NameOfEnum(
+ FieldDescriptorProto_Label_descriptor(), value);
+}
+inline bool FieldDescriptorProto_Label_Parse(
+ const ::std::string& name, FieldDescriptorProto_Label* value) {
+ return ::google::protobuf::internal::ParseNamedEnum<FieldDescriptorProto_Label>(
+ FieldDescriptorProto_Label_descriptor(), name, value);
+}
enum FileOptions_OptimizeMode {
FileOptions_OptimizeMode_SPEED = 1,
FileOptions_OptimizeMode_CODE_SIZE = 2
@@ -93,6 +110,15 @@ LIBPROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value);
const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = FileOptions_OptimizeMode_SPEED;
const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = FileOptions_OptimizeMode_CODE_SIZE;
+inline const ::std::string& FileOptions_OptimizeMode_Name(FileOptions_OptimizeMode value) {
+ return ::google::protobuf::internal::NameOfEnum(
+ FileOptions_OptimizeMode_descriptor(), value);
+}
+inline bool FileOptions_OptimizeMode_Parse(
+ const ::std::string& name, FileOptions_OptimizeMode* value) {
+ return ::google::protobuf::internal::ParseNamedEnum<FileOptions_OptimizeMode>(
+ FileOptions_OptimizeMode_descriptor(), name, value);
+}
enum FieldOptions_CType {
FieldOptions_CType_CORD = 1,
FieldOptions_CType_STRING_PIECE = 2
@@ -102,6 +128,15 @@ LIBPROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value);
const FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_CORD;
const FieldOptions_CType FieldOptions_CType_CType_MAX = FieldOptions_CType_STRING_PIECE;
+inline const ::std::string& FieldOptions_CType_Name(FieldOptions_CType value) {
+ return ::google::protobuf::internal::NameOfEnum(
+ FieldOptions_CType_descriptor(), value);
+}
+inline bool FieldOptions_CType_Parse(
+ const ::std::string& name, FieldOptions_CType* value) {
+ return ::google::protobuf::internal::ParseNamedEnum<FieldOptions_CType>(
+ FieldOptions_CType_descriptor(), name, value);
+}
// ===================================================================
class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message {
@@ -137,14 +172,17 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
void MergeFrom(const FileDescriptorSet& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -170,8 +208,8 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -223,14 +261,17 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
void MergeFrom(const FileDescriptorProto& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -248,6 +289,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline const ::std::string& name() const;
inline void set_name(const ::std::string& value);
inline void set_name(const char* value);
+ inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
// optional string package = 2;
@@ -257,6 +299,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline const ::std::string& package() const;
inline void set_package(const ::std::string& value);
inline void set_package(const char* value);
+ inline void set_package(const char* value, size_t size);
inline ::std::string* mutable_package();
// repeated string dependency = 3;
@@ -269,9 +312,11 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline ::std::string* mutable_dependency(int index);
inline void set_dependency(int index, const ::std::string& value);
inline void set_dependency(int index, const char* value);
+ inline void set_dependency(int index, const char* value, size_t size);
inline ::std::string* add_dependency();
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);
// repeated .google.protobuf.DescriptorProto message_type = 4;
inline int message_type_size() const;
@@ -334,8 +379,8 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto > service_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_;
::google::protobuf::FileOptions* options_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -387,14 +432,17 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
void MergeFrom(const DescriptorProto_ExtensionRange& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -425,8 +473,8 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
::google::protobuf::int32 start_;
::google::protobuf::int32 end_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -478,14 +526,17 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
void MergeFrom(const DescriptorProto& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -505,6 +556,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
inline const ::std::string& name() const;
inline void set_name(const ::std::string& value);
inline void set_name(const char* value);
+ inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
// repeated .google.protobuf.FieldDescriptorProto field = 2;
@@ -576,8 +628,8 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange > extension_range_;
::google::protobuf::MessageOptions* options_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -629,14 +681,17 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
void MergeFrom(const FieldDescriptorProto& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -671,6 +726,13 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
static inline bool Type_IsValid(int value) {
return FieldDescriptorProto_Type_IsValid(value);
}
+ static inline const ::std::string& Type_Name(Type value) {
+ return FieldDescriptorProto_Type_Name(value);
+ }
+ static inline bool Type_Parse(const ::std::string& name,
+ Type* value) {
+ return FieldDescriptorProto_Type_Parse(name, value);
+ }
static const Type Type_MIN =
FieldDescriptorProto_Type_Type_MIN;
static const Type Type_MAX =
@@ -687,6 +749,13 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
static inline bool Label_IsValid(int value) {
return FieldDescriptorProto_Label_IsValid(value);
}
+ static inline const ::std::string& Label_Name(Label value) {
+ return FieldDescriptorProto_Label_Name(value);
+ }
+ static inline bool Label_Parse(const ::std::string& name,
+ Label* value) {
+ return FieldDescriptorProto_Label_Parse(name, value);
+ }
static const Label Label_MIN =
FieldDescriptorProto_Label_Label_MIN;
static const Label Label_MAX =
@@ -701,6 +770,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline const ::std::string& name() const;
inline void set_name(const ::std::string& value);
inline void set_name(const char* value);
+ inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
// optional int32 number = 3;
@@ -731,6 +801,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline const ::std::string& type_name() const;
inline void set_type_name(const ::std::string& value);
inline void set_type_name(const char* value);
+ inline void set_type_name(const char* value, size_t size);
inline ::std::string* mutable_type_name();
// optional string extendee = 2;
@@ -740,6 +811,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline const ::std::string& extendee() const;
inline void set_extendee(const ::std::string& value);
inline void set_extendee(const char* value);
+ inline void set_extendee(const char* value, size_t size);
inline ::std::string* mutable_extendee();
// optional string default_value = 7;
@@ -749,6 +821,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline const ::std::string& default_value() const;
inline void set_default_value(const ::std::string& value);
inline void set_default_value(const char* value);
+ inline void set_default_value(const char* value, size_t size);
inline ::std::string* mutable_default_value();
// optional .google.protobuf.FieldOptions options = 8;
@@ -774,8 +847,8 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
::std::string* default_value_;
static const ::std::string _default_default_value_;
::google::protobuf::FieldOptions* options_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -827,14 +900,17 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
void MergeFrom(const EnumDescriptorProto& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -852,6 +928,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
inline const ::std::string& name() const;
inline void set_name(const ::std::string& value);
inline void set_name(const char* value);
+ inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
@@ -879,8 +956,8 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
static const ::std::string _default_name_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_;
::google::protobuf::EnumOptions* options_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -932,14 +1009,17 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
void MergeFrom(const EnumValueDescriptorProto& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -957,6 +1037,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
inline const ::std::string& name() const;
inline void set_name(const ::std::string& value);
inline void set_name(const char* value);
+ inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
// optional int32 number = 2;
@@ -981,8 +1062,8 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
static const ::std::string _default_name_;
::google::protobuf::int32 number_;
::google::protobuf::EnumValueOptions* options_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1034,14 +1115,17 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
void MergeFrom(const ServiceDescriptorProto& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -1059,6 +1143,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
inline const ::std::string& name() const;
inline void set_name(const ::std::string& value);
inline void set_name(const char* value);
+ inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
// repeated .google.protobuf.MethodDescriptorProto method = 2;
@@ -1086,8 +1171,8 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
static const ::std::string _default_name_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_;
::google::protobuf::ServiceOptions* options_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1139,14 +1224,17 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
void MergeFrom(const MethodDescriptorProto& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -1164,6 +1252,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
inline const ::std::string& name() const;
inline void set_name(const ::std::string& value);
inline void set_name(const char* value);
+ inline void set_name(const char* value, size_t size);
inline ::std::string* mutable_name();
// optional string input_type = 2;
@@ -1173,6 +1262,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
inline const ::std::string& input_type() const;
inline void set_input_type(const ::std::string& value);
inline void set_input_type(const char* value);
+ inline void set_input_type(const char* value, size_t size);
inline ::std::string* mutable_input_type();
// optional string output_type = 3;
@@ -1182,6 +1272,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
inline const ::std::string& output_type() const;
inline void set_output_type(const ::std::string& value);
inline void set_output_type(const char* value);
+ inline void set_output_type(const char* value, size_t size);
inline ::std::string* mutable_output_type();
// optional .google.protobuf.MethodOptions options = 4;
@@ -1202,8 +1293,8 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
::std::string* output_type_;
static const ::std::string _default_output_type_;
::google::protobuf::MethodOptions* options_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1255,14 +1346,17 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
void MergeFrom(const FileOptions& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -1281,6 +1375,13 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
static inline bool OptimizeMode_IsValid(int value) {
return FileOptions_OptimizeMode_IsValid(value);
}
+ static inline const ::std::string& OptimizeMode_Name(OptimizeMode value) {
+ return FileOptions_OptimizeMode_Name(value);
+ }
+ static inline bool OptimizeMode_Parse(const ::std::string& name,
+ OptimizeMode* value) {
+ return FileOptions_OptimizeMode_Parse(name, value);
+ }
static const OptimizeMode OptimizeMode_MIN =
FileOptions_OptimizeMode_OptimizeMode_MIN;
static const OptimizeMode OptimizeMode_MAX =
@@ -1295,6 +1396,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
inline const ::std::string& java_package() const;
inline void set_java_package(const ::std::string& value);
inline void set_java_package(const char* value);
+ inline void set_java_package(const char* value, size_t size);
inline ::std::string* mutable_java_package();
// optional string java_outer_classname = 8;
@@ -1304,6 +1406,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
inline const ::std::string& java_outer_classname() const;
inline void set_java_outer_classname(const ::std::string& value);
inline void set_java_outer_classname(const char* value);
+ inline void set_java_outer_classname(const char* value, size_t size);
inline ::std::string* mutable_java_outer_classname();
// optional bool java_multiple_files = 10 [default = false];
@@ -1313,7 +1416,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
inline bool java_multiple_files() const;
inline void set_java_multiple_files(bool value);
- // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = CODE_SIZE];
+ // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
inline bool has_optimize_for() const;
inline void clear_optimize_for();
static const int kOptimizeForFieldNumber = 9;
@@ -1330,87 +1433,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- template <typename _proto_TypeTraits>
- inline bool HasExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FileOptions, _proto_TypeTraits>& id) const {
- return _extensions_.Has(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline void ClearExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FileOptions, _proto_TypeTraits>& id) {
- _extensions_.ClearExtension(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline int ExtensionSize(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FileOptions, _proto_TypeTraits>& id) const {
- return _extensions_.ExtensionSize(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::ConstType GetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FileOptions, _proto_TypeTraits>& id) const {
- return _proto_TypeTraits::Get(id.number(), _extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType MutableExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FileOptions, _proto_TypeTraits>& id) {
- return _proto_TypeTraits::Mutable(id.number(), &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void SetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FileOptions, _proto_TypeTraits>& id,
- typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Set(id.number(), value, &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::ConstType GetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FileOptions, _proto_TypeTraits>& id,
- int index) const {
- return _proto_TypeTraits::Get(id.number(), _extensions_, index);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType MutableExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FileOptions, _proto_TypeTraits>& id,
- int index) {
- return _proto_TypeTraits::Mutable(id.number(),index,&_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void SetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FileOptions, _proto_TypeTraits>& id,
- int index, typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Set(id.number(), index, value, &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType AddExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FileOptions, _proto_TypeTraits>& id) {
- return _proto_TypeTraits::Add(id.number(), &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void AddExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FileOptions, _proto_TypeTraits>& id,
- typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Add(id.number(), value, &_extensions_);
- }
+ GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -1423,8 +1446,8 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
bool java_multiple_files_;
int optimize_for_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1476,14 +1499,17 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
void MergeFrom(const MessageOptions& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -1511,87 +1537,7 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- template <typename _proto_TypeTraits>
- inline bool HasExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MessageOptions, _proto_TypeTraits>& id) const {
- return _extensions_.Has(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline void ClearExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MessageOptions, _proto_TypeTraits>& id) {
- _extensions_.ClearExtension(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline int ExtensionSize(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MessageOptions, _proto_TypeTraits>& id) const {
- return _extensions_.ExtensionSize(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::ConstType GetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MessageOptions, _proto_TypeTraits>& id) const {
- return _proto_TypeTraits::Get(id.number(), _extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType MutableExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MessageOptions, _proto_TypeTraits>& id) {
- return _proto_TypeTraits::Mutable(id.number(), &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void SetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MessageOptions, _proto_TypeTraits>& id,
- typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Set(id.number(), value, &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::ConstType GetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MessageOptions, _proto_TypeTraits>& id,
- int index) const {
- return _proto_TypeTraits::Get(id.number(), _extensions_, index);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType MutableExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MessageOptions, _proto_TypeTraits>& id,
- int index) {
- return _proto_TypeTraits::Mutable(id.number(),index,&_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void SetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MessageOptions, _proto_TypeTraits>& id,
- int index, typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Set(id.number(), index, value, &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType AddExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MessageOptions, _proto_TypeTraits>& id) {
- return _proto_TypeTraits::Add(id.number(), &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void AddExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MessageOptions, _proto_TypeTraits>& id,
- typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Add(id.number(), value, &_extensions_);
- }
+ GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -1599,8 +1545,8 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
bool message_set_wire_format_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -1652,14 +1598,17 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
void MergeFrom(const FieldOptions& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -1678,6 +1627,13 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
static inline bool CType_IsValid(int value) {
return FieldOptions_CType_IsValid(value);
}
+ static inline const ::std::string& CType_Name(CType value) {
+ return FieldOptions_CType_Name(value);
+ }
+ static inline bool CType_Parse(const ::std::string& name,
+ CType* value) {
+ return FieldOptions_CType_Parse(name, value);
+ }
static const CType CType_MIN =
FieldOptions_CType_CType_MIN;
static const CType CType_MAX =
@@ -1699,6 +1655,13 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
inline bool packed() const;
inline void set_packed(bool value);
+ // optional bool deprecated = 3 [default = false];
+ inline bool has_deprecated() const;
+ inline void clear_deprecated();
+ static const int kDeprecatedFieldNumber = 3;
+ inline bool deprecated() const;
+ inline void set_deprecated(bool value);
+
// optional string experimental_map_key = 9;
inline bool has_experimental_map_key() const;
inline void clear_experimental_map_key();
@@ -1706,6 +1669,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
inline const ::std::string& experimental_map_key() const;
inline void set_experimental_map_key(const ::std::string& value);
inline void set_experimental_map_key(const char* value);
+ inline void set_experimental_map_key(const char* value, size_t size);
inline ::std::string* mutable_experimental_map_key();
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
@@ -1718,87 +1682,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- template <typename _proto_TypeTraits>
- inline bool HasExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FieldOptions, _proto_TypeTraits>& id) const {
- return _extensions_.Has(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline void ClearExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FieldOptions, _proto_TypeTraits>& id) {
- _extensions_.ClearExtension(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline int ExtensionSize(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FieldOptions, _proto_TypeTraits>& id) const {
- return _extensions_.ExtensionSize(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::ConstType GetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FieldOptions, _proto_TypeTraits>& id) const {
- return _proto_TypeTraits::Get(id.number(), _extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType MutableExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FieldOptions, _proto_TypeTraits>& id) {
- return _proto_TypeTraits::Mutable(id.number(), &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void SetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FieldOptions, _proto_TypeTraits>& id,
- typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Set(id.number(), value, &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::ConstType GetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FieldOptions, _proto_TypeTraits>& id,
- int index) const {
- return _proto_TypeTraits::Get(id.number(), _extensions_, index);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType MutableExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FieldOptions, _proto_TypeTraits>& id,
- int index) {
- return _proto_TypeTraits::Mutable(id.number(),index,&_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void SetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FieldOptions, _proto_TypeTraits>& id,
- int index, typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Set(id.number(), index, value, &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType AddExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FieldOptions, _proto_TypeTraits>& id) {
- return _proto_TypeTraits::Add(id.number(), &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void AddExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- FieldOptions, _proto_TypeTraits>& id,
- typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Add(id.number(), value, &_extensions_);
- }
+ GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
@@ -1806,12 +1690,13 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
int ctype_;
bool packed_;
+ bool deprecated_;
::std::string* experimental_map_key_;
static const ::std::string _default_experimental_map_key_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
- ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
inline bool _has_bit(int index) const {
@@ -1862,14 +1747,17 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
void MergeFrom(const EnumOptions& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -1890,95 +1778,15 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- template <typename _proto_TypeTraits>
- inline bool HasExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumOptions, _proto_TypeTraits>& id) const {
- return _extensions_.Has(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline void ClearExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumOptions, _proto_TypeTraits>& id) {
- _extensions_.ClearExtension(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline int ExtensionSize(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumOptions, _proto_TypeTraits>& id) const {
- return _extensions_.ExtensionSize(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::ConstType GetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumOptions, _proto_TypeTraits>& id) const {
- return _proto_TypeTraits::Get(id.number(), _extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType MutableExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumOptions, _proto_TypeTraits>& id) {
- return _proto_TypeTraits::Mutable(id.number(), &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void SetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumOptions, _proto_TypeTraits>& id,
- typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Set(id.number(), value, &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::ConstType GetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumOptions, _proto_TypeTraits>& id,
- int index) const {
- return _proto_TypeTraits::Get(id.number(), _extensions_, index);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType MutableExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumOptions, _proto_TypeTraits>& id,
- int index) {
- return _proto_TypeTraits::Mutable(id.number(),index,&_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void SetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumOptions, _proto_TypeTraits>& id,
- int index, typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Set(id.number(), index, value, &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType AddExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumOptions, _proto_TypeTraits>& id) {
- return _proto_TypeTraits::Add(id.number(), &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void AddExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumOptions, _proto_TypeTraits>& id,
- typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Add(id.number(), value, &_extensions_);
- }
+ GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -2030,14 +1838,17 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
void MergeFrom(const EnumValueOptions& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -2058,95 +1869,15 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- template <typename _proto_TypeTraits>
- inline bool HasExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumValueOptions, _proto_TypeTraits>& id) const {
- return _extensions_.Has(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline void ClearExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumValueOptions, _proto_TypeTraits>& id) {
- _extensions_.ClearExtension(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline int ExtensionSize(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumValueOptions, _proto_TypeTraits>& id) const {
- return _extensions_.ExtensionSize(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::ConstType GetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumValueOptions, _proto_TypeTraits>& id) const {
- return _proto_TypeTraits::Get(id.number(), _extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType MutableExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumValueOptions, _proto_TypeTraits>& id) {
- return _proto_TypeTraits::Mutable(id.number(), &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void SetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumValueOptions, _proto_TypeTraits>& id,
- typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Set(id.number(), value, &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::ConstType GetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumValueOptions, _proto_TypeTraits>& id,
- int index) const {
- return _proto_TypeTraits::Get(id.number(), _extensions_, index);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType MutableExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumValueOptions, _proto_TypeTraits>& id,
- int index) {
- return _proto_TypeTraits::Mutable(id.number(),index,&_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void SetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumValueOptions, _proto_TypeTraits>& id,
- int index, typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Set(id.number(), index, value, &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType AddExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumValueOptions, _proto_TypeTraits>& id) {
- return _proto_TypeTraits::Add(id.number(), &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void AddExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- EnumValueOptions, _proto_TypeTraits>& id,
- typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Add(id.number(), value, &_extensions_);
- }
+ GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -2198,14 +1929,17 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
void MergeFrom(const ServiceOptions& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -2226,95 +1960,15 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- template <typename _proto_TypeTraits>
- inline bool HasExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- ServiceOptions, _proto_TypeTraits>& id) const {
- return _extensions_.Has(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline void ClearExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- ServiceOptions, _proto_TypeTraits>& id) {
- _extensions_.ClearExtension(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline int ExtensionSize(
- const ::google::protobuf::internal::ExtensionIdentifier<
- ServiceOptions, _proto_TypeTraits>& id) const {
- return _extensions_.ExtensionSize(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::ConstType GetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- ServiceOptions, _proto_TypeTraits>& id) const {
- return _proto_TypeTraits::Get(id.number(), _extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType MutableExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- ServiceOptions, _proto_TypeTraits>& id) {
- return _proto_TypeTraits::Mutable(id.number(), &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void SetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- ServiceOptions, _proto_TypeTraits>& id,
- typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Set(id.number(), value, &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::ConstType GetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- ServiceOptions, _proto_TypeTraits>& id,
- int index) const {
- return _proto_TypeTraits::Get(id.number(), _extensions_, index);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType MutableExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- ServiceOptions, _proto_TypeTraits>& id,
- int index) {
- return _proto_TypeTraits::Mutable(id.number(),index,&_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void SetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- ServiceOptions, _proto_TypeTraits>& id,
- int index, typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Set(id.number(), index, value, &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType AddExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- ServiceOptions, _proto_TypeTraits>& id) {
- return _proto_TypeTraits::Add(id.number(), &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void AddExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- ServiceOptions, _proto_TypeTraits>& id,
- typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Add(id.number(), value, &_extensions_);
- }
+ GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -2366,14 +2020,17 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
void MergeFrom(const MethodOptions& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -2394,95 +2051,15 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- template <typename _proto_TypeTraits>
- inline bool HasExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MethodOptions, _proto_TypeTraits>& id) const {
- return _extensions_.Has(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline void ClearExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MethodOptions, _proto_TypeTraits>& id) {
- _extensions_.ClearExtension(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline int ExtensionSize(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MethodOptions, _proto_TypeTraits>& id) const {
- return _extensions_.ExtensionSize(id.number());
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::ConstType GetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MethodOptions, _proto_TypeTraits>& id) const {
- return _proto_TypeTraits::Get(id.number(), _extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType MutableExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MethodOptions, _proto_TypeTraits>& id) {
- return _proto_TypeTraits::Mutable(id.number(), &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void SetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MethodOptions, _proto_TypeTraits>& id,
- typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Set(id.number(), value, &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::ConstType GetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MethodOptions, _proto_TypeTraits>& id,
- int index) const {
- return _proto_TypeTraits::Get(id.number(), _extensions_, index);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType MutableExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MethodOptions, _proto_TypeTraits>& id,
- int index) {
- return _proto_TypeTraits::Mutable(id.number(),index,&_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void SetExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MethodOptions, _proto_TypeTraits>& id,
- int index, typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Set(id.number(), index, value, &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline typename _proto_TypeTraits::MutableType AddExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MethodOptions, _proto_TypeTraits>& id) {
- return _proto_TypeTraits::Add(id.number(), &_extensions_);
- }
-
- template <typename _proto_TypeTraits>
- inline void AddExtension(
- const ::google::protobuf::internal::ExtensionIdentifier<
- MethodOptions, _proto_TypeTraits>& id,
- typename _proto_TypeTraits::ConstType value) {
- _proto_TypeTraits::Add(id.number(), value, &_extensions_);
- }
+ GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions)
private:
::google::protobuf::internal::ExtensionSet _extensions_;
::google::protobuf::UnknownFieldSet _unknown_fields_;
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -2534,14 +2111,17 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
void MergeFrom(const UninterpretedOption_NamePart& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -2559,6 +2139,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
inline const ::std::string& name_part() const;
inline void set_name_part(const ::std::string& value);
inline void set_name_part(const char* value);
+ inline void set_name_part(const char* value, size_t size);
inline ::std::string* mutable_name_part();
// required bool is_extension = 2;
@@ -2575,8 +2156,8 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
::std::string* name_part_;
static const ::std::string _default_name_part_;
bool is_extension_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -2628,14 +2209,17 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
void MergeFrom(const UninterpretedOption& from);
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
- bool SerializeWithCachedSizes(
+ void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
+ void SharedCtor();
+ void SharedDtor();
void SetCachedSize(int size) const { _cached_size_ = size; }
public:
@@ -2665,6 +2249,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
inline const ::std::string& identifier_value() const;
inline void set_identifier_value(const ::std::string& value);
inline void set_identifier_value(const char* value);
+ inline void set_identifier_value(const char* value, size_t size);
inline ::std::string* mutable_identifier_value();
// optional uint64 positive_int_value = 4;
@@ -2710,8 +2295,8 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
double double_value_;
::std::string* string_value_;
static const ::std::string _default_string_value_;
- friend void protobuf_BuildDesc_google_2fprotobuf_2fdescriptor_2eproto_AssignGlobalDescriptors(
- const ::google::protobuf::FileDescriptor* file);
+ friend void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::uint32 _has_bits_[(6 + 31) / 32];
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
@@ -2794,6 +2379,13 @@ inline void FileDescriptorProto::set_name(const char* value) {
}
name_->assign(value);
}
+inline void FileDescriptorProto::set_name(const char* value, size_t size) {
+ _set_bit(0);
+ if (name_ == &_default_name_) {
+ name_ = new ::std::string;
+ }
+ name_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* FileDescriptorProto::mutable_name() {
_set_bit(0);
if (name_ == &_default_name_) {
@@ -2829,6 +2421,13 @@ inline void FileDescriptorProto::set_package(const char* value) {
}
package_->assign(value);
}
+inline void FileDescriptorProto::set_package(const char* value, size_t size) {
+ _set_bit(1);
+ if (package_ == &_default_package_) {
+ package_ = new ::std::string;
+ }
+ package_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* FileDescriptorProto::mutable_package() {
_set_bit(1);
if (package_ == &_default_package_) {
@@ -2864,6 +2463,10 @@ inline void FileDescriptorProto::set_dependency(int index, const ::std::string&
inline void FileDescriptorProto::set_dependency(int index, const char* value) {
dependency_.Mutable(index)->assign(value);
}
+inline void FileDescriptorProto::set_dependency(int index, const char* value, size_t size) {
+ dependency_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* FileDescriptorProto::add_dependency() {
return dependency_.Add();
}
@@ -2873,6 +2476,9 @@ inline void FileDescriptorProto::add_dependency(const ::std::string& value) {
inline void FileDescriptorProto::add_dependency(const char* value) {
dependency_.Add()->assign(value);
}
+inline void FileDescriptorProto::add_dependency(const char* value, size_t size) {
+ dependency_.Add()->assign(reinterpret_cast<const char*>(value), size);
+}
// repeated .google.protobuf.DescriptorProto message_type = 4;
inline int FileDescriptorProto::message_type_size() const {
@@ -3058,6 +2664,13 @@ inline void DescriptorProto::set_name(const char* value) {
}
name_->assign(value);
}
+inline void DescriptorProto::set_name(const char* value, size_t size) {
+ _set_bit(0);
+ if (name_ == &_default_name_) {
+ name_ = new ::std::string;
+ }
+ name_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* DescriptorProto::mutable_name() {
_set_bit(0);
if (name_ == &_default_name_) {
@@ -3239,6 +2852,13 @@ inline void FieldDescriptorProto::set_name(const char* value) {
}
name_->assign(value);
}
+inline void FieldDescriptorProto::set_name(const char* value, size_t size) {
+ _set_bit(0);
+ if (name_ == &_default_name_) {
+ name_ = new ::std::string;
+ }
+ name_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* FieldDescriptorProto::mutable_name() {
_set_bit(0);
if (name_ == &_default_name_) {
@@ -3324,6 +2944,13 @@ inline void FieldDescriptorProto::set_type_name(const char* value) {
}
type_name_->assign(value);
}
+inline void FieldDescriptorProto::set_type_name(const char* value, size_t size) {
+ _set_bit(4);
+ if (type_name_ == &_default_type_name_) {
+ type_name_ = new ::std::string;
+ }
+ type_name_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* FieldDescriptorProto::mutable_type_name() {
_set_bit(4);
if (type_name_ == &_default_type_name_) {
@@ -3359,6 +2986,13 @@ inline void FieldDescriptorProto::set_extendee(const char* value) {
}
extendee_->assign(value);
}
+inline void FieldDescriptorProto::set_extendee(const char* value, size_t size) {
+ _set_bit(5);
+ if (extendee_ == &_default_extendee_) {
+ extendee_ = new ::std::string;
+ }
+ extendee_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* FieldDescriptorProto::mutable_extendee() {
_set_bit(5);
if (extendee_ == &_default_extendee_) {
@@ -3394,6 +3028,13 @@ inline void FieldDescriptorProto::set_default_value(const char* value) {
}
default_value_->assign(value);
}
+inline void FieldDescriptorProto::set_default_value(const char* value, size_t size) {
+ _set_bit(6);
+ if (default_value_ == &_default_default_value_) {
+ default_value_ = new ::std::string;
+ }
+ default_value_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* FieldDescriptorProto::mutable_default_value() {
_set_bit(6);
if (default_value_ == &_default_default_value_) {
@@ -3450,6 +3091,13 @@ inline void EnumDescriptorProto::set_name(const char* value) {
}
name_->assign(value);
}
+inline void EnumDescriptorProto::set_name(const char* value, size_t size) {
+ _set_bit(0);
+ if (name_ == &_default_name_) {
+ name_ = new ::std::string;
+ }
+ name_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* EnumDescriptorProto::mutable_name() {
_set_bit(0);
if (name_ == &_default_name_) {
@@ -3531,6 +3179,13 @@ inline void EnumValueDescriptorProto::set_name(const char* value) {
}
name_->assign(value);
}
+inline void EnumValueDescriptorProto::set_name(const char* value, size_t size) {
+ _set_bit(0);
+ if (name_ == &_default_name_) {
+ name_ = new ::std::string;
+ }
+ name_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* EnumValueDescriptorProto::mutable_name() {
_set_bit(0);
if (name_ == &_default_name_) {
@@ -3603,6 +3258,13 @@ inline void ServiceDescriptorProto::set_name(const char* value) {
}
name_->assign(value);
}
+inline void ServiceDescriptorProto::set_name(const char* value, size_t size) {
+ _set_bit(0);
+ if (name_ == &_default_name_) {
+ name_ = new ::std::string;
+ }
+ name_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* ServiceDescriptorProto::mutable_name() {
_set_bit(0);
if (name_ == &_default_name_) {
@@ -3684,6 +3346,13 @@ inline void MethodDescriptorProto::set_name(const char* value) {
}
name_->assign(value);
}
+inline void MethodDescriptorProto::set_name(const char* value, size_t size) {
+ _set_bit(0);
+ if (name_ == &_default_name_) {
+ name_ = new ::std::string;
+ }
+ name_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* MethodDescriptorProto::mutable_name() {
_set_bit(0);
if (name_ == &_default_name_) {
@@ -3719,6 +3388,13 @@ inline void MethodDescriptorProto::set_input_type(const char* value) {
}
input_type_->assign(value);
}
+inline void MethodDescriptorProto::set_input_type(const char* value, size_t size) {
+ _set_bit(1);
+ if (input_type_ == &_default_input_type_) {
+ input_type_ = new ::std::string;
+ }
+ input_type_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* MethodDescriptorProto::mutable_input_type() {
_set_bit(1);
if (input_type_ == &_default_input_type_) {
@@ -3754,6 +3430,13 @@ inline void MethodDescriptorProto::set_output_type(const char* value) {
}
output_type_->assign(value);
}
+inline void MethodDescriptorProto::set_output_type(const char* value, size_t size) {
+ _set_bit(2);
+ if (output_type_ == &_default_output_type_) {
+ output_type_ = new ::std::string;
+ }
+ output_type_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* MethodDescriptorProto::mutable_output_type() {
_set_bit(2);
if (output_type_ == &_default_output_type_) {
@@ -3810,6 +3493,13 @@ inline void FileOptions::set_java_package(const char* value) {
}
java_package_->assign(value);
}
+inline void FileOptions::set_java_package(const char* value, size_t size) {
+ _set_bit(0);
+ if (java_package_ == &_default_java_package_) {
+ java_package_ = new ::std::string;
+ }
+ java_package_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* FileOptions::mutable_java_package() {
_set_bit(0);
if (java_package_ == &_default_java_package_) {
@@ -3845,6 +3535,13 @@ inline void FileOptions::set_java_outer_classname(const char* value) {
}
java_outer_classname_->assign(value);
}
+inline void FileOptions::set_java_outer_classname(const char* value, size_t size) {
+ _set_bit(1);
+ if (java_outer_classname_ == &_default_java_outer_classname_) {
+ java_outer_classname_ = new ::std::string;
+ }
+ java_outer_classname_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* FileOptions::mutable_java_outer_classname() {
_set_bit(1);
if (java_outer_classname_ == &_default_java_outer_classname_) {
@@ -3869,12 +3566,12 @@ inline void FileOptions::set_java_multiple_files(bool value) {
java_multiple_files_ = value;
}
-// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = CODE_SIZE];
+// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
inline bool FileOptions::has_optimize_for() const {
return _has_bit(3);
}
inline void FileOptions::clear_optimize_for() {
- optimize_for_ = 2;
+ optimize_for_ = 1;
_clear_bit(3);
}
inline ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const {
@@ -3993,35 +3690,58 @@ inline void FieldOptions::set_packed(bool value) {
packed_ = value;
}
+// optional bool deprecated = 3 [default = false];
+inline bool FieldOptions::has_deprecated() const {
+ return _has_bit(2);
+}
+inline void FieldOptions::clear_deprecated() {
+ deprecated_ = false;
+ _clear_bit(2);
+}
+inline bool FieldOptions::deprecated() const {
+ return deprecated_;
+}
+inline void FieldOptions::set_deprecated(bool value) {
+ _set_bit(2);
+ deprecated_ = value;
+}
+
// optional string experimental_map_key = 9;
inline bool FieldOptions::has_experimental_map_key() const {
- return _has_bit(2);
+ return _has_bit(3);
}
inline void FieldOptions::clear_experimental_map_key() {
if (experimental_map_key_ != &_default_experimental_map_key_) {
experimental_map_key_->clear();
}
- _clear_bit(2);
+ _clear_bit(3);
}
inline const ::std::string& FieldOptions::experimental_map_key() const {
return *experimental_map_key_;
}
inline void FieldOptions::set_experimental_map_key(const ::std::string& value) {
- _set_bit(2);
+ _set_bit(3);
if (experimental_map_key_ == &_default_experimental_map_key_) {
experimental_map_key_ = new ::std::string;
}
experimental_map_key_->assign(value);
}
inline void FieldOptions::set_experimental_map_key(const char* value) {
- _set_bit(2);
+ _set_bit(3);
if (experimental_map_key_ == &_default_experimental_map_key_) {
experimental_map_key_ = new ::std::string;
}
experimental_map_key_->assign(value);
}
+inline void FieldOptions::set_experimental_map_key(const char* value, size_t size) {
+ _set_bit(3);
+ if (experimental_map_key_ == &_default_experimental_map_key_) {
+ experimental_map_key_ = new ::std::string;
+ }
+ experimental_map_key_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* FieldOptions::mutable_experimental_map_key() {
- _set_bit(2);
+ _set_bit(3);
if (experimental_map_key_ == &_default_experimental_map_key_) {
experimental_map_key_ = new ::std::string;
}
@@ -4200,6 +3920,13 @@ inline void UninterpretedOption_NamePart::set_name_part(const char* value) {
}
name_part_->assign(value);
}
+inline void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) {
+ _set_bit(0);
+ if (name_part_ == &_default_name_part_) {
+ name_part_ = new ::std::string;
+ }
+ name_part_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* UninterpretedOption_NamePart::mutable_name_part() {
_set_bit(0);
if (name_part_ == &_default_name_part_) {
@@ -4280,6 +4007,13 @@ inline void UninterpretedOption::set_identifier_value(const char* value) {
}
identifier_value_->assign(value);
}
+inline void UninterpretedOption::set_identifier_value(const char* value, size_t size) {
+ _set_bit(1);
+ if (identifier_value_ == &_default_identifier_value_) {
+ identifier_value_ = new ::std::string;
+ }
+ identifier_value_->assign(reinterpret_cast<const char*>(value), size);
+}
inline ::std::string* UninterpretedOption::mutable_identifier_value() {
_set_bit(1);
if (identifier_value_ == &_default_identifier_value_) {
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index e0e6f7f2..381a7438 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -250,7 +250,7 @@ message FileOptions {
SPEED = 1; // Generate complete code for parsing, serialization, etc.
CODE_SIZE = 2; // Use ReflectionOps to implement these methods.
}
- optional OptimizeMode optimize_for = 9 [default=CODE_SIZE];
+ optional OptimizeMode optimize_for = 9 [default=SPEED];
@@ -306,6 +306,12 @@ 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
+ // is a formalization for deprecating fields.
+ optional bool deprecated = 3 [default=false];
+
// EXPERIMENTAL. DO NOT USE.
// For "map" fields, the name of the field in the enclosed type that
// is the key for this map. For example, suppose we have:
@@ -328,6 +334,7 @@ message FieldOptions {
}
message EnumOptions {
+
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc
index 6a233cea..910f7e4e 100644
--- a/src/google/protobuf/descriptor_database.cc
+++ b/src/google/protobuf/descriptor_database.cc
@@ -33,7 +33,11 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/descriptor_database.h>
+
+#include <set>
+
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/stl_util-inl.h>
#include <google/protobuf/stubs/map-util.h>
@@ -44,151 +48,312 @@ DescriptorDatabase::~DescriptorDatabase() {}
// ===================================================================
-SimpleDescriptorDatabase::SimpleDescriptorDatabase() {}
-SimpleDescriptorDatabase::~SimpleDescriptorDatabase() {
- STLDeleteElements(&files_to_delete_);
-}
-
-void SimpleDescriptorDatabase::Add(const FileDescriptorProto& file) {
- FileDescriptorProto* new_file = new FileDescriptorProto;
- new_file->CopyFrom(file);
- AddAndOwn(new_file);
-}
-
-void SimpleDescriptorDatabase::AddAndOwn(const FileDescriptorProto* file) {
- files_to_delete_.push_back(file);
- InsertOrUpdate(&files_by_name_, file->name(), file);
+template <typename Value>
+bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddFile(
+ const FileDescriptorProto& file,
+ Value value) {
+ if (!InsertIfNotPresent(&by_name_, file.name(), value)) {
+ GOOGLE_LOG(ERROR) << "File already exists in database: " << file.name();
+ return false;
+ }
- string path = file->package();
+ string path = file.package();
if (!path.empty()) path += '.';
- for (int i = 0; i < file->message_type_size(); i++) {
- AddMessage(path, file->message_type(i), file);
+ for (int i = 0; i < file.message_type_size(); i++) {
+ if (!AddSymbol(path + file.message_type(i).name(), value)) return false;
+ if (!AddNestedExtensions(file.message_type(i), value)) return false;
}
- for (int i = 0; i < file->enum_type_size(); i++) {
- AddEnum(path, file->enum_type(i), file);
+ for (int i = 0; i < file.enum_type_size(); i++) {
+ if (!AddSymbol(path + file.enum_type(i).name(), value)) return false;
}
- for (int i = 0; i < file->extension_size(); i++) {
- AddField(path, file->extension(i), file);
+ for (int i = 0; i < file.extension_size(); i++) {
+ if (!AddSymbol(path + file.extension(i).name(), value)) return false;
+ if (!AddExtension(file.extension(i), value)) return false;
}
- for (int i = 0; i < file->service_size(); i++) {
- AddService(path, file->service(i), file);
+ for (int i = 0; i < file.service_size(); i++) {
+ if (!AddSymbol(path + file.service(i).name(), value)) return false;
}
+
+ return true;
}
-void SimpleDescriptorDatabase::AddMessage(
- const string& path,
- const DescriptorProto& message_type,
- const FileDescriptorProto* file) {
- string full_name = path + message_type.name();
- InsertOrUpdate(&files_by_symbol_, full_name, file);
+template <typename Value>
+bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddSymbol(
+ const string& name, Value value) {
+ // We need to make sure not to violate our map invariant.
- string sub_path = full_name + '.';
- for (int i = 0; i < message_type.nested_type_size(); i++) {
- AddMessage(sub_path, message_type.nested_type(i), file);
+ // If the symbol name is invalid it could break our lookup algorithm (which
+ // relies on the fact that '.' sorts before all other characters that are
+ // valid in symbol names).
+ if (!ValidateSymbolName(name)) {
+ GOOGLE_LOG(ERROR) << "Invalid symbol name: " << name;
+ return false;
+ }
+
+ // Try to look up the symbol to make sure a super-symbol doesn't already
+ // exist.
+ typename map<string, Value>::iterator iter = FindLastLessOrEqual(name);
+
+ if (iter == by_symbol_.end()) {
+ // Apparently the map is currently empty. Just insert and be done with it.
+ by_symbol_.insert(make_pair(name, value));
+ return true;
}
- for (int i = 0; i < message_type.enum_type_size(); i++) {
- AddEnum(sub_path, message_type.enum_type(i), file);
+
+ if (IsSubSymbol(iter->first, name)) {
+ GOOGLE_LOG(ERROR) << "Symbol name \"" << name << "\" conflicts with the existing "
+ "symbol \"" << iter->first << "\".";
+ return false;
}
- for (int i = 0; i < message_type.field_size(); i++) {
- AddField(sub_path, message_type.field(i), file);
+
+ // OK, that worked. Now we have to make sure that no symbol in the map is
+ // a sub-symbol of the one we are inserting. The only symbol which could
+ // be so is the first symbol that is greater than the new symbol. Since
+ // |iter| points at the last symbol that is less than or equal, we just have
+ // to increment it.
+ ++iter;
+
+ if (iter != by_symbol_.end() && IsSubSymbol(name, iter->first)) {
+ GOOGLE_LOG(ERROR) << "Symbol name \"" << name << "\" conflicts with the existing "
+ "symbol \"" << iter->first << "\".";
+ return false;
+ }
+
+ // OK, no conflicts.
+
+ // Insert the new symbol using the iterator as a hint, the new entry will
+ // appear immediately before the one the iterator is pointing at.
+ by_symbol_.insert(iter, make_pair(name, value));
+
+ return true;
+}
+
+template <typename Value>
+bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddNestedExtensions(
+ const DescriptorProto& message_type,
+ Value value) {
+ for (int i = 0; i < message_type.nested_type_size(); i++) {
+ if (!AddNestedExtensions(message_type.nested_type(i), value)) return false;
}
for (int i = 0; i < message_type.extension_size(); i++) {
- AddField(sub_path, message_type.extension(i), file);
+ if (!AddExtension(message_type.extension(i), value)) return false;
}
+ return true;
}
-void SimpleDescriptorDatabase::AddField(
- const string& path,
+template <typename Value>
+bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddExtension(
const FieldDescriptorProto& field,
- const FileDescriptorProto* file) {
- string full_name = path + field.name();
- InsertOrUpdate(&files_by_symbol_, full_name, file);
-
- if (field.has_extendee()) {
- // This field is an extension.
- if (!field.extendee().empty() && field.extendee()[0] == '.') {
- // The extension is fully-qualified. We can use it as a lookup key in
- // the files_by_symbol_ table.
- InsertOrUpdate(&files_by_extension_,
- make_pair(field.extendee().substr(1), field.number()),
- file);
- } else {
- // Not fully-qualified. We can't really do anything here, unfortunately.
+ Value value) {
+ if (!field.extendee().empty() && field.extendee()[0] == '.') {
+ // The extension is fully-qualified. We can use it as a lookup key in
+ // the by_symbol_ table.
+ if (!InsertIfNotPresent(&by_extension_,
+ make_pair(field.extendee().substr(1),
+ field.number()),
+ value)) {
+ GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: "
+ "extend " << field.extendee() << " { "
+ << field.name() << " = " << field.number() << " }";
+ return false;
}
+ } else {
+ // Not fully-qualified. We can't really do anything here, unfortunately.
+ // We don't consider this an error, though, because the descriptor is
+ // valid.
}
+ return true;
}
-void SimpleDescriptorDatabase::AddEnum(
- const string& path,
- const EnumDescriptorProto& enum_type,
- const FileDescriptorProto* file) {
- string full_name = path + enum_type.name();
- InsertOrUpdate(&files_by_symbol_, full_name, file);
+template <typename Value>
+Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindFile(
+ const string& filename) {
+ return FindWithDefault(by_name_, filename, Value());
+}
+
+template <typename Value>
+Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindSymbol(
+ const string& name) {
+ typename map<string, Value>::iterator iter = FindLastLessOrEqual(name);
+
+ return (iter != by_symbol_.end() && IsSubSymbol(iter->first, name)) ?
+ iter->second : Value();
+}
- string sub_path = full_name + '.';
- for (int i = 0; i < enum_type.value_size(); i++) {
- InsertOrUpdate(&files_by_symbol_,
- sub_path + enum_type.value(i).name(),
- file);
+template <typename Value>
+Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindExtension(
+ const string& containing_type,
+ int field_number) {
+ return FindWithDefault(by_extension_,
+ make_pair(containing_type, field_number),
+ Value());
+}
+
+template <typename Value>
+bool SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllExtensionNumbers(
+ const string& containing_type,
+ vector<int>* output) {
+ typename map<pair<string, int>, Value >::const_iterator it =
+ by_extension_.lower_bound(make_pair(containing_type, 0));
+ bool success = false;
+
+ for (; it != by_extension_.end() && it->first.first == containing_type;
+ ++it) {
+ output->push_back(it->first.second);
+ success = true;
}
+
+ return success;
+}
+
+template <typename Value>
+typename map<string, Value>::iterator
+SimpleDescriptorDatabase::DescriptorIndex<Value>::FindLastLessOrEqual(
+ const string& name) {
+ // Find the last key in the map which sorts less than or equal to the
+ // symbol name. Since upper_bound() returns the *first* key that sorts
+ // *greater* than the input, we want the element immediately before that.
+ typename map<string, Value>::iterator iter = by_symbol_.upper_bound(name);
+ if (iter != by_symbol_.begin()) --iter;
+ return iter;
}
-void SimpleDescriptorDatabase::AddService(
- const string& path,
- const ServiceDescriptorProto& service,
- const FileDescriptorProto* file) {
- string full_name = path + service.name();
- InsertOrUpdate(&files_by_symbol_, full_name, file);
+template <typename Value>
+bool SimpleDescriptorDatabase::DescriptorIndex<Value>::IsSubSymbol(
+ const string& sub_symbol, const string& super_symbol) {
+ return sub_symbol == super_symbol ||
+ (HasPrefixString(super_symbol, sub_symbol) &&
+ super_symbol[sub_symbol.size()] == '.');
+}
- string sub_path = full_name + '.';
- for (int i = 0; i < service.method_size(); i++) {
- InsertOrUpdate(&files_by_symbol_,
- sub_path + service.method(i).name(),
- file);
+template <typename Value>
+bool SimpleDescriptorDatabase::DescriptorIndex<Value>::ValidateSymbolName(
+ const string& name) {
+ for (int i = 0; i < name.size(); i++) {
+ // I don't trust ctype.h due to locales. :(
+ if (name[i] != '.' && name[i] != '_' &&
+ (name[i] < '0' || name[i] > '9') &&
+ (name[i] < 'A' || name[i] > 'Z') &&
+ (name[i] < 'a' || name[i] > 'z')) {
+ return false;
+ }
}
+ return true;
+}
+
+// -------------------------------------------------------------------
+
+SimpleDescriptorDatabase::SimpleDescriptorDatabase() {}
+SimpleDescriptorDatabase::~SimpleDescriptorDatabase() {
+ STLDeleteElements(&files_to_delete_);
+}
+
+bool SimpleDescriptorDatabase::Add(const FileDescriptorProto& file) {
+ FileDescriptorProto* new_file = new FileDescriptorProto;
+ new_file->CopyFrom(file);
+ return AddAndOwn(new_file);
+}
+
+bool SimpleDescriptorDatabase::AddAndOwn(const FileDescriptorProto* file) {
+ files_to_delete_.push_back(file);
+ return index_.AddFile(*file, file);
}
bool SimpleDescriptorDatabase::FindFileByName(
const string& filename,
FileDescriptorProto* output) {
- const FileDescriptorProto* result = FindPtrOrNull(files_by_name_, filename);
- if (result == NULL) {
- return false;
- } else {
- output->CopyFrom(*result);
- return true;
- }
+ return MaybeCopy(index_.FindFile(filename), output);
}
bool SimpleDescriptorDatabase::FindFileContainingSymbol(
const string& symbol_name,
FileDescriptorProto* output) {
- const FileDescriptorProto* result =
- FindPtrOrNull(files_by_symbol_, symbol_name);
- if (result == NULL) {
- return false;
- } else {
- output->CopyFrom(*result);
- return true;
- }
+ return MaybeCopy(index_.FindSymbol(symbol_name), output);
}
bool SimpleDescriptorDatabase::FindFileContainingExtension(
const string& containing_type,
int field_number,
FileDescriptorProto* output) {
- const FileDescriptorProto* result =
- FindPtrOrNull(files_by_extension_,
- make_pair(containing_type, field_number));
- if (result == NULL) {
- return false;
+ return MaybeCopy(index_.FindExtension(containing_type, field_number), output);
+}
+
+bool SimpleDescriptorDatabase::FindAllExtensionNumbers(
+ const string& extendee_type,
+ vector<int>* output) {
+ return index_.FindAllExtensionNumbers(extendee_type, output);
+}
+
+bool SimpleDescriptorDatabase::MaybeCopy(const FileDescriptorProto* file,
+ FileDescriptorProto* output) {
+ if (file == NULL) return false;
+ output->CopyFrom(*file);
+ return true;
+}
+
+// -------------------------------------------------------------------
+
+EncodedDescriptorDatabase::EncodedDescriptorDatabase() {}
+EncodedDescriptorDatabase::~EncodedDescriptorDatabase() {
+ for (int i = 0; i < files_to_delete_.size(); i++) {
+ operator delete(files_to_delete_[i]);
+ }
+}
+
+bool EncodedDescriptorDatabase::Add(
+ const void* encoded_file_descriptor, int size) {
+ FileDescriptorProto file;
+ if (file.ParseFromArray(encoded_file_descriptor, size)) {
+ return index_.AddFile(file, make_pair(encoded_file_descriptor, size));
} else {
- output->CopyFrom(*result);
- return true;
+ GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to "
+ "EncodedDescriptorDatabase::Add().";
+ return false;
}
}
+bool EncodedDescriptorDatabase::AddCopy(
+ const void* encoded_file_descriptor, int size) {
+ void* copy = operator new(size);
+ memcpy(copy, encoded_file_descriptor, size);
+ files_to_delete_.push_back(copy);
+ return Add(copy, size);
+}
+
+bool EncodedDescriptorDatabase::FindFileByName(
+ const string& filename,
+ FileDescriptorProto* output) {
+ return MaybeParse(index_.FindFile(filename), output);
+}
+
+bool EncodedDescriptorDatabase::FindFileContainingSymbol(
+ const string& symbol_name,
+ FileDescriptorProto* output) {
+ return MaybeParse(index_.FindSymbol(symbol_name), output);
+}
+
+bool EncodedDescriptorDatabase::FindFileContainingExtension(
+ const string& containing_type,
+ int field_number,
+ FileDescriptorProto* output) {
+ return MaybeParse(index_.FindExtension(containing_type, field_number),
+ output);
+}
+
+bool EncodedDescriptorDatabase::FindAllExtensionNumbers(
+ const string& extendee_type,
+ vector<int>* output) {
+ return index_.FindAllExtensionNumbers(extendee_type, output);
+}
+
+bool EncodedDescriptorDatabase::MaybeParse(
+ pair<const void*, int> encoded_file,
+ FileDescriptorProto* output) {
+ if (encoded_file.first == NULL) return false;
+ return output->ParseFromArray(encoded_file.first, encoded_file.second);
+}
+
// ===================================================================
DescriptorPoolDatabase::DescriptorPoolDatabase(const DescriptorPool& pool)
@@ -231,6 +396,22 @@ bool DescriptorPoolDatabase::FindFileContainingExtension(
return true;
}
+bool DescriptorPoolDatabase::FindAllExtensionNumbers(
+ const string& extendee_type,
+ vector<int>* output) {
+ const Descriptor* extendee = pool_.FindMessageTypeByName(extendee_type);
+ if (extendee == NULL) return false;
+
+ vector<const FieldDescriptor*> extensions;
+ pool_.FindAllExtensions(extendee, &extensions);
+
+ for (int i = 0; i < extensions.size(); ++i) {
+ output->push_back(extensions[i]->number());
+ }
+
+ return true;
+}
+
// ===================================================================
MergedDescriptorDatabase::MergedDescriptorDatabase(
@@ -301,5 +482,27 @@ bool MergedDescriptorDatabase::FindFileContainingExtension(
return false;
}
+bool MergedDescriptorDatabase::FindAllExtensionNumbers(
+ const string& extendee_type,
+ vector<int>* output) {
+ set<int> merged_results;
+ vector<int> results;
+ bool success = false;
+
+ for (int i = 0; i < sources_.size(); i++) {
+ if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) {
+ copy(results.begin(), results.end(),
+ insert_iterator<set<int> >(merged_results, merged_results.begin()));
+ success = true;
+ }
+ results.clear();
+ }
+
+ copy(merged_results.begin(), merged_results.end(),
+ insert_iterator<vector<int> >(*output, output->end()));
+
+ return success;
+}
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h
index 1230d09b..c23ab75f 100644
--- a/src/google/protobuf/descriptor_database.h
+++ b/src/google/protobuf/descriptor_database.h
@@ -46,6 +46,13 @@
namespace google {
namespace protobuf {
+// Defined in this file.
+class DescriptorDatabase;
+class SimpleDescriptorDatabase;
+class EncodedDescriptorDatabase;
+class DescriptorPoolDatabase;
+class MergedDescriptorDatabase;
+
// Abstract interface for a database of descriptors.
//
// This is useful if you want to create a DescriptorPool which loads
@@ -78,6 +85,21 @@ class LIBPROTOBUF_EXPORT DescriptorDatabase {
int field_number,
FileDescriptorProto* output) = 0;
+ // Finds the tag numbers used by all known extensions of
+ // extendee_type, and appends them to output in an undefined
+ // order. This method is best-effort: it's not guaranteed that the
+ // database will find all extensions, and it's not guaranteed that
+ // FindFileContainingExtension will return true on all of the found
+ // numbers. Returns true if the search was successful, otherwise
+ // returns false and leaves output unchanged.
+ //
+ // This method has a default implementation that always returns
+ // false.
+ virtual bool FindAllExtensionNumbers(const string& extendee_type,
+ vector<int>* output) {
+ return false;
+ }
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorDatabase);
};
@@ -85,7 +107,11 @@ class LIBPROTOBUF_EXPORT DescriptorDatabase {
// A DescriptorDatabase into which you can insert files manually.
//
// FindFileContainingSymbol() is fully-implemented. When you add a file, its
-// symbols will be indexed for this purpose.
+// symbols will be indexed for this purpose. Note that the implementation
+// may return false positives, but only if it isn't possible for the symbol
+// to be defined in any other file. In particular, if a file defines a symbol
+// "Foo", then searching for "Foo.[anything]" will match that file. This way,
+// the database does not need to aggressively index all children of a symbol.
//
// FindFileContainingExtension() is mostly-implemented. It works if and only
// if the original FieldDescriptorProto defining the extension has a
@@ -105,11 +131,13 @@ class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
~SimpleDescriptorDatabase();
// Adds the FileDescriptorProto to the database, making a copy. The object
- // can be deleted after Add() returns.
- void Add(const FileDescriptorProto& file);
+ // can be deleted after Add() returns. Returns false if the file conflicted
+ // with a file already in the database, in which case an error will have
+ // been written to GOOGLE_LOG(ERROR).
+ bool Add(const FileDescriptorProto& file);
// Adds the FileDescriptorProto to the database and takes ownership of it.
- void AddAndOwn(const FileDescriptorProto* file);
+ bool AddAndOwn(const FileDescriptorProto* file);
// implements DescriptorDatabase -----------------------------------
bool FindFileByName(const string& filename,
@@ -119,31 +147,162 @@ class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
bool FindFileContainingExtension(const string& containing_type,
int field_number,
FileDescriptorProto* output);
+ bool FindAllExtensionNumbers(const string& extendee_type,
+ vector<int>* output);
private:
- // Helpers to recursively add particular descriptors and all their contents
- // to the by-symbol and by-extension tables.
- void AddMessage(const string& path,
- const DescriptorProto& message_type,
- const FileDescriptorProto* file);
- void AddField(const string& path,
- const FieldDescriptorProto& field,
- const FileDescriptorProto* file);
- void AddEnum(const string& path,
- const EnumDescriptorProto& enum_type,
- const FileDescriptorProto* file);
- void AddService(const string& path,
- const ServiceDescriptorProto& service,
- const FileDescriptorProto* file);
+ // So that it can use DescriptorIndex.
+ friend class EncodedDescriptorDatabase;
+
+ // An index mapping file names, symbol names, and extension numbers to
+ // some sort of values.
+ template <typename Value>
+ class DescriptorIndex {
+ public:
+ // Helpers to recursively add particular descriptors and all their contents
+ // to the index.
+ bool AddFile(const FileDescriptorProto& file,
+ Value value);
+ bool AddSymbol(const string& name, Value value);
+ bool AddNestedExtensions(const DescriptorProto& message_type,
+ Value value);
+ bool AddExtension(const FieldDescriptorProto& field,
+ Value value);
+
+ Value FindFile(const string& filename);
+ Value FindSymbol(const string& name);
+ Value FindExtension(const string& containing_type, int field_number);
+ bool FindAllExtensionNumbers(const string& containing_type,
+ vector<int>* output);
+
+ private:
+ map<string, Value> by_name_;
+ map<string, Value> by_symbol_;
+ map<pair<string, int>, Value> by_extension_;
+
+ // Invariant: The by_symbol_ map does not contain any symbols which are
+ // prefixes of other symbols in the map. For example, "foo.bar" is a
+ // prefix of "foo.bar.baz" (but is not a prefix of "foo.barbaz").
+ //
+ // This invariant is important because it means that given a symbol name,
+ // we can find a key in the map which is a prefix of the symbol in O(lg n)
+ // time, and we know that there is at most one such key.
+ //
+ // The prefix lookup algorithm works like so:
+ // 1) Find the last key in the map which is less than or equal to the
+ // search key.
+ // 2) If the found key is a prefix of the search key, then return it.
+ // Otherwise, there is no match.
+ //
+ // I am sure this algorithm has been described elsewhere, but since I
+ // wasn't able to find it quickly I will instead prove that it works
+ // myself. The key to the algorithm is that if a match exists, step (1)
+ // will find it. Proof:
+ // 1) Define the "search key" to be the key we are looking for, the "found
+ // key" to be the key found in step (1), and the "match key" to be the
+ // key which actually matches the serach key (i.e. the key we're trying
+ // to find).
+ // 2) The found key must be less than or equal to the search key by
+ // definition.
+ // 3) The match key must also be less than or equal to the search key
+ // (because it is a prefix).
+ // 4) The match key cannot be greater than the found key, because if it
+ // were, then step (1) of the algorithm would have returned the match
+ // key instead (since it finds the *greatest* key which is less than or
+ // equal to the search key).
+ // 5) Therefore, the found key must be between the match key and the search
+ // key, inclusive.
+ // 6) Since the search key must be a sub-symbol of the match key, if it is
+ // not equal to the match key, then search_key[match_key.size()] must
+ // be '.'.
+ // 7) Since '.' sorts before any other character that is valid in a symbol
+ // name, then if the found key is not equal to the match key, then
+ // found_key[match_key.size()] must also be '.', because any other value
+ // would make it sort after the search key.
+ // 8) Therefore, if the found key is not equal to the match key, then the
+ // found key must be a sub-symbol of the match key. However, this would
+ // contradict our map invariant which says that no symbol in the map is
+ // a sub-symbol of any other.
+ // 9) Therefore, the found key must match the match key.
+ //
+ // The above proof assumes the match key exists. In the case that the
+ // match key does not exist, then step (1) will return some other symbol.
+ // That symbol cannot be a super-symbol of the search key since if it were,
+ // then it would be a match, and we're assuming the match key doesn't exist.
+ // Therefore, step 2 will correctly return no match.
+
+ // Find the last entry in the by_symbol_ map whose key is less than or
+ // equal to the given name.
+ typename map<string, Value>::iterator FindLastLessOrEqual(
+ const string& name);
+
+ // True if either the arguments are equal or super_symbol identifies a
+ // parent symbol of sub_symbol (e.g. "foo.bar" is a parent of
+ // "foo.bar.baz", but not a parent of "foo.barbaz").
+ bool IsSubSymbol(const string& sub_symbol, const string& super_symbol);
+ // Returns true if and only if all characters in the name are alphanumerics,
+ // underscores, or periods.
+ bool ValidateSymbolName(const string& name);
+ };
+
+
+ DescriptorIndex<const FileDescriptorProto*> index_;
vector<const FileDescriptorProto*> files_to_delete_;
- map<string, const FileDescriptorProto*> files_by_name_;
- map<string, const FileDescriptorProto*> files_by_symbol_;
- map<pair<string, int>, const FileDescriptorProto*> files_by_extension_;
+
+ // If file is non-NULL, copy it into *output and return true, otherwise
+ // return false.
+ bool MaybeCopy(const FileDescriptorProto* file,
+ FileDescriptorProto* output);
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleDescriptorDatabase);
};
+// Very similar to SimpleDescriptorDatabase, but stores all the descriptors
+// as raw bytes and generally tries to use as little memory as possible.
+//
+// The same caveats regarding FindFileContainingExtension() apply as with
+// SimpleDescriptorDatabase.
+class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
+ public:
+ EncodedDescriptorDatabase();
+ ~EncodedDescriptorDatabase();
+
+ // Adds the FileDescriptorProto to the database. The descriptor is provided
+ // in encoded form. The database does not make a copy of the bytes, nor
+ // does it take ownership; it's up to the caller to make sure the bytes
+ // remain valid for the life of the database. Returns false and logs an error
+ // if the bytes are not a valid FileDescriptorProto or if the file conflicted
+ // with a file already in the database.
+ bool Add(const void* encoded_file_descriptor, int size);
+
+ // Like Add(), but makes a copy of the data, so that the caller does not
+ // need to keep it around.
+ bool AddCopy(const void* encoded_file_descriptor, int size);
+
+ // implements DescriptorDatabase -----------------------------------
+ bool FindFileByName(const string& filename,
+ FileDescriptorProto* output);
+ bool FindFileContainingSymbol(const string& symbol_name,
+ FileDescriptorProto* output);
+ bool FindFileContainingExtension(const string& containing_type,
+ int field_number,
+ FileDescriptorProto* output);
+ bool FindAllExtensionNumbers(const string& extendee_type,
+ vector<int>* output);
+
+ private:
+ SimpleDescriptorDatabase::DescriptorIndex<pair<const void*, int> > index_;
+ vector<void*> files_to_delete_;
+
+ // If encoded_file.first is non-NULL, parse the data into *output and return
+ // true, otherwise return false.
+ bool MaybeParse(pair<const void*, int> encoded_file,
+ FileDescriptorProto* output);
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EncodedDescriptorDatabase);
+};
+
// A DescriptorDatabase that fetches files from a given pool.
class LIBPROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase {
public:
@@ -158,6 +317,8 @@ class LIBPROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase {
bool FindFileContainingExtension(const string& containing_type,
int field_number,
FileDescriptorProto* output);
+ bool FindAllExtensionNumbers(const string& extendee_type,
+ vector<int>* output);
private:
const DescriptorPool& pool_;
@@ -185,6 +346,10 @@ class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase {
bool FindFileContainingExtension(const string& containing_type,
int field_number,
FileDescriptorProto* output);
+ // Merges the results of calling all databases. Returns true iff any
+ // of the databases returned true.
+ bool FindAllExtensionNumbers(const string& extendee_type,
+ vector<int>* output);
private:
vector<DescriptorDatabase*> sources_;
diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc
index d56de04c..64ec551a 100644
--- a/src/google/protobuf/descriptor_database_unittest.cc
+++ b/src/google/protobuf/descriptor_database_unittest.cc
@@ -48,13 +48,6 @@ namespace google {
namespace protobuf {
namespace {
-static bool AddToPool(DescriptorPool* pool, const char* file_text) {
- FileDescriptorProto file_proto;
- if (!TextFormat::ParseFromString(file_text, &file_proto)) return false;
- if (pool->BuildFile(file_proto) == NULL) return false;
- return true;
-}
-
static void AddToDatabase(SimpleDescriptorDatabase* database,
const char* file_text) {
FileDescriptorProto file_proto;
@@ -74,25 +67,134 @@ static void ExpectContainsType(const FileDescriptorProto& proto,
// ===================================================================
-TEST(SimpleDescriptorDatabaseTest, FindFileByName) {
- SimpleDescriptorDatabase database;
- AddToDatabase(&database,
+#if GTEST_HAS_PARAM_TEST
+
+// SimpleDescriptorDatabase, EncodedDescriptorDatabase, and
+// DescriptorPoolDatabase call for very similar tests. Instead of writing
+// three nearly-identical sets of tests, we use parameterized tests to apply
+// the same code to all three.
+
+// The parameterized test runs against a DescriptarDatabaseTestCase. We have
+// implementations for each of the three classes we want to test.
+class DescriptorDatabaseTestCase {
+ public:
+ virtual ~DescriptorDatabaseTestCase() {}
+
+ virtual DescriptorDatabase* GetDatabase() = 0;
+ virtual bool AddToDatabase(const FileDescriptorProto& file) = 0;
+};
+
+// Factory function type.
+typedef DescriptorDatabaseTestCase* DescriptorDatabaseTestCaseFactory();
+
+// Specialization for SimpleDescriptorDatabase.
+class SimpleDescriptorDatabaseTestCase : public DescriptorDatabaseTestCase {
+ public:
+ static DescriptorDatabaseTestCase* New() {
+ return new SimpleDescriptorDatabaseTestCase;
+ }
+
+ virtual ~SimpleDescriptorDatabaseTestCase() {}
+
+ virtual DescriptorDatabase* GetDatabase() {
+ return &database_;
+ }
+ virtual bool AddToDatabase(const FileDescriptorProto& file) {
+ return database_.Add(file);
+ }
+
+ private:
+ SimpleDescriptorDatabase database_;
+};
+
+// Specialization for EncodedDescriptorDatabase.
+class EncodedDescriptorDatabaseTestCase : public DescriptorDatabaseTestCase {
+ public:
+ static DescriptorDatabaseTestCase* New() {
+ return new EncodedDescriptorDatabaseTestCase;
+ }
+
+ virtual ~EncodedDescriptorDatabaseTestCase() {}
+
+ virtual DescriptorDatabase* GetDatabase() {
+ return &database_;
+ }
+ virtual bool AddToDatabase(const FileDescriptorProto& file) {
+ string data;
+ file.SerializeToString(&data);
+ return database_.AddCopy(data.data(), data.size());
+ }
+
+ private:
+ EncodedDescriptorDatabase database_;
+};
+
+// Specialization for DescriptorPoolDatabase.
+class DescriptorPoolDatabaseTestCase : public DescriptorDatabaseTestCase {
+ public:
+ static DescriptorDatabaseTestCase* New() {
+ return new EncodedDescriptorDatabaseTestCase;
+ }
+
+ DescriptorPoolDatabaseTestCase() : database_(pool_) {}
+ virtual ~DescriptorPoolDatabaseTestCase() {}
+
+ virtual DescriptorDatabase* GetDatabase() {
+ return &database_;
+ }
+ virtual bool AddToDatabase(const FileDescriptorProto& file) {
+ return pool_.BuildFile(file);
+ }
+
+ private:
+ DescriptorPool pool_;
+ DescriptorPoolDatabase database_;
+};
+
+// -------------------------------------------------------------------
+
+class DescriptorDatabaseTest
+ : public testing::TestWithParam<DescriptorDatabaseTestCaseFactory*> {
+ protected:
+ virtual void SetUp() {
+ test_case_.reset(GetParam()());
+ database_ = test_case_->GetDatabase();
+ }
+
+ void AddToDatabase(const char* file_descriptor_text) {
+ FileDescriptorProto file_proto;
+ EXPECT_TRUE(TextFormat::ParseFromString(file_descriptor_text, &file_proto));
+ EXPECT_TRUE(test_case_->AddToDatabase(file_proto));
+ }
+
+ void AddToDatabaseWithError(const char* file_descriptor_text) {
+ FileDescriptorProto file_proto;
+ EXPECT_TRUE(TextFormat::ParseFromString(file_descriptor_text, &file_proto));
+ EXPECT_FALSE(test_case_->AddToDatabase(file_proto));
+ }
+
+ scoped_ptr<DescriptorDatabaseTestCase> test_case_;
+ DescriptorDatabase* database_;
+};
+
+TEST_P(DescriptorDatabaseTest, FindFileByName) {
+ AddToDatabase(
"name: \"foo.proto\" "
"message_type { name:\"Foo\" }");
- AddToDatabase(&database,
+ AddToDatabase(
"name: \"bar.proto\" "
"message_type { name:\"Bar\" }");
{
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileByName("foo.proto", &file));
+ EXPECT_TRUE(database_->FindFileByName("foo.proto", &file));
EXPECT_EQ("foo.proto", file.name());
ExpectContainsType(file, "Foo");
}
{
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileByName("bar.proto", &file));
+ EXPECT_TRUE(database_->FindFileByName("bar.proto", &file));
EXPECT_EQ("bar.proto", file.name());
ExpectContainsType(file, "Bar");
}
@@ -100,13 +202,12 @@ TEST(SimpleDescriptorDatabaseTest, FindFileByName) {
{
// Fails to find undefined files.
FileDescriptorProto file;
- EXPECT_FALSE(database.FindFileByName("baz.proto", &file));
+ EXPECT_FALSE(database_->FindFileByName("baz.proto", &file));
}
}
-TEST(SimpleDescriptorDatabaseTest, FindFileContainingSymbol) {
- SimpleDescriptorDatabase database;
- AddToDatabase(&database,
+TEST_P(DescriptorDatabaseTest, FindFileContainingSymbol) {
+ AddToDatabase(
"name: \"foo.proto\" "
"message_type { "
" name: \"Foo\" "
@@ -124,96 +225,95 @@ TEST(SimpleDescriptorDatabaseTest, FindFileContainingSymbol) {
" method { name: \"Thud\" } "
"}"
);
- AddToDatabase(&database,
+ AddToDatabase(
"name: \"bar.proto\" "
"package: \"corge\" "
"message_type { name: \"Bar\" }");
{
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingSymbol("Foo", &file));
+ EXPECT_TRUE(database_->FindFileContainingSymbol("Foo", &file));
EXPECT_EQ("foo.proto", file.name());
}
{
// Can find fields.
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingSymbol("Foo.qux", &file));
+ EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.qux", &file));
EXPECT_EQ("foo.proto", file.name());
}
{
// Can find nested types.
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingSymbol("Foo.Grault", &file));
+ EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.Grault", &file));
EXPECT_EQ("foo.proto", file.name());
}
{
// Can find nested enums.
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingSymbol("Foo.Garply", &file));
+ EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.Garply", &file));
EXPECT_EQ("foo.proto", file.name());
}
{
// Can find enum types.
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingSymbol("Waldo", &file));
+ EXPECT_TRUE(database_->FindFileContainingSymbol("Waldo", &file));
EXPECT_EQ("foo.proto", file.name());
}
{
// Can find enum values.
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingSymbol("Waldo.FRED", &file));
+ EXPECT_TRUE(database_->FindFileContainingSymbol("Waldo.FRED", &file));
EXPECT_EQ("foo.proto", file.name());
}
{
// Can find extensions.
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingSymbol("plugh", &file));
+ EXPECT_TRUE(database_->FindFileContainingSymbol("plugh", &file));
EXPECT_EQ("foo.proto", file.name());
}
{
// Can find services.
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingSymbol("Xyzzy", &file));
+ EXPECT_TRUE(database_->FindFileContainingSymbol("Xyzzy", &file));
EXPECT_EQ("foo.proto", file.name());
}
{
// Can find methods.
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingSymbol("Xyzzy.Thud", &file));
+ EXPECT_TRUE(database_->FindFileContainingSymbol("Xyzzy.Thud", &file));
EXPECT_EQ("foo.proto", file.name());
}
{
// Can find things in packages.
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingSymbol("corge.Bar", &file));
+ EXPECT_TRUE(database_->FindFileContainingSymbol("corge.Bar", &file));
EXPECT_EQ("bar.proto", file.name());
}
{
// Fails to find undefined symbols.
FileDescriptorProto file;
- EXPECT_FALSE(database.FindFileContainingSymbol("Baz", &file));
+ EXPECT_FALSE(database_->FindFileContainingSymbol("Baz", &file));
}
{
// Names must be fully-qualified.
FileDescriptorProto file;
- EXPECT_FALSE(database.FindFileContainingSymbol("Bar", &file));
+ EXPECT_FALSE(database_->FindFileContainingSymbol("Bar", &file));
}
}
-TEST(SimpleDescriptorDatabaseTest, FindFileContainingExtension) {
- SimpleDescriptorDatabase database;
- AddToDatabase(&database,
+TEST_P(DescriptorDatabaseTest, FindFileContainingExtension) {
+ AddToDatabase(
"name: \"foo.proto\" "
"message_type { "
" name: \"Foo\" "
@@ -221,7 +321,7 @@ TEST(SimpleDescriptorDatabaseTest, FindFileContainingExtension) {
" extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
" extendee: \".Foo\" }"
"}");
- AddToDatabase(&database,
+ AddToDatabase(
"name: \"bar.proto\" "
"package: \"corge\" "
"dependency: \"foo.proto\" "
@@ -235,20 +335,20 @@ TEST(SimpleDescriptorDatabaseTest, FindFileContainingExtension) {
{
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingExtension("Foo", 5, &file));
+ EXPECT_TRUE(database_->FindFileContainingExtension("Foo", 5, &file));
EXPECT_EQ("foo.proto", file.name());
}
{
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingExtension("Foo", 32, &file));
+ EXPECT_TRUE(database_->FindFileContainingExtension("Foo", 32, &file));
EXPECT_EQ("bar.proto", file.name());
}
{
// Can find extensions for qualified type names.
FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingExtension("corge.Bar", 70, &file));
+ EXPECT_TRUE(database_->FindFileContainingExtension("corge.Bar", 70, &file));
EXPECT_EQ("bar.proto", file.name());
}
@@ -256,173 +356,127 @@ TEST(SimpleDescriptorDatabaseTest, FindFileContainingExtension) {
// Can't find extensions whose extendee was not fully-qualified in the
// FileDescriptorProto.
FileDescriptorProto file;
- EXPECT_FALSE(database.FindFileContainingExtension("Bar", 56, &file));
- EXPECT_FALSE(database.FindFileContainingExtension("corge.Bar", 56, &file));
+ EXPECT_FALSE(database_->FindFileContainingExtension("Bar", 56, &file));
+ EXPECT_FALSE(
+ database_->FindFileContainingExtension("corge.Bar", 56, &file));
}
{
// Can't find non-existent extension numbers.
FileDescriptorProto file;
- EXPECT_FALSE(database.FindFileContainingExtension("Foo", 12, &file));
+ EXPECT_FALSE(database_->FindFileContainingExtension("Foo", 12, &file));
}
{
// Can't find extensions for non-existent types.
FileDescriptorProto file;
- EXPECT_FALSE(database.FindFileContainingExtension("NoSuchType", 5, &file));
+ EXPECT_FALSE(
+ database_->FindFileContainingExtension("NoSuchType", 5, &file));
}
{
// Can't find extensions for unqualified type names.
FileDescriptorProto file;
- EXPECT_FALSE(database.FindFileContainingExtension("Bar", 70, &file));
+ EXPECT_FALSE(database_->FindFileContainingExtension("Bar", 70, &file));
}
}
-// ===================================================================
-
-TEST(DescriptorPoolDatabaseTest, FindFileByName) {
- DescriptorPool pool;
- ASSERT_TRUE(AddToPool(&pool,
- "name: \"foo.proto\" "
- "message_type { name:\"Foo\" }"));
- ASSERT_TRUE(AddToPool(&pool,
- "name: \"bar.proto\" "
- "message_type { name:\"Bar\" }"));
-
- DescriptorPoolDatabase database(pool);
-
- {
- FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileByName("foo.proto", &file));
- EXPECT_EQ("foo.proto", file.name());
- ExpectContainsType(file, "Foo");
- }
-
- {
- FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileByName("bar.proto", &file));
- EXPECT_EQ("bar.proto", file.name());
- ExpectContainsType(file, "Bar");
- }
-
- {
- // Fails to find undefined files.
- FileDescriptorProto file;
- EXPECT_FALSE(database.FindFileByName("baz.proto", &file));
- }
-}
-
-TEST(DescriptorPoolDatabaseTest, FindFileContainingSymbol) {
- DescriptorPool pool;
- ASSERT_TRUE(AddToPool(&pool,
+TEST_P(DescriptorDatabaseTest, FindAllExtensionNumbers) {
+ AddToDatabase(
"name: \"foo.proto\" "
"message_type { "
" name: \"Foo\" "
- " field { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
- "}"));
- ASSERT_TRUE(AddToPool(&pool,
+ " extension_range { start: 1 end: 1000 } "
+ " extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
+ " extendee: \".Foo\" }"
+ "}");
+ AddToDatabase(
"name: \"bar.proto\" "
"package: \"corge\" "
- "message_type { name: \"Bar\" }"));
-
- DescriptorPoolDatabase database(pool);
-
- {
- FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingSymbol("Foo", &file));
- EXPECT_EQ("foo.proto", file.name());
- }
+ "dependency: \"foo.proto\" "
+ "message_type { "
+ " name: \"Bar\" "
+ " extension_range { start: 1 end: 1000 } "
+ "} "
+ "extension { name:\"grault\" extendee: \".Foo\" number:32 } "
+ "extension { name:\"garply\" extendee: \".corge.Bar\" number:70 } "
+ "extension { name:\"waldo\" extendee: \"Bar\" number:56 } ");
{
- // Can find fields.
- FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingSymbol("Foo.qux", &file));
- EXPECT_EQ("foo.proto", file.name());
+ vector<int> numbers;
+ EXPECT_TRUE(database_->FindAllExtensionNumbers("Foo", &numbers));
+ ASSERT_EQ(2, numbers.size());
+ sort(numbers.begin(), numbers.end());
+ EXPECT_EQ(5, numbers[0]);
+ EXPECT_EQ(32, numbers[1]);
}
{
- // Can find things in packages.
- FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingSymbol("corge.Bar", &file));
- EXPECT_EQ("bar.proto", file.name());
+ vector<int> numbers;
+ EXPECT_TRUE(database_->FindAllExtensionNumbers("corge.Bar", &numbers));
+ // Note: won't find extension 56 due to the name not being fully qualified.
+ ASSERT_EQ(1, numbers.size());
+ EXPECT_EQ(70, numbers[0]);
}
{
- // Fails to find undefined symbols.
- FileDescriptorProto file;
- EXPECT_FALSE(database.FindFileContainingSymbol("Baz", &file));
+ // Can't find extensions for non-existent types.
+ vector<int> numbers;
+ EXPECT_FALSE(database_->FindAllExtensionNumbers("NoSuchType", &numbers));
}
{
- // Names must be fully-qualified.
- FileDescriptorProto file;
- EXPECT_FALSE(database.FindFileContainingSymbol("Bar", &file));
+ // Can't find extensions for unqualified types.
+ vector<int> numbers;
+ EXPECT_FALSE(database_->FindAllExtensionNumbers("Bar", &numbers));
}
}
-TEST(DescriptorPoolDatabaseTest, FindFileContainingExtension) {
- DescriptorPool pool;
- ASSERT_TRUE(AddToPool(&pool,
+TEST_P(DescriptorDatabaseTest, ConflictingFileError) {
+ AddToDatabase(
"name: \"foo.proto\" "
"message_type { "
" name: \"Foo\" "
- " extension_range { start: 1 end: 1000 } "
- " extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
- " extendee: \"Foo\" }"
- "}"));
- ASSERT_TRUE(AddToPool(&pool,
- "name: \"bar.proto\" "
- "package: \"corge\" "
- "dependency: \"foo.proto\" "
+ "}");
+ AddToDatabaseWithError(
+ "name: \"foo.proto\" "
"message_type { "
" name: \"Bar\" "
- " extension_range { start: 1 end: 1000 } "
- "} "
- "extension { name:\"grault\" label:LABEL_OPTIONAL type:TYPE_BOOL number:32 "
- " extendee: \"Foo\" } "
- "extension { name:\"garply\" label:LABEL_OPTIONAL type:TYPE_BOOL number:70 "
- " extendee: \"Bar\" } "));
-
- DescriptorPoolDatabase database(pool);
-
- {
- FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingExtension("Foo", 5, &file));
- EXPECT_EQ("foo.proto", file.name());
- }
-
- {
- FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingExtension("Foo", 32, &file));
- EXPECT_EQ("bar.proto", file.name());
- }
+ "}");
+}
- {
- // Can find extensions for qualified type names..
- FileDescriptorProto file;
- EXPECT_TRUE(database.FindFileContainingExtension("corge.Bar", 70, &file));
- EXPECT_EQ("bar.proto", file.name());
- }
+TEST_P(DescriptorDatabaseTest, ConflictingTypeError) {
+ AddToDatabase(
+ "name: \"foo.proto\" "
+ "message_type { "
+ " name: \"Foo\" "
+ "}");
+ AddToDatabaseWithError(
+ "name: \"bar.proto\" "
+ "message_type { "
+ " name: \"Foo\" "
+ "}");
+}
- {
- // Can't find non-existent extension numbers.
- FileDescriptorProto file;
- EXPECT_FALSE(database.FindFileContainingExtension("Foo", 12, &file));
- }
+TEST_P(DescriptorDatabaseTest, ConflictingExtensionError) {
+ AddToDatabase(
+ "name: \"foo.proto\" "
+ "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
+ " extendee: \".Foo\" }");
+ AddToDatabaseWithError(
+ "name: \"bar.proto\" "
+ "extension { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 "
+ " extendee: \".Foo\" }");
+}
- {
- // Can't find extensions for non-existent types.
- FileDescriptorProto file;
- EXPECT_FALSE(database.FindFileContainingExtension("NoSuchType", 5, &file));
- }
+INSTANTIATE_TEST_CASE_P(Simple, DescriptorDatabaseTest,
+ testing::Values(&SimpleDescriptorDatabaseTestCase::New));
+INSTANTIATE_TEST_CASE_P(MemoryConserving, DescriptorDatabaseTest,
+ testing::Values(&EncodedDescriptorDatabaseTestCase::New));
+INSTANTIATE_TEST_CASE_P(Pool, DescriptorDatabaseTest,
+ testing::Values(&DescriptorPoolDatabaseTestCase::New));
- {
- // Can't find extensions for unqualified type names.
- FileDescriptorProto file;
- EXPECT_FALSE(database.FindFileContainingExtension("Bar", 70, &file));
- }
-}
+#endif // GTEST_HAS_PARAM_TEST
// ===================================================================
@@ -610,6 +664,49 @@ TEST_F(MergedDescriptorDatabaseTest, FindFileContainingExtension) {
}
}
+TEST_F(MergedDescriptorDatabaseTest, FindAllExtensionNumbers) {
+ {
+ // Message only has extension in database1_
+ vector<int> numbers;
+ EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Foo", &numbers));
+ ASSERT_EQ(1, numbers.size());
+ EXPECT_EQ(3, numbers[0]);
+ }
+
+ {
+ // Message only has extension in database2_
+ vector<int> numbers;
+ EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Bar", &numbers));
+ ASSERT_EQ(1, numbers.size());
+ EXPECT_EQ(5, numbers[0]);
+ }
+
+ {
+ // Merge results from the two databases.
+ vector<int> numbers;
+ EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Baz", &numbers));
+ ASSERT_EQ(2, numbers.size());
+ sort(numbers.begin(), numbers.end());
+ EXPECT_EQ(12, numbers[0]);
+ EXPECT_EQ(13, numbers[1]);
+ }
+
+ {
+ vector<int> numbers;
+ EXPECT_TRUE(reverse_merged_.FindAllExtensionNumbers("Baz", &numbers));
+ ASSERT_EQ(2, numbers.size());
+ sort(numbers.begin(), numbers.end());
+ EXPECT_EQ(12, numbers[0]);
+ EXPECT_EQ(13, numbers[1]);
+ }
+
+ {
+ // Can't find extensions for a non-existent message.
+ vector<int> numbers;
+ EXPECT_FALSE(reverse_merged_.FindAllExtensionNumbers("Blah", &numbers));
+ }
+}
+
} // anonymous namespace
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index 5ffaea77..ce216135 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -346,6 +346,18 @@ TEST_F(FileDescriptorTest, FindExtensionByNumber) {
EXPECT_TRUE(pool_.FindExtensionByNumber(foo_message_, 2) == NULL);
}
+TEST_F(FileDescriptorTest, BuildAgain) {
+ // Test that if te call BuildFile again on the same input we get the same
+ // FileDescriptor back.
+ FileDescriptorProto file;
+ foo_file_->CopyTo(&file);
+ EXPECT_EQ(foo_file_, pool_.BuildFile(file));
+
+ // But if we change the file then it won't work.
+ file.set_package("some.other.package");
+ EXPECT_TRUE(pool_.BuildFile(file) == NULL);
+}
+
// ===================================================================
// Test simple flat messages and fields.
@@ -1492,6 +1504,16 @@ TEST_F(ExtensionDescriptorTest, FindExtensionByName) {
EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == NULL);
}
+TEST_F(ExtensionDescriptorTest, FindAllExtensions) {
+ vector<const FieldDescriptor*> extensions;
+ pool_.FindAllExtensions(foo_, &extensions);
+ ASSERT_EQ(4, extensions.size());
+ EXPECT_EQ(10, extensions[0]->number());
+ EXPECT_EQ(19, extensions[1]->number());
+ EXPECT_EQ(30, extensions[2]->number());
+ EXPECT_EQ(39, extensions[3]->number());
+}
+
// ===================================================================
class MiscTest : public testing::Test {
@@ -1716,6 +1738,219 @@ TEST_F(MiscTest, FieldOptions) {
EXPECT_EQ(FieldOptions::CORD, bar->options().ctype());
}
+// ===================================================================
+
+class AllowUnknownDependenciesTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ FileDescriptorProto foo_proto, bar_proto;
+
+ pool_.AllowUnknownDependencies();
+
+ ASSERT_TRUE(TextFormat::ParseFromString(
+ "name: 'foo.proto'"
+ "dependency: 'bar.proto'"
+ "dependency: 'baz.proto'"
+ "message_type {"
+ " name: 'Foo'"
+ " field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'Bar' }"
+ " field { name:'baz' number:2 label:LABEL_OPTIONAL type_name:'Baz' }"
+ " field { name:'qux' number:3 label:LABEL_OPTIONAL"
+ " type_name: '.corge.Qux'"
+ " type: TYPE_ENUM"
+ " options {"
+ " uninterpreted_option {"
+ " name {"
+ " name_part: 'grault'"
+ " is_extension: true"
+ " }"
+ " positive_int_value: 1234"
+ " }"
+ " }"
+ " }"
+ "}",
+ &foo_proto));
+ ASSERT_TRUE(TextFormat::ParseFromString(
+ "name: 'bar.proto'"
+ "message_type { name: 'Bar' }",
+ &bar_proto));
+
+ // Collect pointers to stuff.
+ bar_file_ = pool_.BuildFile(bar_proto);
+ ASSERT_TRUE(bar_file_ != NULL);
+
+ ASSERT_EQ(1, bar_file_->message_type_count());
+ bar_type_ = bar_file_->message_type(0);
+
+ foo_file_ = pool_.BuildFile(foo_proto);
+ ASSERT_TRUE(foo_file_ != NULL);
+
+ ASSERT_EQ(1, foo_file_->message_type_count());
+ foo_type_ = foo_file_->message_type(0);
+
+ ASSERT_EQ(3, foo_type_->field_count());
+ bar_field_ = foo_type_->field(0);
+ baz_field_ = foo_type_->field(1);
+ qux_field_ = foo_type_->field(2);
+ }
+
+ const FileDescriptor* bar_file_;
+ const Descriptor* bar_type_;
+ const FileDescriptor* foo_file_;
+ const Descriptor* foo_type_;
+ const FieldDescriptor* bar_field_;
+ const FieldDescriptor* baz_field_;
+ const FieldDescriptor* qux_field_;
+
+ DescriptorPool pool_;
+};
+
+TEST_F(AllowUnknownDependenciesTest, PlaceholderFile) {
+ ASSERT_EQ(2, foo_file_->dependency_count());
+ EXPECT_EQ(bar_file_, foo_file_->dependency(0));
+
+ const FileDescriptor* baz_file = foo_file_->dependency(1);
+ EXPECT_EQ("baz.proto", baz_file->name());
+ EXPECT_EQ(0, baz_file->message_type_count());
+
+ // Placeholder files should not be findable.
+ EXPECT_EQ(bar_file_, pool_.FindFileByName(bar_file_->name()));
+ EXPECT_TRUE(pool_.FindFileByName(baz_file->name()) == NULL);
+}
+
+TEST_F(AllowUnknownDependenciesTest, PlaceholderTypes) {
+ ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type());
+ EXPECT_EQ(bar_type_, bar_field_->message_type());
+
+ ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_field_->type());
+ const Descriptor* baz_type = baz_field_->message_type();
+ EXPECT_EQ("Baz", baz_type->name());
+ EXPECT_EQ("Baz", baz_type->full_name());
+ EXPECT_EQ("Baz.placeholder.proto", baz_type->file()->name());
+ EXPECT_EQ(0, baz_type->extension_range_count());
+
+ ASSERT_EQ(FieldDescriptor::TYPE_ENUM, qux_field_->type());
+ const EnumDescriptor* qux_type = qux_field_->enum_type();
+ EXPECT_EQ("Qux", qux_type->name());
+ EXPECT_EQ("corge.Qux", qux_type->full_name());
+ EXPECT_EQ("corge.Qux.placeholder.proto", qux_type->file()->name());
+
+ // Placeholder types should not be findable.
+ EXPECT_EQ(bar_type_, pool_.FindMessageTypeByName(bar_type_->full_name()));
+ EXPECT_TRUE(pool_.FindMessageTypeByName(baz_type->full_name()) == NULL);
+ EXPECT_TRUE(pool_.FindEnumTypeByName(qux_type->full_name()) == NULL);
+}
+
+TEST_F(AllowUnknownDependenciesTest, CopyTo) {
+ // FieldDescriptor::CopyTo() should write non-fully-qualified type names
+ // for placeholder types which were not originally fully-qualified.
+ FieldDescriptorProto proto;
+
+ // Bar is not a placeholder, so it is fully-qualified.
+ bar_field_->CopyTo(&proto);
+ EXPECT_EQ(".Bar", proto.type_name());
+ EXPECT_EQ(FieldDescriptorProto::TYPE_MESSAGE, proto.type());
+
+ // Baz is an unqualified placeholder.
+ proto.Clear();
+ baz_field_->CopyTo(&proto);
+ EXPECT_EQ("Baz", proto.type_name());
+ EXPECT_FALSE(proto.has_type());
+
+ // Qux is a fully-qualified placeholder.
+ proto.Clear();
+ qux_field_->CopyTo(&proto);
+ EXPECT_EQ(".corge.Qux", proto.type_name());
+ EXPECT_EQ(FieldDescriptorProto::TYPE_ENUM, proto.type());
+}
+
+TEST_F(AllowUnknownDependenciesTest, CustomOptions) {
+ // Qux should still have the uninterpreted option attached.
+ ASSERT_EQ(1, qux_field_->options().uninterpreted_option_size());
+ const UninterpretedOption& option =
+ qux_field_->options().uninterpreted_option(0);
+ ASSERT_EQ(1, option.name_size());
+ EXPECT_EQ("grault", option.name(0).name_part());
+}
+
+TEST_F(AllowUnknownDependenciesTest, UnknownExtendee) {
+ // Test that we can extend an unknown type. This is slightly tricky because
+ // it means that the placeholder type must have an extension range.
+
+ FileDescriptorProto extension_proto;
+
+ ASSERT_TRUE(TextFormat::ParseFromString(
+ "name: 'extension.proto'"
+ "extension { extendee: 'UnknownType' name:'some_extension' number:123"
+ " label:LABEL_OPTIONAL type:TYPE_INT32 }",
+ &extension_proto));
+ const FileDescriptor* file = pool_.BuildFile(extension_proto);
+
+ ASSERT_TRUE(file != NULL);
+
+ ASSERT_EQ(1, file->extension_count());
+ const Descriptor* extendee = file->extension(0)->containing_type();
+ EXPECT_EQ("UnknownType", extendee->name());
+ ASSERT_EQ(1, extendee->extension_range_count());
+ EXPECT_EQ(1, extendee->extension_range(0)->start);
+ EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end);
+}
+
+TEST_F(AllowUnknownDependenciesTest, CustomOption) {
+ // Test that we can use a custom option without having parsed
+ // descriptor.proto.
+
+ FileDescriptorProto option_proto;
+
+ ASSERT_TRUE(TextFormat::ParseFromString(
+ "name: \"unknown_custom_options.proto\" "
+ "dependency: \"google/protobuf/descriptor.proto\" "
+ "extension { "
+ " extendee: \"google.protobuf.FileOptions\" "
+ " name: \"some_option\" "
+ " number: 123456 "
+ " label: LABEL_OPTIONAL "
+ " type: TYPE_INT32 "
+ "} "
+ "options { "
+ " uninterpreted_option { "
+ " name { "
+ " name_part: \"some_option\" "
+ " is_extension: true "
+ " } "
+ " positive_int_value: 1234 "
+ " } "
+ " uninterpreted_option { "
+ " name { "
+ " name_part: \"unknown_option\" "
+ " is_extension: true "
+ " } "
+ " positive_int_value: 1234 "
+ " } "
+ " uninterpreted_option { "
+ " name { "
+ " name_part: \"optimize_for\" "
+ " is_extension: false "
+ " } "
+ " identifier_value: \"SPEED\" "
+ " } "
+ "}",
+ &option_proto));
+
+ const FileDescriptor* file = pool_.BuildFile(option_proto);
+ ASSERT_TRUE(file != NULL);
+
+ // Verify that no extension options were set, but they were left as
+ // uninterpreted_options.
+ vector<const FieldDescriptor*> fields;
+ file->options().GetReflection()->ListFields(file->options(), &fields);
+ ASSERT_EQ(2, fields.size());
+ EXPECT_TRUE(file->options().has_optimize_for());
+ EXPECT_EQ(2, file->options().uninterpreted_option_size());
+}
+
+// ===================================================================
+
TEST(CustomOptions, OptionLocations) {
const Descriptor* message =
protobuf_unittest::TestMessageWithCustomOptions::descriptor();
@@ -2108,7 +2343,10 @@ TEST_F(ValidationErrorTest, DupeFile) {
// defined.
BuildFileWithErrors(
"name: \"foo.proto\" "
- "message_type { name: \"Foo\" }",
+ "message_type { name: \"Foo\" } "
+ // Add another type so that the files aren't identical (in which case there
+ // would be no error).
+ "enum_type { name: \"Bar\" }",
"foo.proto: foo.proto: OTHER: A file with this name is already in the "
"pool.\n");
@@ -2174,6 +2412,10 @@ TEST_F(ValidationErrorTest, InvalidDefaults) {
// we look up the type name.
" field { name: \"quux\" number: 5 label: LABEL_OPTIONAL"
" default_value: \"abc\" type_name: \"Foo\" }"
+
+ // Repeateds can't have defaults.
+ " field { name: \"corge\" number: 6 label: LABEL_REPEATED type: TYPE_INT32"
+ " default_value: \"1\" }"
"}",
"foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value.\n"
@@ -2181,6 +2423,10 @@ TEST_F(ValidationErrorTest, InvalidDefaults) {
"foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or "
"false.\n"
"foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n"
+ "foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default "
+ "values.\n"
+ // This ends up being reported later because the error is detected at
+ // cross-linking time.
"foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default "
"values.\n");
}
@@ -2473,6 +2719,24 @@ TEST_F(ValidationErrorTest, SearchMostLocalFirst) {
"foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is not defined.\n");
}
+TEST_F(ValidationErrorTest, SearchMostLocalFirst2) {
+ // This test would find the most local "Bar" first, and does, but
+ // proceeds to find the outer one because the inner one's not an
+ // aggregate.
+ BuildFile(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Bar\""
+ " nested_type { name: \"Baz\" }"
+ "}"
+ "message_type {"
+ " name: \"Foo\""
+ " field { name: \"Bar\" number:1 type:TYPE_BYTES } "
+ " field { name:\"baz\" number:2 label:LABEL_OPTIONAL"
+ " type_name:\"Bar.Baz\" }"
+ "}");
+}
+
TEST_F(ValidationErrorTest, PackageOriginallyDeclaredInTransitiveDependent) {
// Imagine we have the following:
//
@@ -2519,11 +2783,39 @@ TEST_F(ValidationErrorTest, FieldTypeNotAType) {
"name: \"foo.proto\" "
"message_type {"
" name: \"Foo\""
- " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"bar\" }"
+ " field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
+ " type_name:\".Foo.bar\" }"
" field { name:\"bar\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
"}",
- "foo.proto: Foo.foo: TYPE: \"bar\" is not a type.\n");
+ "foo.proto: Foo.foo: TYPE: \".Foo.bar\" is not a type.\n");
+}
+
+TEST_F(ValidationErrorTest, RelativeFieldTypeNotAType) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " nested_type {"
+ " name: \"Bar\""
+ " field { name:\"Baz\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " }"
+ " name: \"Foo\""
+ " field { name:\"foo\" number:1 label:LABEL_OPTIONAL "
+ " type_name:\"Bar.Baz\" }"
+ "}",
+ "foo.proto: Foo.foo: TYPE: \"Bar.Baz\" is not a type.\n");
+}
+
+TEST_F(ValidationErrorTest, FieldTypeMayBeItsName) {
+ BuildFile(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Bar\""
+ "}"
+ "message_type {"
+ " name: \"Foo\""
+ " field { name:\"Bar\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }"
+ "}");
}
TEST_F(ValidationErrorTest, EnumFieldTypeIsMessage) {
@@ -3346,6 +3638,21 @@ TEST_F(DatabaseBackedPoolTest, FindExtensionByNumber) {
EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == NULL);
}
+TEST_F(DatabaseBackedPoolTest, FindAllExtensions) {
+ DescriptorPool pool(&database_);
+
+ const Descriptor* foo = pool.FindMessageTypeByName("Foo");
+
+ for (int i = 0; i < 2; ++i) {
+ // Repeat the lookup twice, to check that we get consistent
+ // results despite the fallback database lookup mutating the pool.
+ vector<const FieldDescriptor*> extensions;
+ pool.FindAllExtensions(foo, &extensions);
+ ASSERT_EQ(1, extensions.size());
+ EXPECT_EQ(5, extensions[0]->number());
+ }
+}
+
TEST_F(DatabaseBackedPoolTest, ErrorWithoutErrorCollector) {
ErrorDescriptorDatabase error_database;
DescriptorPool pool(&error_database);
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index b969c13b..be8235e7 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -229,8 +229,7 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info)
new(OffsetToPointer(type_info_->unknown_fields_offset)) UnknownFieldSet;
if (type_info_->extensions_offset != -1) {
- new(OffsetToPointer(type_info_->extensions_offset))
- ExtensionSet(&type_info_->type, type_info_->pool, type_info_->factory);
+ new(OffsetToPointer(type_info_->extensions_offset)) ExtensionSet;
}
for (int i = 0; i < descriptor->field_count(); i++) {
@@ -508,6 +507,7 @@ const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
type_info->unknown_fields_offset,
type_info->extensions_offset,
type_info->pool,
+ this,
type_info->size));
// Cross link prototypes.
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index f431cedc..0e618902 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -33,68 +33,108 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/wire_format.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/wire_format_inl.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/stubs/map-util.h>
namespace google {
namespace protobuf {
namespace internal {
-// -------------------------------------------------------------------
-// Lookup functions
-
-const FieldDescriptor*
-ExtensionSet::FindKnownExtensionOrDie(int number) const {
- const FieldDescriptor* descriptor =
- descriptor_pool_->FindExtensionByNumber(*extendee_, number);
- if (descriptor == NULL) {
- // This extension doesn't exist, so we have to crash. However, let's
- // try to provide an informative error message.
- if (descriptor_pool_ == DescriptorPool::generated_pool() &&
- message_factory_ == MessageFactory::generated_factory()) {
- // This is probably the ExtensionSet for a generated class.
- GOOGLE_LOG(FATAL) << ": No extension is registered for \""
- << (*extendee_)->full_name() << "\" with number "
- << number << ". Perhaps you were trying to access it via "
- "the Reflection interface, but you provided a "
- "FieldDescriptor which did not come from a linked-in "
- "message type? This is not permitted; linkin-in message "
- "types cannot use non-linked-in extensions. Try "
- "converting to a DynamicMessage first.";
- } else {
- // This is probably a DynamicMessage.
- GOOGLE_LOG(FATAL) << ": No extension is registered for \""
- << (*extendee_)->full_name() << "\" with number "
- << number << ". If you were using a DynamicMessage, "
- "remember that you are only allowed to access extensions "
- "which are defined in the DescriptorPool which you passed "
- "to DynamicMessageFactory's constructor.";
- }
+namespace {
+
+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(real_type(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 Message* message_prototype;
+ };
+};
+
+typedef hash_map<pair<const Message*, int>, ExtensionInfo> ExtensionRegistry;
+ExtensionRegistry* registry_ = NULL;
+
+// This function is only called at startup, so there is no need for thread-
+// safety.
+void Register(const Message* containing_type, int number, ExtensionInfo info) {
+ if (registry_ == NULL) registry_ = new ExtensionRegistry;
+
+ if (!InsertIfNotPresent(registry_, make_pair(containing_type, number),
+ info)) {
+ GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \""
+ << containing_type->GetDescriptor()->full_name()
+ << "\", field number " << number << ".";
}
- return descriptor;
}
-const Message*
-ExtensionSet::GetPrototype(const Descriptor* message_type) const {
- return message_factory_->GetPrototype(message_type);
+const ExtensionInfo* FindRegisteredExtension(
+ const Message* containing_type, int number) {
+ return (registry_ == NULL) ? NULL :
+ FindOrNull(*registry_, make_pair(containing_type, number));
+}
+
+} // namespace
+
+void ExtensionSet::RegisterExtension(const Message* containing_type,
+ int number, FieldType type,
+ bool is_repeated, bool is_packed) {
+ GOOGLE_CHECK_NE(type, FieldDescriptor::TYPE_ENUM);
+ GOOGLE_CHECK_NE(type, FieldDescriptor::TYPE_MESSAGE);
+ GOOGLE_CHECK_NE(type, FieldDescriptor::TYPE_GROUP);
+ ExtensionInfo info(type, is_repeated, is_packed);
+ Register(containing_type, number, info);
+}
+
+void ExtensionSet::RegisterEnumExtension(const Message* containing_type,
+ int number, FieldType type,
+ bool is_repeated, bool is_packed,
+ EnumValidityFunc* is_valid) {
+ GOOGLE_CHECK_EQ(type, FieldDescriptor::TYPE_ENUM);
+ ExtensionInfo info(type, is_repeated, is_packed);
+ info.enum_is_valid = is_valid;
+ Register(containing_type, number, info);
+}
+
+void ExtensionSet::RegisterMessageExtension(const Message* containing_type,
+ int number, FieldType type,
+ bool is_repeated, bool is_packed,
+ const Message* prototype) {
+ GOOGLE_CHECK(type == FieldDescriptor::TYPE_MESSAGE ||
+ type == FieldDescriptor::TYPE_GROUP);
+ ExtensionInfo info(type, is_repeated, is_packed);
+ info.message_prototype = prototype;
+ Register(containing_type, number, info);
}
// ===================================================================
// Constructors and basic methods.
-ExtensionSet::ExtensionSet(const Descriptor* const* extendee,
- const DescriptorPool* pool,
- MessageFactory* factory)
- : extendee_(extendee),
- descriptor_pool_(pool),
- message_factory_(factory) {
-}
+ExtensionSet::ExtensionSet() {}
ExtensionSet::~ExtensionSet() {
for (map<int, Extension>::iterator iter = extensions_.begin();
@@ -103,18 +143,21 @@ ExtensionSet::~ExtensionSet() {
}
}
-void ExtensionSet::AppendToList(vector<const FieldDescriptor*>* output) const {
+void ExtensionSet::AppendToList(const Descriptor* containing_type,
+ const DescriptorPool* pool,
+ vector<const FieldDescriptor*>* output) const {
for (map<int, Extension>::const_iterator iter = extensions_.begin();
iter != extensions_.end(); ++iter) {
bool has = false;
- if (iter->second.descriptor->is_repeated()) {
+ if (iter->second.is_repeated) {
has = iter->second.GetSize() > 0;
} else {
has = !iter->second.is_cleared;
}
if (has) {
- output->push_back(iter->second.descriptor);
+ output->push_back(
+ pool->FindExtensionByNumber(containing_type, iter->first));
}
}
}
@@ -122,7 +165,7 @@ void ExtensionSet::AppendToList(vector<const FieldDescriptor*>* output) const {
bool ExtensionSet::Has(int number) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
if (iter == extensions_.end()) return false;
- GOOGLE_DCHECK(!iter->second.descriptor->is_repeated());
+ GOOGLE_DCHECK(!iter->second.is_repeated);
return !iter->second.is_cleared;
}
@@ -141,47 +184,46 @@ void ExtensionSet::ClearExtension(int number) {
// ===================================================================
// Field accessors
-#define GOOGLE_DCHECK_TYPE(DESCRIPTOR, LABEL, CPPTYPE) \
- GOOGLE_DCHECK_EQ(DESCRIPTOR->label(), FieldDescriptor::LABEL_##LABEL); \
- GOOGLE_DCHECK_EQ(DESCRIPTOR->cpp_type(), FieldDescriptor::CPPTYPE_##CPPTYPE)
+#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \
+ GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \
+ : FieldDescriptor::LABEL_OPTIONAL, \
+ FieldDescriptor::LABEL_##LABEL); \
+ GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
// -------------------------------------------------------------------
// Primitives
#define PRIMITIVE_ACCESSORS(UPPERCASE, LOWERCASE, CAMELCASE) \
\
-LOWERCASE ExtensionSet::Get##CAMELCASE(int number) const { \
+LOWERCASE ExtensionSet::Get##CAMELCASE(int number, \
+ LOWERCASE default_value) const { \
map<int, Extension>::const_iterator iter = extensions_.find(number); \
- if (iter == extensions_.end()) { \
- /* Not present. Return the default value. */ \
- const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number); \
- GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, UPPERCASE); \
- return descriptor->default_value_##LOWERCASE(); \
+ if (iter == extensions_.end() || iter->second.is_cleared) { \
+ return default_value; \
} else { \
- GOOGLE_DCHECK_TYPE(iter->second.descriptor, OPTIONAL, UPPERCASE); \
+ GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, UPPERCASE); \
return iter->second.LOWERCASE##_value; \
} \
} \
\
-void ExtensionSet::Set##CAMELCASE(int number, LOWERCASE value) { \
- Extension* extension = &extensions_[number]; \
- if (extension->descriptor == NULL) { \
- /* Not previoulsy present. Initialize it. */ \
- const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number); \
- GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, UPPERCASE); \
- extension->descriptor = descriptor; \
- extension->LOWERCASE##_value = descriptor->default_value_##LOWERCASE(); \
+void ExtensionSet::Set##CAMELCASE(int number, FieldType type, \
+ LOWERCASE value) { \
+ Extension* extension; \
+ if (MaybeNewExtension(number, &extension)) { \
+ extension->type = type; \
+ GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_##UPPERCASE);\
+ extension->is_repeated = false; \
} else { \
- GOOGLE_DCHECK_TYPE(extension->descriptor, OPTIONAL, UPPERCASE); \
- extension->is_cleared = false; \
+ GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, UPPERCASE); \
} \
+ extension->is_cleared = false; \
extension->LOWERCASE##_value = value; \
} \
\
LOWERCASE ExtensionSet::GetRepeated##CAMELCASE(int number, int index) const { \
map<int, Extension>::const_iterator iter = extensions_.find(number); \
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; \
- GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, UPPERCASE); \
+ GOOGLE_DCHECK_TYPE(iter->second, REPEATED, UPPERCASE); \
return iter->second.repeated_##LOWERCASE##_value->Get(index); \
} \
\
@@ -189,20 +231,22 @@ void ExtensionSet::SetRepeated##CAMELCASE( \
int number, int index, LOWERCASE value) { \
map<int, Extension>::iterator iter = extensions_.find(number); \
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; \
- GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, UPPERCASE); \
+ GOOGLE_DCHECK_TYPE(iter->second, REPEATED, UPPERCASE); \
iter->second.repeated_##LOWERCASE##_value->Set(index, value); \
} \
\
-void ExtensionSet::Add##CAMELCASE(int number, LOWERCASE value) { \
- Extension* extension = &extensions_[number]; \
- if (extension->descriptor == NULL) { \
- /* Not previoulsy present. Initialize it. */ \
- const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number); \
- GOOGLE_DCHECK_TYPE(descriptor, REPEATED, UPPERCASE); \
+void ExtensionSet::Add##CAMELCASE(int number, FieldType type, \
+ bool packed, LOWERCASE value) { \
+ Extension* extension; \
+ if (MaybeNewExtension(number, &extension)) { \
+ extension->type = type; \
+ GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_##UPPERCASE);\
+ extension->is_repeated = true; \
+ extension->is_packed = packed; \
extension->repeated_##LOWERCASE##_value = new RepeatedField<LOWERCASE>(); \
- extension->descriptor = descriptor; \
} else { \
- GOOGLE_DCHECK_TYPE(extension->descriptor, REPEATED, UPPERCASE); \
+ GOOGLE_DCHECK_TYPE(*extension, REPEATED, UPPERCASE); \
+ GOOGLE_DCHECK_EQ(extension->is_packed, packed); \
} \
extension->repeated_##LOWERCASE##_value->Add(value); \
}
@@ -220,121 +264,113 @@ PRIMITIVE_ACCESSORS( BOOL, bool, Bool)
// -------------------------------------------------------------------
// Enums
-int ExtensionSet::GetEnum(int number) const {
+int ExtensionSet::GetEnum(int number, int default_value) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
- if (iter == extensions_.end()) {
+ if (iter == extensions_.end() || iter->second.is_cleared) {
// Not present. Return the default value.
- const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
- GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, ENUM);
- return descriptor->default_value_enum()->number();
+ return default_value;
} else {
- GOOGLE_DCHECK_TYPE(iter->second.descriptor, OPTIONAL, ENUM);
+ GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, ENUM);
return iter->second.enum_value;
}
}
-void ExtensionSet::SetEnum(int number, int value) {
- Extension* extension = &extensions_[number];
- if (extension->descriptor == NULL) {
- // Not previoulsy present. Initialize it.
- const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
- GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, ENUM);
- extension->descriptor = descriptor;
- extension->enum_value = descriptor->default_value_enum()->number();
+void ExtensionSet::SetEnum(int number, FieldType type, int value) {
+ Extension* extension;
+ if (MaybeNewExtension(number, &extension)) {
+ extension->type = type;
+ GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_ENUM);
+ extension->is_repeated = false;
} else {
- GOOGLE_DCHECK_TYPE(extension->descriptor, OPTIONAL, ENUM);
- extension->is_cleared = false;
+ GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, ENUM);
}
- GOOGLE_DCHECK(extension->descriptor->enum_type()->FindValueByNumber(value) != NULL);
+ extension->is_cleared = false;
extension->enum_value = value;
}
int ExtensionSet::GetRepeatedEnum(int number, int index) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
- GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, ENUM);
+ GOOGLE_DCHECK_TYPE(iter->second, REPEATED, ENUM);
return iter->second.repeated_enum_value->Get(index);
}
void ExtensionSet::SetRepeatedEnum(int number, int index, int value) {
map<int, Extension>::iterator iter = extensions_.find(number);
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
- GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, ENUM);
- GOOGLE_DCHECK(iter->second.descriptor->enum_type()
- ->FindValueByNumber(value) != NULL);
+ GOOGLE_DCHECK_TYPE(iter->second, REPEATED, ENUM);
iter->second.repeated_enum_value->Set(index, value);
}
-void ExtensionSet::AddEnum(int number, int value) {
- Extension* extension = &extensions_[number];
- if (extension->descriptor == NULL) {
- // Not previoulsy present. Initialize it.
- const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
- GOOGLE_DCHECK_TYPE(descriptor, REPEATED, ENUM);
+void ExtensionSet::AddEnum(int number, FieldType type,
+ bool packed, int value) {
+ Extension* extension;
+ if (MaybeNewExtension(number, &extension)) {
+ extension->type = type;
+ GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_ENUM);
+ extension->is_repeated = true;
+ extension->is_packed = packed;
extension->repeated_enum_value = new RepeatedField<int>();
- extension->descriptor = descriptor;
} else {
- GOOGLE_DCHECK_TYPE(extension->descriptor, REPEATED, ENUM);
+ GOOGLE_DCHECK_TYPE(*extension, REPEATED, ENUM);
+ GOOGLE_DCHECK_EQ(extension->is_packed, packed);
}
- GOOGLE_DCHECK(extension->descriptor->enum_type()->FindValueByNumber(value) != NULL);
extension->repeated_enum_value->Add(value);
}
// -------------------------------------------------------------------
// Strings
-const string& ExtensionSet::GetString(int number) const {
+const string& ExtensionSet::GetString(int number,
+ const string& default_value) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
- if (iter == extensions_.end()) {
+ if (iter == extensions_.end() || iter->second.is_cleared) {
// Not present. Return the default value.
- const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
- GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, STRING);
- return descriptor->default_value_string();
+ return default_value;
} else {
- GOOGLE_DCHECK_TYPE(iter->second.descriptor, OPTIONAL, STRING);
+ GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, STRING);
return *iter->second.string_value;
}
}
-string* ExtensionSet::MutableString(int number) {
- Extension* extension = &extensions_[number];
- if (extension->descriptor == NULL) {
- // Not previoulsy present. Initialize it.
- const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
- GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, STRING);
- extension->descriptor = descriptor;
+string* ExtensionSet::MutableString(int number, FieldType type) {
+ Extension* extension;
+ if (MaybeNewExtension(number, &extension)) {
+ extension->type = type;
+ GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_STRING);
+ extension->is_repeated = false;
extension->string_value = new string;
} else {
- GOOGLE_DCHECK_TYPE(extension->descriptor, OPTIONAL, STRING);
- extension->is_cleared = false;
+ GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, STRING);
}
+ extension->is_cleared = false;
return extension->string_value;
}
const string& ExtensionSet::GetRepeatedString(int number, int index) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
- GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, STRING);
+ GOOGLE_DCHECK_TYPE(iter->second, REPEATED, STRING);
return iter->second.repeated_string_value->Get(index);
}
string* ExtensionSet::MutableRepeatedString(int number, int index) {
map<int, Extension>::iterator iter = extensions_.find(number);
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
- GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, STRING);
+ GOOGLE_DCHECK_TYPE(iter->second, REPEATED, STRING);
return iter->second.repeated_string_value->Mutable(index);
}
-string* ExtensionSet::AddString(int number) {
- Extension* extension = &extensions_[number];
- if (extension->descriptor == NULL) {
- // Not previoulsy present. Initialize it.
- const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
- GOOGLE_DCHECK_TYPE(descriptor, REPEATED, STRING);
+string* ExtensionSet::AddString(int number, FieldType type) {
+ Extension* extension;
+ if (MaybeNewExtension(number, &extension)) {
+ extension->type = type;
+ GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_STRING);
+ extension->is_repeated = true;
+ extension->is_packed = false;
extension->repeated_string_value = new RepeatedPtrField<string>();
- extension->descriptor = descriptor;
} else {
- GOOGLE_DCHECK_TYPE(extension->descriptor, REPEATED, STRING);
+ GOOGLE_DCHECK_TYPE(*extension, REPEATED, STRING);
}
return extension->repeated_string_value->Add();
}
@@ -342,59 +378,108 @@ string* ExtensionSet::AddString(int number) {
// -------------------------------------------------------------------
// Messages
-const Message& ExtensionSet::GetMessage(int number) const {
+const Message& ExtensionSet::GetMessage(int number,
+ const Message& default_value) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
if (iter == extensions_.end()) {
// Not present. Return the default value.
- const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
- GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, MESSAGE);
- return *GetPrototype(descriptor->message_type());
+ return default_value;
+ } else {
+ GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
+ return *iter->second.message_value;
+ }
+}
+
+const Message& ExtensionSet::GetMessage(int number,
+ const Descriptor* message_type,
+ MessageFactory* factory) const {
+ map<int, Extension>::const_iterator iter = extensions_.find(number);
+ if (iter == extensions_.end() || iter->second.is_cleared) {
+ // Not present. Return the default value.
+ return *factory->GetPrototype(message_type);
} else {
- GOOGLE_DCHECK_TYPE(iter->second.descriptor, OPTIONAL, MESSAGE);
+ GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
return *iter->second.message_value;
}
}
-Message* ExtensionSet::MutableMessage(int number) {
- Extension* extension = &extensions_[number];
- if (extension->descriptor == NULL) {
- // Not previoulsy present. Initialize it.
- const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
- GOOGLE_DCHECK_TYPE(descriptor, OPTIONAL, MESSAGE);
- extension->descriptor = descriptor;
- extension->message_value = GetPrototype(descriptor->message_type())->New();
+Message* ExtensionSet::MutableMessage(int number, FieldType type,
+ const Message& prototype) {
+ Extension* extension;
+ if (MaybeNewExtension(number, &extension)) {
+ extension->type = type;
+ GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
+ extension->is_repeated = false;
+ extension->message_value = prototype.New();
} else {
- GOOGLE_DCHECK_TYPE(extension->descriptor, OPTIONAL, MESSAGE);
- extension->is_cleared = false;
+ GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
}
+ extension->is_cleared = false;
+ return extension->message_value;
+}
+
+Message* ExtensionSet::MutableMessage(int number, FieldType type,
+ const Descriptor* message_type,
+ MessageFactory* factory) {
+ Extension* extension;
+ if (MaybeNewExtension(number, &extension)) {
+ extension->type = type;
+ GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
+ extension->is_repeated = false;
+ extension->is_packed = false;
+ const Message* prototype = factory->GetPrototype(message_type);
+ GOOGLE_CHECK(prototype != NULL);
+ extension->message_value = prototype->New();
+ } else {
+ GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
+ }
+ extension->is_cleared = false;
return extension->message_value;
}
const Message& ExtensionSet::GetRepeatedMessage(int number, int index) const {
map<int, Extension>::const_iterator iter = extensions_.find(number);
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
- GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, MESSAGE);
+ GOOGLE_DCHECK_TYPE(iter->second, REPEATED, MESSAGE);
return iter->second.repeated_message_value->Get(index);
}
Message* ExtensionSet::MutableRepeatedMessage(int number, int index) {
map<int, Extension>::iterator iter = extensions_.find(number);
GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty).";
- GOOGLE_DCHECK_TYPE(iter->second.descriptor, REPEATED, MESSAGE);
+ GOOGLE_DCHECK_TYPE(iter->second, REPEATED, MESSAGE);
return iter->second.repeated_message_value->Mutable(index);
}
-Message* ExtensionSet::AddMessage(int number) {
- Extension* extension = &extensions_[number];
- if (extension->descriptor == NULL) {
- // Not previoulsy present. Initialize it.
- const FieldDescriptor* descriptor = FindKnownExtensionOrDie(number);
- GOOGLE_DCHECK_TYPE(descriptor, REPEATED, MESSAGE);
+Message* ExtensionSet::AddMessage(int number, FieldType type,
+ const Message& prototype) {
+ Extension* extension;
+ if (MaybeNewExtension(number, &extension)) {
+ extension->type = type;
+ GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
+ extension->is_repeated = true;
+ extension->repeated_message_value =
+ new RepeatedPtrField<Message>(&prototype);
+ } else {
+ GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
+ }
+ return extension->repeated_message_value->Add();
+}
+
+Message* ExtensionSet::AddMessage(int number, FieldType type,
+ const Descriptor* message_type,
+ MessageFactory* factory) {
+ Extension* extension;
+ if (MaybeNewExtension(number, &extension)) {
+ extension->type = type;
+ GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
+ extension->is_repeated = true;
+ const Message* prototype = factory->GetPrototype(message_type);
+ GOOGLE_CHECK(prototype != NULL);
extension->repeated_message_value =
- new RepeatedPtrField<Message>(GetPrototype(descriptor->message_type()));
- extension->descriptor = descriptor;
+ new RepeatedPtrField<Message>(prototype);
} else {
- GOOGLE_DCHECK_TYPE(extension->descriptor, REPEATED, MESSAGE);
+ GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
}
return extension->repeated_message_value->Add();
}
@@ -410,59 +495,32 @@ void ExtensionSet::Clear() {
}
}
-namespace {
-
-// A helper function for merging RepeatedFields...
-// TODO(kenton): Implement this as a method of RepeatedField? Make generated
-// MergeFrom methods use it?
-
-template <typename Type>
-void MergeRepeatedFields(const RepeatedField<Type>& source,
- RepeatedField<Type>* destination) {
- destination->Reserve(destination->size() + source.size());
- for (int i = 0; i < source.size(); i++) {
- destination->Add(source.Get(i));
- }
-}
-
-void MergeRepeatedFields(const RepeatedPtrField<string>& source,
- RepeatedPtrField<string>* destination) {
- destination->Reserve(destination->size() + source.size());
- for (int i = 0; i < source.size(); i++) {
- destination->Add()->assign(source.Get(i));
- }
-}
-
-void MergeRepeatedFields(const RepeatedPtrField<Message>& source,
- RepeatedPtrField<Message>* destination) {
- destination->Reserve(destination->size() + source.size());
- for (int i = 0; i < source.size(); i++) {
- destination->Add()->MergeFrom(source.Get(i));
- }
-}
-
-} // namespace
-
void ExtensionSet::MergeFrom(const ExtensionSet& other) {
- GOOGLE_DCHECK_EQ(*extendee_, *other.extendee_);
-
for (map<int, Extension>::const_iterator iter = other.extensions_.begin();
iter != other.extensions_.end(); ++iter) {
- const FieldDescriptor* field = iter->second.descriptor;
- if (field->is_repeated()) {
- const Extension& other_extension = iter->second;
- Extension* extension = &extensions_[iter->first];
- switch (field->cpp_type()) {
+ const Extension& other_extension = iter->second;
+
+ if (other_extension.is_repeated) {
+ Extension* extension;
+ bool is_new = MaybeNewExtension(iter->first, &extension);
+ if (is_new) {
+ // Extension did not already exist in set.
+ extension->type = other_extension.type;
+ extension->is_repeated = true;
+ } else {
+ GOOGLE_DCHECK_EQ(extension->type, other_extension.type);
+ GOOGLE_DCHECK(extension->is_repeated);
+ }
+
+ switch (cpp_type(other_extension.type)) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE: \
- if (extension->descriptor == NULL) { \
- extension->descriptor = field; \
+ if (is_new) { \
extension->repeated_##LOWERCASE##_value = \
new REPEATED_TYPE; \
} \
- MergeRepeatedFields( \
- *other_extension.repeated_##LOWERCASE##_value, \
- extension->repeated_##LOWERCASE##_value); \
+ extension->repeated_##LOWERCASE##_value->MergeFrom( \
+ *other_extension.repeated_##LOWERCASE##_value); \
break;
HANDLE_TYPE( INT32, int32, RepeatedField < int32>);
@@ -477,22 +535,21 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) {
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_MESSAGE:
- if (extension->descriptor == NULL) {
- extension->descriptor = field;
+ if (is_new) {
extension->repeated_message_value = new RepeatedPtrField<Message>(
other_extension.repeated_message_value->prototype());
}
- MergeRepeatedFields(
- *other_extension.repeated_message_value,
- extension->repeated_message_value);
+ extension->repeated_message_value->MergeFrom(
+ *other_extension.repeated_message_value);
break;
}
} else {
- if (!iter->second.is_cleared) {
- switch (field->cpp_type()) {
-#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \
- case FieldDescriptor::CPPTYPE_##UPPERCASE: \
- Set##CAMELCASE(iter->first, iter->second.LOWERCASE##_value); \
+ if (!other_extension.is_cleared) {
+ switch (cpp_type(other_extension.type)) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \
+ case FieldDescriptor::CPPTYPE_##UPPERCASE: \
+ Set##CAMELCASE(iter->first, other_extension.type, \
+ other_extension.LOWERCASE##_value); \
break;
HANDLE_TYPE( INT32, int32, Int32);
@@ -505,10 +562,13 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) {
HANDLE_TYPE( ENUM, enum, Enum);
#undef HANDLE_TYPE
case FieldDescriptor::CPPTYPE_STRING:
- SetString(iter->first, *iter->second.string_value);
+ SetString(iter->first, other_extension.type,
+ *other_extension.string_value);
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
- MutableMessage(iter->first)->MergeFrom(*iter->second.message_value);
+ MutableMessage(iter->first, other_extension.type,
+ *other_extension.message_value)
+ ->MergeFrom(*other_extension.message_value);
break;
}
}
@@ -518,19 +578,16 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) {
void ExtensionSet::Swap(ExtensionSet* x) {
extensions_.swap(x->extensions_);
- std::swap(extendee_, x->extendee_);
- std::swap(descriptor_pool_, x->descriptor_pool_);
- std::swap(message_factory_, x->message_factory_);
}
bool ExtensionSet::IsInitialized() const {
- // Extensions are never requried. However, we need to check that all
+ // Extensions are never required. However, we need to check that all
// embedded messages are initialized.
for (map<int, Extension>::const_iterator iter = extensions_.begin();
iter != extensions_.end(); ++iter) {
const Extension& extension = iter->second;
- if (extension.descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- if (extension.descriptor->is_repeated()) {
+ if (cpp_type(extension.type) == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (extension.is_repeated) {
for (int i = 0; i < extension.repeated_message_value->size(); i++) {
if (!extension.repeated_message_value->Get(i).IsInitialized()) {
return false;
@@ -548,36 +605,201 @@ bool ExtensionSet::IsInitialized() const {
}
bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
- Message* message) {
- const FieldDescriptor* field =
- message->GetReflection()
- ->FindKnownExtensionByNumber(WireFormat::GetTagFieldNumber(tag));
+ const Message* containing_type,
+ UnknownFieldSet* unknown_fields) {
+ int number = WireFormat::GetTagFieldNumber(tag);
+ WireFormat::WireType wire_type = WireFormat::GetTagWireType(tag);
+
+ const ExtensionInfo* extension =
+ FindRegisteredExtension(containing_type, number);
+
+ bool is_unknown;
+ if (extension == NULL) {
+ is_unknown = true;
+ } else if (extension->is_packed) {
+ is_unknown = (wire_type != WireFormat::WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ WireFormat::WireType expected_wire_type =
+ WireFormat::WireTypeForFieldType(real_type(extension->type));
+ is_unknown = (wire_type != expected_wire_type);
+ }
+
+ if (is_unknown) {
+ WireFormat::SkipField(input, tag, unknown_fields);
+ } 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) \
+ case FieldDescriptor::TYPE_##UPPERCASE: \
+ while (input->BytesUntilLimit() > 0) { \
+ CPP_LOWERCASE value; \
+ if (!WireFormat::Read##CAMELCASE(input, &value)) return false; \
+ Add##CPP_CAMELCASE(number, FieldDescriptor::TYPE_##UPPERCASE, \
+ true, value); \
+ } \
+ 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);
+#undef HANDLE_TYPE
+
+ case FieldDescriptor::TYPE_ENUM:
+ while (input->BytesUntilLimit() > 0) {
+ int value;
+ if (!WireFormat::ReadEnum(input, &value)) return false;
+ if (extension->enum_is_valid(value)) {
+ AddEnum(number, FieldDescriptor::TYPE_ENUM, true, value);
+ }
+ }
+ break;
+
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_BYTES:
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
+ break;
+ }
+
+ input->PopLimit(limit);
+ } else {
+ switch (extension->type) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, CPP_CAMELCASE, CPP_LOWERCASE) \
+ case FieldDescriptor::TYPE_##UPPERCASE: { \
+ CPP_LOWERCASE value; \
+ if (!WireFormat::Read##CAMELCASE(input, &value)) return false; \
+ if (extension->is_repeated) { \
+ Add##CPP_CAMELCASE(number, FieldDescriptor::TYPE_##UPPERCASE, \
+ false, value); \
+ } else { \
+ Set##CPP_CAMELCASE(number, FieldDescriptor::TYPE_##UPPERCASE, value);\
+ } \
+ } 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);
+#undef HANDLE_TYPE
+
+ case FieldDescriptor::TYPE_ENUM: {
+ int value;
+ if (!WireFormat::ReadEnum(input, &value)) return false;
+
+ if (!extension->enum_is_valid(value)) {
+ // Invalid value. Treat as unknown.
+ if (unknown_fields != NULL) {
+ unknown_fields->AddVarint(number, value);
+ }
+ } else if (extension->is_repeated) {
+ AddEnum(number, FieldDescriptor::TYPE_ENUM, false, value);
+ } else {
+ SetEnum(number, FieldDescriptor::TYPE_ENUM, value);
+ }
+ break;
+ }
+
+ case FieldDescriptor::TYPE_STRING: {
+ string* value = extension->is_repeated ?
+ AddString(number, FieldDescriptor::TYPE_STRING) :
+ MutableString(number, FieldDescriptor::TYPE_STRING);
+ if (!WireFormat::ReadString(input, value)) return false;
+ break;
+ }
- return WireFormat::ParseAndMergeField(tag, field, message, input);
+ case FieldDescriptor::TYPE_BYTES: {
+ string* value = extension->is_repeated ?
+ AddString(number, FieldDescriptor::TYPE_STRING) :
+ MutableString(number, FieldDescriptor::TYPE_STRING);
+ if (!WireFormat::ReadBytes(input, value)) return false;
+ break;
+ }
+
+ case FieldDescriptor::TYPE_GROUP: {
+ Message* value = extension->is_repeated ?
+ AddMessage(number, FieldDescriptor::TYPE_GROUP,
+ *extension->message_prototype) :
+ MutableMessage(number, FieldDescriptor::TYPE_GROUP,
+ *extension->message_prototype);
+ if (!WireFormat::ReadGroup(number, input, value)) return false;
+ break;
+ }
+
+ case FieldDescriptor::TYPE_MESSAGE: {
+ Message* value = extension->is_repeated ?
+ AddMessage(number, FieldDescriptor::TYPE_MESSAGE,
+ *extension->message_prototype) :
+ MutableMessage(number, FieldDescriptor::TYPE_MESSAGE,
+ *extension->message_prototype);
+ if (!WireFormat::ReadMessage(input, value)) return false;
+ break;
+ }
+ }
+ }
+
+ return true;
}
-bool ExtensionSet::SerializeWithCachedSizes(
+void ExtensionSet::SerializeWithCachedSizes(
int start_field_number, int end_field_number,
- const Message& message,
io::CodedOutputStream* output) const {
map<int, Extension>::const_iterator iter;
for (iter = extensions_.lower_bound(start_field_number);
iter != extensions_.end() && iter->first < end_field_number;
++iter) {
- if (!iter->second.SerializeFieldWithCachedSizes(message, output)) {
- return false;
- }
+ iter->second.SerializeFieldWithCachedSizes(iter->first, output);
}
+}
- return true;
+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;
}
-int ExtensionSet::ByteSize(const Message& message) const {
+int ExtensionSet::ByteSize() const {
int total_size = 0;
for (map<int, Extension>::const_iterator iter = extensions_.begin();
iter != extensions_.end(); ++iter) {
- total_size += iter->second.ByteSize(message);
+ total_size += iter->second.ByteSize(iter->first);
}
return total_size;
@@ -595,12 +817,19 @@ int ExtensionSet::SpaceUsedExcludingSelf() const {
return total_size;
}
+bool ExtensionSet::MaybeNewExtension(int number, Extension** result) {
+ pair<map<int, Extension>::iterator, bool> insert_result =
+ extensions_.insert(make_pair(number, Extension()));
+ *result = &insert_result.first->second;
+ return insert_result.second;
+}
+
// ===================================================================
// Methods of ExtensionSet::Extension
void ExtensionSet::Extension::Clear() {
- if (descriptor->is_repeated()) {
- switch (descriptor->cpp_type()) {
+ if (is_repeated) {
+ switch (cpp_type(type)) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE: \
repeated_##LOWERCASE##_value->Clear(); \
@@ -620,33 +849,18 @@ void ExtensionSet::Extension::Clear() {
}
} else {
if (!is_cleared) {
- switch (descriptor->cpp_type()) {
-#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
- case FieldDescriptor::CPPTYPE_##UPPERCASE: \
- LOWERCASE##_value = descriptor->default_value_##LOWERCASE(); \
- break
-
- HANDLE_TYPE( INT32, int32);
- HANDLE_TYPE( INT64, int64);
- HANDLE_TYPE(UINT32, uint32);
- HANDLE_TYPE(UINT64, uint64);
- HANDLE_TYPE( FLOAT, float);
- HANDLE_TYPE(DOUBLE, double);
- HANDLE_TYPE( BOOL, bool);
-#undef HANDLE_TYPE
- case FieldDescriptor::CPPTYPE_ENUM:
- enum_value = descriptor->default_value_enum()->number();
- break;
+ switch (cpp_type(type)) {
case FieldDescriptor::CPPTYPE_STRING:
- if (descriptor->has_default_value()) {
- string_value->assign(descriptor->default_value_string());
- } else {
- string_value->clear();
- }
+ string_value->clear();
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
message_value->Clear();
break;
+ default:
+ // No need to do anything. Get*() will return the default value
+ // as long as is_cleared is true and Set*() will overwrite the
+ // previous value.
+ break;
}
is_cleared = true;
@@ -654,29 +868,247 @@ void ExtensionSet::Extension::Clear() {
}
}
-bool ExtensionSet::Extension::SerializeFieldWithCachedSizes(
- const Message& message,
+void ExtensionSet::Extension::SerializeFieldWithCachedSizes(
+ int number,
io::CodedOutputStream* output) const {
- if (descriptor->is_repeated() || !is_cleared) {
- return WireFormat::SerializeFieldWithCachedSizes(
- descriptor, message, output);
- } else {
- return true;
+ if (is_repeated) {
+ if (is_packed) {
+ if (cached_size == 0) return;
+
+ WireFormat::WriteTag(number, WireFormat::WIRETYPE_LENGTH_DELIMITED,
+ output);
+ output->WriteVarint32(cached_size);
+
+ switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
+ case FieldDescriptor::TYPE_##UPPERCASE: \
+ for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
+ WireFormat::Write##CAMELCASE##NoTag( \
+ repeated_##LOWERCASE##_value->Get(i), output); \
+ } \
+ 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 FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_BYTES:
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::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++) { \
+ WireFormat::Write##CAMELCASE(number, \
+ repeated_##LOWERCASE##_value->Get(i), output); \
+ } \
+ 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: \
+ WireFormat::Write##CAMELCASE(number, VALUE, output); \
+ 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
+ }
}
}
-int64 ExtensionSet::Extension::ByteSize(const Message& message) const {
- if (descriptor->is_repeated() || !is_cleared) {
- return WireFormat::FieldByteSize(descriptor, message);
- } else {
- // Cleared, non-repeated field.
- return 0;
+int ExtensionSet::Extension::ByteSize(int number) const {
+ int result = 0;
+
+ if (is_repeated) {
+ if (is_packed) {
+ switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
+ case FieldDescriptor::TYPE_##UPPERCASE: \
+ for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
+ result += WireFormat::CAMELCASE##Size( \
+ repeated_##LOWERCASE##_value->Get(i)); \
+ } \
+ 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( ENUM, Enum, enum);
+#undef HANDLE_TYPE
+
+ // Stuff with fixed size.
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
+ case FieldDescriptor::TYPE_##UPPERCASE: \
+ result += WireFormat::k##CAMELCASE##Size * \
+ repeated_##LOWERCASE##_value->size(); \
+ break
+ 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);
+#undef HANDLE_TYPE
+
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_BYTES:
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed.";
+ break;
+ }
+
+ cached_size = result;
+ if (result > 0) {
+ result += io::CodedOutputStream::VarintSize32(result);
+ result += io::CodedOutputStream::VarintSize32(
+ WireFormat::MakeTag(number, WireFormat::WIRETYPE_LENGTH_DELIMITED));
+ }
+ } else {
+ int tag_size = WireFormat::TagSize(number, real_type(type));
+
+ switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
+ case FieldDescriptor::TYPE_##UPPERCASE: \
+ result += tag_size * repeated_##LOWERCASE##_value->size(); \
+ for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \
+ result += WireFormat::CAMELCASE##Size( \
+ repeated_##LOWERCASE##_value->Get(i)); \
+ } \
+ 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( 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
+
+ // Stuff with fixed size.
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
+ case FieldDescriptor::TYPE_##UPPERCASE: \
+ result += (tag_size + WireFormat::k##CAMELCASE##Size) * \
+ repeated_##LOWERCASE##_value->size(); \
+ break
+ 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);
+#undef HANDLE_TYPE
+ }
+ }
+ } else if (!is_cleared) {
+ result += WireFormat::TagSize(number, real_type(type));
+ switch (real_type(type)) {
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \
+ case FieldDescriptor::TYPE_##UPPERCASE: \
+ result += WireFormat::CAMELCASE##Size(LOWERCASE); \
+ 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( 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
+
+ // Stuff with fixed size.
+#define HANDLE_TYPE(UPPERCASE, CAMELCASE) \
+ case FieldDescriptor::TYPE_##UPPERCASE: \
+ result += WireFormat::k##CAMELCASE##Size; \
+ break
+ HANDLE_TYPE( FIXED32, Fixed32);
+ HANDLE_TYPE( FIXED64, Fixed64);
+ HANDLE_TYPE(SFIXED32, SFixed32);
+ HANDLE_TYPE(SFIXED64, SFixed64);
+ HANDLE_TYPE( FLOAT, Float);
+ HANDLE_TYPE( DOUBLE, Double);
+ HANDLE_TYPE( BOOL, Bool);
+#undef HANDLE_TYPE
+ }
}
+
+ return result;
}
int ExtensionSet::Extension::GetSize() const {
- GOOGLE_DCHECK(descriptor->is_repeated());
- switch (descriptor->cpp_type()) {
+ GOOGLE_DCHECK(is_repeated);
+ switch (cpp_type(type)) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE: \
return repeated_##LOWERCASE##_value->size()
@@ -699,8 +1131,8 @@ int ExtensionSet::Extension::GetSize() const {
}
void ExtensionSet::Extension::Free() {
- if (descriptor->is_repeated()) {
- switch (descriptor->cpp_type()) {
+ if (is_repeated) {
+ switch (cpp_type(type)) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE: \
delete repeated_##LOWERCASE##_value; \
@@ -719,7 +1151,7 @@ void ExtensionSet::Extension::Free() {
#undef HANDLE_TYPE
}
} else {
- switch (descriptor->cpp_type()) {
+ switch (cpp_type(type)) {
case FieldDescriptor::CPPTYPE_STRING:
delete string_value;
break;
@@ -734,8 +1166,8 @@ void ExtensionSet::Extension::Free() {
int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
int total_size = 0;
- if (descriptor->is_repeated()) {
- switch (descriptor->cpp_type()) {
+ if (is_repeated) {
+ switch (cpp_type(type)) {
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
case FieldDescriptor::CPPTYPE_##UPPERCASE: \
total_size += sizeof(*repeated_##LOWERCASE##_value) + \
@@ -754,7 +1186,7 @@ int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
HANDLE_TYPE(MESSAGE, message);
}
} else {
- switch (descriptor->cpp_type()) {
+ switch (cpp_type(type)) {
case FieldDescriptor::CPPTYPE_STRING:
total_size += sizeof(*string_value) +
StringSpaceUsedExcludingSelf(*string_value);
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index 9ad241f2..8e64b9bd 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -44,6 +44,7 @@
#include <utility>
#include <string>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message.h>
namespace google {
@@ -53,6 +54,7 @@ namespace protobuf {
class DescriptorPool; // descriptor.h
class Message; // message.h
class MessageFactory; // message.h
+ class UnknownFieldSet; // unknown_field_set.h
namespace io {
class CodedInputStream; // coded_stream.h
class CodedOutputStream; // coded_stream.h
@@ -64,6 +66,12 @@ namespace protobuf {
namespace protobuf {
namespace internal {
+// Used to store values of type FieldDescriptor::Type without having to
+// #include descriptor.h. Also, ensures that we use only one byte to store
+// these values, which is important to keep the layout of
+// ExtensionSet::Extension small.
+typedef uint8 FieldType;
+
// 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
@@ -77,30 +85,42 @@ namespace internal {
// off to the ExtensionSet for parsing. Etc.
class LIBPROTOBUF_EXPORT ExtensionSet {
public:
- // Construct an ExtensionSet.
- // extendee: Descriptor for the type being extended. We pass in a pointer
- // to a pointer to the extendee to get around an initialization
- // problem: when we create the ExtensionSet for a message type,
- // its descriptor may not exist yet. But we know where that
- // descriptor pointer will be placed, and by the time it's used
- // by this ExtensionSet it will be fully initialized, so passing
- // a pointer to that location works. Note that this problem
- // will only occur for messages defined in descriptor.proto.
- // pool: DescriptorPool to search for extension definitions.
- // factory: MessageFactory used to construct implementations of messages
- // for extensions with message type. This factory must be able
- // to construct any message type found in "pool".
- // All three objects remain property of the caller and must outlive the
- // ExtensionSet.
- ExtensionSet(const Descriptor* const* extendee,
- const DescriptorPool* pool,
- MessageFactory* factory);
-
+ 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
+ // does not use ParseField(); only protocol-compiler-generated parsing
+ // methods do.
+ static void RegisterExtension(const Message* containing_type,
+ int number, FieldType type,
+ bool is_repeated, bool is_packed);
+ static void RegisterEnumExtension(const Message* containing_type,
+ int number, FieldType type,
+ bool is_repeated, bool is_packed,
+ EnumValidityFunc* is_valid);
+ static void RegisterMessageExtension(const Message* containing_type,
+ int number, FieldType type,
+ bool is_repeated, bool is_packed,
+ const Message* prototype);
+
+ // =================================================================
+
// Add all fields which are currently present to the given vector. This
- // is useful to implement Reflection::ListFields().
- void AppendToList(vector<const FieldDescriptor*>* output) const;
+ // 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?
+ void AppendToList(const Descriptor* containing_type,
+ const DescriptorPool* pool,
+ vector<const FieldDescriptor*>* output) const;
// =================================================================
// Accessors
@@ -138,28 +158,34 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// singular fields -------------------------------------------------
- int32 GetInt32 (int number) const;
- int64 GetInt64 (int number) const;
- uint32 GetUInt32(int number) const;
- uint64 GetUInt64(int number) const;
- float GetFloat (int number) const;
- double GetDouble(int number) const;
- bool GetBool (int number) const;
- int GetEnum (int number) const;
- const string & GetString (int number) const;
- const Message& GetMessage(int number) const;
-
- void SetInt32 (int number, int32 value);
- void SetInt64 (int number, int64 value);
- void SetUInt32(int number, uint32 value);
- void SetUInt64(int number, uint64 value);
- void SetFloat (int number, float value);
- void SetDouble(int number, double value);
- void SetBool (int number, bool value);
- void SetEnum (int number, int value);
- void SetString(int number, const string& value);
- string * MutableString (int number);
- Message* MutableMessage(int number);
+ int32 GetInt32 (int number, int32 default_value) const;
+ int64 GetInt64 (int number, int64 default_value) const;
+ uint32 GetUInt32(int number, uint32 default_value) const;
+ uint64 GetUInt64(int number, uint64 default_value) const;
+ float GetFloat (int number, float default_value) const;
+ double GetDouble(int number, double default_value) const;
+ bool GetBool (int number, bool default_value) const;
+ int GetEnum (int number, int default_value) const;
+ const string & GetString (int number, const string& default_value) const;
+ const Message& GetMessage(int number, const Message& default_value) const;
+ const Message& GetMessage(int number, const Descriptor* message_type,
+ MessageFactory* factory) const;
+
+ 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);
+ Message* MutableMessage(int number, FieldType type,
+ const Message& prototype);
+ Message* MutableMessage(int number, FieldType type,
+ const Descriptor* message_type,
+ MessageFactory* factory);
// repeated fields -------------------------------------------------
@@ -186,17 +212,21 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
string * MutableRepeatedString (int number, int index);
Message* MutableRepeatedMessage(int number, int index);
- void AddInt32 (int number, int32 value);
- void AddInt64 (int number, int64 value);
- void AddUInt32(int number, uint32 value);
- void AddUInt64(int number, uint64 value);
- void AddFloat (int number, float value);
- void AddDouble(int number, double value);
- void AddBool (int number, bool value);
- void AddEnum (int number, int value);
- void AddString(int number, const string& value);
- string * AddString (int number);
- Message* AddMessage(int number);
+ 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);
+ Message* AddMessage(int number, FieldType type,
+ const Message& prototype);
+ Message* AddMessage(int number, FieldType type,
+ const Descriptor* message_type,
+ MessageFactory* factory);
// -----------------------------------------------------------------
// TODO(kenton): Hardcore memory management accessors
@@ -212,40 +242,41 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
void Swap(ExtensionSet* other);
bool IsInitialized() const;
- // These parsing and serialization functions all want a pointer to the
- // message object because they hand off the actual work to WireFormat,
- // which works in terms of a reflection interface. Yes, this means there
- // are some redundant virtual function calls that end up being made, but
- // it probably doesn't matter much in practice, and the alternative would
- // involve reproducing a lot of WireFormat's functionality.
-
// Parses a single extension from the input. The input should start out
- // positioned immediately after the tag.
- bool ParseField(uint32 tag, io::CodedInputStream* input, Message* message);
+ // positioned immediately after the tag. |containing_type| is the default
+ // instance for the containing message; it is used only to look up the
+ // extension by number. See RegisterExtension(), above. Unlike the other
+ // methods of ExtensionSet, this only works for generated message types --
+ // it looks up extensions registered using RegisterExtension().
+ bool ParseField(uint32 tag, io::CodedInputStream* input,
+ const Message* containing_type,
+ UnknownFieldSet* unknown_fields);
// Write all extension fields with field numbers in the range
// [start_field_number, end_field_number)
// to the output stream, using the cached sizes computed when ByteSize() was
// last called. Note that the range bounds are inclusive-exclusive.
- bool SerializeWithCachedSizes(int start_field_number,
+ void SerializeWithCachedSizes(int start_field_number,
int end_field_number,
- const Message& message,
io::CodedOutputStream* output) const;
+ // Same as SerializeWithCachedSizes, but without any bounds checking.
+ // The caller must ensure that target has sufficient capacity for the
+ // serialized extensions.
+ //
+ // Returns a pointer past the last written byte.
+ uint8* SerializeWithCachedSizesToArray(int start_field_number,
+ int end_field_number,
+ uint8* target) const;
+
// Returns the total serialized size of all the extensions.
- int ByteSize(const Message& message) const;
+ int ByteSize() const;
// Returns (an estimate of) the total number of bytes used for storing the
// extensions in memory, excluding sizeof(*this).
int SpaceUsedExcludingSelf() const;
private:
- // Like FindKnownExtension(), but GOOGLE_CHECK-fail if not found.
- const FieldDescriptor* FindKnownExtensionOrDie(int number) const;
-
- // Get the prototype for the message.
- const Message* GetPrototype(const Descriptor* message_type) const;
-
struct Extension {
union {
int32 int32_value;
@@ -271,7 +302,8 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
RepeatedPtrField<Message>* repeated_message_value;
};
- const FieldDescriptor* descriptor;
+ FieldType type;
+ bool is_repeated;
// For singular types, indicates if the extension is "cleared". This
// happens when an extension is set and then later cleared by the caller.
@@ -281,19 +313,29 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// simply becomes zero when cleared.
bool is_cleared;
- Extension(): descriptor(NULL), is_cleared(false) {}
+ // For repeated types, this indicates if the [packed=true] option is set.
+ bool is_packed;
+
+ // 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.
+ mutable int cached_size;
// Some helper methods for operations on a single Extension.
- bool SerializeFieldWithCachedSizes(
- const Message& message,
+ void SerializeFieldWithCachedSizes(
+ int number,
io::CodedOutputStream* output) const;
- int64 ByteSize(const Message& message) const;
+ int ByteSize(int number) const;
void Clear();
int GetSize() const;
void Free();
int SpaceUsedExcludingSelf() const;
};
+ // 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);
+
// The Extension struct is small enough to be passed by value, so we use it
// directly as the value type in the map rather than use pointers. We use
// a map rather than hash_map here because we expect most ExtensionSets will
@@ -301,30 +343,26 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// for 100 elements or more. Also, we want AppendToList() to order fields
// by field number.
map<int, Extension> extensions_;
- const Descriptor* const* extendee_;
- const DescriptorPool* descriptor_pool_;
- MessageFactory* message_factory_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet);
};
// These are just for convenience...
-inline void ExtensionSet::SetString(int number, const string& value) {
- MutableString(number)->assign(value);
+inline void ExtensionSet::SetString(int number, FieldType type,
+ const string& value) {
+ MutableString(number, type)->assign(value);
}
inline void ExtensionSet::SetRepeatedString(int number, int index,
const string& value) {
MutableRepeatedString(number, index)->assign(value);
}
-inline void ExtensionSet::AddString(int number, const string& value) {
- AddString(number)->assign(value);
+inline void ExtensionSet::AddString(int number, FieldType type,
+ const string& value) {
+ AddString(number, type)->assign(value);
}
// ===================================================================
-// Implementation details
-//
-// DO NOT DEPEND ON ANYTHING BELOW THIS POINT. This is for use from
-// generated code only.
+// Glue for generated extension accessors
// -------------------------------------------------------------------
// Template magic
@@ -377,8 +415,10 @@ class PrimitiveTypeTraits {
public:
typedef Type ConstType;
- static inline ConstType Get(int number, const ExtensionSet& set);
- static inline void Set(int number, ConstType value, ExtensionSet* set);
+ static inline ConstType Get(int number, const ExtensionSet& set,
+ ConstType default_value);
+ static inline void Set(int number, FieldType field_type,
+ ConstType value, ExtensionSet* set);
};
template <typename Type>
@@ -388,17 +428,18 @@ class RepeatedPrimitiveTypeTraits {
static inline Type Get(int number, const ExtensionSet& set, int index);
static inline void Set(int number, int index, Type value, ExtensionSet* set);
- static inline void Add(int number, Type value, ExtensionSet* set);
+ static inline void Add(int number, FieldType field_type,
+ bool is_packed, Type value, ExtensionSet* set);
};
#define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD) \
template<> inline TYPE PrimitiveTypeTraits<TYPE>::Get( \
- int number, const ExtensionSet& set) { \
- return set.Get##METHOD(number); \
+ int number, const ExtensionSet& set, TYPE default_value) { \
+ return set.Get##METHOD(number, default_value); \
} \
template<> inline void PrimitiveTypeTraits<TYPE>::Set( \
- int number, ConstType value, ExtensionSet* set) { \
- set->Set##METHOD(number, value); \
+ int number, FieldType field_type, TYPE value, ExtensionSet* set) { \
+ set->Set##METHOD(number, field_type, value); \
} \
\
template<> inline TYPE RepeatedPrimitiveTypeTraits<TYPE>::Get( \
@@ -406,12 +447,13 @@ template<> inline TYPE RepeatedPrimitiveTypeTraits<TYPE>::Get( \
return set.GetRepeated##METHOD(number, index); \
} \
template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Set( \
- int number, int index, ConstType value, ExtensionSet* set) { \
+ int number, int index, TYPE value, ExtensionSet* set) { \
set->SetRepeated##METHOD(number, index, value); \
} \
template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::Add( \
- int number, ConstType value, ExtensionSet* set) { \
- set->Add##METHOD(number, value); \
+ int number, FieldType field_type, bool is_packed, \
+ TYPE value, ExtensionSet* set) { \
+ set->Add##METHOD(number, field_type, is_packed, value); \
}
PROTOBUF_DEFINE_PRIMITIVE_TYPE( int32, Int32)
@@ -433,14 +475,17 @@ class LIBPROTOBUF_EXPORT StringTypeTraits {
typedef const string& ConstType;
typedef string* MutableType;
- static inline const string& Get(int number, const ExtensionSet& set) {
- return set.GetString(number);
+ static inline const string& Get(int number, const ExtensionSet& set,
+ ConstType default_value) {
+ return set.GetString(number, default_value);
}
- static inline void Set(int number, const string& value, ExtensionSet* set) {
- set->SetString(number, value);
+ static inline void Set(int number, FieldType field_type,
+ const string& value, ExtensionSet* set) {
+ set->SetString(number, field_type, value);
}
- static inline string* Mutable(int number, ExtensionSet* set) {
- return set->MutableString(number);
+ static inline string* Mutable(int number, FieldType field_type,
+ ExtensionSet* set) {
+ return set->MutableString(number, field_type);
}
};
@@ -460,11 +505,14 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
static inline string* Mutable(int number, int index, ExtensionSet* set) {
return set->MutableRepeatedString(number, index);
}
- static inline void Add(int number, const string& value, ExtensionSet* set) {
- set->AddString(number, value);
+ static inline void Add(int number, FieldType field_type,
+ bool is_packed, const string& value,
+ ExtensionSet* set) {
+ set->AddString(number, field_type, value);
}
- static inline string* Add(int number, ExtensionSet* set) {
- return set->AddString(number);
+ static inline string* Add(int number, FieldType field_type,
+ ExtensionSet* set) {
+ return set->AddString(number, field_type);
}
};
@@ -473,20 +521,23 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
// ExtensionSet represents enums using integers internally, so we have to
// static_cast around.
-template <typename Type>
+template <typename Type, bool IsValid(int)>
class EnumTypeTraits {
public:
typedef Type ConstType;
- static inline ConstType Get(int number, const ExtensionSet& set) {
- return static_cast<Type>(set.GetEnum(number));
+ static inline ConstType Get(int number, const ExtensionSet& set,
+ ConstType default_value) {
+ return static_cast<Type>(set.GetEnum(number, default_value));
}
- static inline void Set(int number, ConstType value, ExtensionSet* set) {
- set->SetEnum(number, value);
+ static inline void Set(int number, FieldType field_type,
+ ConstType value, ExtensionSet* set) {
+ GOOGLE_DCHECK(IsValid(value));
+ set->SetEnum(number, field_type, value);
}
};
-template <typename Type>
+template <typename Type, bool IsValid(int)>
class RepeatedEnumTypeTraits {
public:
typedef Type ConstType;
@@ -496,10 +547,13 @@ class RepeatedEnumTypeTraits {
}
static inline void Set(int number, int index,
ConstType value, ExtensionSet* set) {
+ GOOGLE_DCHECK(IsValid(value));
set->SetRepeatedEnum(number, index, value);
}
- static inline void Add(int number, ConstType value, ExtensionSet* set) {
- set->AddEnum(number, value);
+ 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);
}
};
@@ -513,13 +567,17 @@ template <typename Type>
class MessageTypeTraits {
public:
typedef const Type& ConstType;
- typedef Type* MutableType;
+ typedef Type* MutableType;
- static inline ConstType Get(int number, const ExtensionSet& set) {
- return static_cast<const Type&>(set.GetMessage(number));
+ static inline ConstType Get(int number, const ExtensionSet& set,
+ ConstType default_value) {
+ return static_cast<const Type&>(
+ set.GetMessage(number, default_value));
}
- static inline MutableType Mutable(int number, ExtensionSet* set) {
- return static_cast<Type*>(set->MutableMessage(number));
+ static inline MutableType Mutable(int number, FieldType field_type,
+ ExtensionSet* set) {
+ return static_cast<Type*>(
+ set->MutableMessage(number, field_type, Type::default_instance()));
}
};
@@ -535,8 +593,10 @@ class RepeatedMessageTypeTraits {
static inline MutableType Mutable(int number, int index, ExtensionSet* set) {
return static_cast<Type*>(set->MutableRepeatedMessage(number, index));
}
- static inline MutableType Add(int number, ExtensionSet* set) {
- return static_cast<Type*>(set->AddMessage(number));
+ static inline MutableType Add(int number, FieldType field_type,
+ ExtensionSet* set) {
+ return static_cast<Type*>(
+ set->AddMessage(number, field_type, Type::default_instance()));
}
};
@@ -546,7 +606,7 @@ class RepeatedMessageTypeTraits {
// This is the type of actual extension objects. E.g. if you have:
// extends Foo with optional int32 bar = 1234;
// then "bar" will be defined in C++ as:
-// ExtensionIdentifier<Foo, PrimitiveTypeTraits<int32>> bar(1234);
+// ExtensionIdentifier<Foo, PrimitiveTypeTraits<int32>, 1, false> bar(1234);
//
// Note that we could, in theory, supply the field number as a template
// parameter, and thus make an instance of ExtensionIdentifier have no
@@ -557,18 +617,145 @@ class RepeatedMessageTypeTraits {
// but that would be bad because it would cause this extension to not be
// registered at static initialization, and therefore using it would crash.
-template <typename ExtendeeType, typename TypeTraitsType>
-class ExtensionIdentifier {
+template <typename ExtendeeType, typename TypeTraitsType,
+ FieldType field_type, bool is_packed>
+class LIBPROTOBUF_EXPORT ExtensionIdentifier {
public:
typedef TypeTraitsType TypeTraits;
typedef ExtendeeType Extendee;
- ExtensionIdentifier(int number): number_(number) {}
+ ExtensionIdentifier(int number, typename TypeTraits::ConstType default_value)
+ : number_(number), default_value_(default_value) {}
inline int number() const { return number_; }
+ typename TypeTraits::ConstType default_value() const {
+ return default_value_;
+ }
+
private:
const int number_;
+ const typename TypeTraits::ConstType default_value_;
};
+// -------------------------------------------------------------------
+// Generated accessors
+
+// This macro should be expanded in the context of a generated type which
+// has extensions.
+//
+// We use "_proto_TypeTraits" as a type name below because "TypeTraits"
+// causes problems if the class has a nested message or enum type with that
+// name and "_TypeTraits" is technically reserved for the C++ library since
+// it starts with an underscore followed by a capital letter.
+#define GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(CLASSNAME) \
+ /* Has, Size, Clear */ \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType field_type, \
+ bool is_packed> \
+ inline bool HasExtension( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
+ return _extensions_.Has(id.number()); \
+ } \
+ \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType field_type, \
+ bool is_packed> \
+ inline void ClearExtension( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
+ _extensions_.ClearExtension(id.number()); \
+ } \
+ \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType field_type, \
+ bool is_packed> \
+ inline int ExtensionSize( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
+ return _extensions_.ExtensionSize(id.number()); \
+ } \
+ \
+ /* Singular accessors */ \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType field_type, \
+ bool is_packed> \
+ inline typename _proto_TypeTraits::ConstType GetExtension( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) const { \
+ return _proto_TypeTraits::Get(id.number(), _extensions_, \
+ id.default_value()); \
+ } \
+ \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType field_type, \
+ bool is_packed> \
+ inline typename _proto_TypeTraits::MutableType MutableExtension( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
+ return _proto_TypeTraits::Mutable(id.number(), field_type, &_extensions_);\
+ } \
+ \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType field_type, \
+ bool is_packed> \
+ inline void SetExtension( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ typename _proto_TypeTraits::ConstType value) { \
+ _proto_TypeTraits::Set(id.number(), field_type, value, &_extensions_); \
+ } \
+ \
+ /* Repeated accessors */ \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType field_type, \
+ bool is_packed> \
+ inline typename _proto_TypeTraits::ConstType GetExtension( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ int index) const { \
+ return _proto_TypeTraits::Get(id.number(), _extensions_, index); \
+ } \
+ \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType field_type, \
+ bool is_packed> \
+ inline typename _proto_TypeTraits::MutableType MutableExtension( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ int index) { \
+ return _proto_TypeTraits::Mutable(id.number(), index, &_extensions_); \
+ } \
+ \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType field_type, \
+ bool is_packed> \
+ inline void SetExtension( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ int index, typename _proto_TypeTraits::ConstType value) { \
+ _proto_TypeTraits::Set(id.number(), index, value, &_extensions_); \
+ } \
+ \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType field_type, \
+ bool is_packed> \
+ inline typename _proto_TypeTraits::MutableType AddExtension( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id) { \
+ return _proto_TypeTraits::Add(id.number(), field_type, &_extensions_); \
+ } \
+ \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType field_type, \
+ bool is_packed> \
+ inline void AddExtension( \
+ const ::google::protobuf::internal::ExtensionIdentifier< \
+ CLASSNAME, _proto_TypeTraits, field_type, is_packed>& id, \
+ typename _proto_TypeTraits::ConstType value) { \
+ _proto_TypeTraits::Add(id.number(), field_type, is_packed, \
+ value, &_extensions_); \
+ }
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc
index 631bbc43..dfd88318 100644
--- a/src/google/protobuf/extension_set_unittest.cc
+++ b/src/google/protobuf/extension_set_unittest.cc
@@ -35,10 +35,13 @@
#include <google/protobuf/extension_set.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/test_util.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/testing/googletest.h>
#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util-inl.h>
namespace google {
namespace protobuf {
@@ -102,6 +105,11 @@ TEST(ExtensionSetTest, Clear) {
unittest::optional_foreign_message_extension));
EXPECT_NE(&unittest_import::ImportMessage::default_instance(),
&message.GetExtension(unittest::optional_import_message_extension));
+
+ // Make sure setting stuff again after clearing works. (This takes slightly
+ // different code paths since the objects are reused.)
+ TestUtil::SetAllExtensions(&message);
+ TestUtil::ExpectAllExtensionsSet(message);
}
TEST(ExtensionSetTest, ClearOneField) {
@@ -166,28 +174,90 @@ TEST(ExtensionSetTest, SwapWithSelf) {
TestUtil::ExpectAllExtensionsSet(message);
}
-TEST(ExtensionSetTest, Serialization) {
+TEST(ExtensionSetTest, SerializationToArray) {
// Serialize as TestAllExtensions and parse as TestAllTypes to insure wire
// compatibility of extensions.
+ //
+ // This checks serialization to a flat array by explicitly reserving space in
+ // the string and calling the generated message's
+ // SerializeWithCachedSizesToArray.
unittest::TestAllExtensions source;
unittest::TestAllTypes destination;
+ TestUtil::SetAllExtensions(&source);
+ int size = source.ByteSize();
string data;
+ data.resize(size);
+ uint8* target = reinterpret_cast<uint8*>(string_as_array(&data));
+ uint8* end = source.SerializeWithCachedSizesToArray(target);
+ EXPECT_EQ(size, end - target);
+ EXPECT_TRUE(destination.ParseFromString(data));
+ TestUtil::ExpectAllFieldsSet(destination);
+}
+TEST(ExtensionSetTest, SerializationToStream) {
+ // Serialize as TestAllExtensions and parse as TestAllTypes to insure wire
+ // compatibility of extensions.
+ //
+ // This checks serialization to an output stream by creating an array output
+ // stream that can only buffer 1 byte at a time - this prevents the message
+ // from ever jumping to the fast path, ensuring that serialization happens via
+ // the CodedOutputStream.
+ unittest::TestAllExtensions source;
+ unittest::TestAllTypes destination;
TestUtil::SetAllExtensions(&source);
- source.SerializeToString(&data);
+ int size = source.ByteSize();
+ string data;
+ data.resize(size);
+ {
+ io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+ io::CodedOutputStream output_stream(&array_stream);
+ source.SerializeWithCachedSizes(&output_stream);
+ ASSERT_FALSE(output_stream.HadError());
+ }
EXPECT_TRUE(destination.ParseFromString(data));
TestUtil::ExpectAllFieldsSet(destination);
}
-TEST(ExtensionSetTest, PackedSerialization) {
+TEST(ExtensionSetTest, PackedSerializationToArray) {
// Serialize as TestPackedExtensions and parse as TestPackedTypes to insure
// wire compatibility of extensions.
+ //
+ // This checks serialization to a flat array by explicitly reserving space in
+ // the string and calling the generated message's
+ // SerializeWithCachedSizesToArray.
unittest::TestPackedExtensions source;
unittest::TestPackedTypes destination;
+ TestUtil::SetPackedExtensions(&source);
+ int size = source.ByteSize();
string data;
+ data.resize(size);
+ uint8* target = reinterpret_cast<uint8*>(string_as_array(&data));
+ uint8* end = source.SerializeWithCachedSizesToArray(target);
+ EXPECT_EQ(size, end - target);
+ EXPECT_TRUE(destination.ParseFromString(data));
+ TestUtil::ExpectPackedFieldsSet(destination);
+}
+TEST(ExtensionSetTest, PackedSerializationToStream) {
+ // Serialize as TestPackedExtensions and parse as TestPackedTypes to insure
+ // wire compatibility of extensions.
+ //
+ // This checks serialization to an output stream by creating an array output
+ // stream that can only buffer 1 byte at a time - this prevents the message
+ // from ever jumping to the fast path, ensuring that serialization happens via
+ // the CodedOutputStream.
+ unittest::TestPackedExtensions source;
+ unittest::TestPackedTypes destination;
TestUtil::SetPackedExtensions(&source);
- source.SerializeToString(&data);
+ int size = source.ByteSize();
+ string data;
+ data.resize(size);
+ {
+ io::ArrayOutputStream array_stream(string_as_array(&data), size, 1);
+ io::CodedOutputStream output_stream(&array_stream);
+ source.SerializeWithCachedSizes(&output_stream);
+ ASSERT_FALSE(output_stream.HadError());
+ }
EXPECT_TRUE(destination.ParseFromString(data));
TestUtil::ExpectPackedFieldsSet(destination);
}
@@ -395,6 +465,14 @@ TEST(ExtensionSetTest, SpaceUsedExcludingSelf) {
}
}
+TEST(ExtensionSetTest, InvalidEnumDeath) {
+ unittest::TestAllExtensions message;
+ EXPECT_DEBUG_DEATH(
+ message.SetExtension(unittest::optional_foreign_enum_extension,
+ static_cast<unittest::ForeignEnum>(53)),
+ "IsValid");
+}
+
} // namespace
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index 085af8f9..ffeaf62d 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -58,6 +58,21 @@ int StringSpaceUsedExcludingSelf(const string& str) {
}
}
+bool ParseNamedEnum(const EnumDescriptor* descriptor,
+ const string& name,
+ int* value) {
+ const EnumValueDescriptor* d = descriptor->FindValueByName(name);
+ if (d == NULL) return false;
+ *value = d->number();
+ return true;
+}
+
+const string& NameOfEnum(const EnumDescriptor* descriptor, int value) {
+ static string kEmptyString;
+ const EnumValueDescriptor* d = descriptor->FindValueByNumber(value);
+ return (d == NULL ? kEmptyString : d->name());
+}
+
// ===================================================================
// Helpers for reporting usage errors (e.g. trying to use GetInt32() on
// a string field).
@@ -160,6 +175,7 @@ GeneratedMessageReflection::GeneratedMessageReflection(
int unknown_fields_offset,
int extensions_offset,
const DescriptorPool* descriptor_pool,
+ MessageFactory* factory,
int object_size)
: descriptor_ (descriptor),
default_instance_ (default_instance),
@@ -170,7 +186,8 @@ GeneratedMessageReflection::GeneratedMessageReflection(
object_size_ (object_size),
descriptor_pool_ ((descriptor_pool == NULL) ?
DescriptorPool::generated_pool() :
- descriptor_pool) {
+ descriptor_pool),
+ message_factory_ (factory) {
}
GeneratedMessageReflection::~GeneratedMessageReflection() {}
@@ -365,7 +382,8 @@ void GeneratedMessageReflection::ListFields(
}
if (extensions_offset_ != -1) {
- GetExtensionSet(message).AppendToList(output);
+ GetExtensionSet(message).AppendToList(descriptor_, descriptor_pool_,
+ output);
}
// ListFields() must sort output by field number.
@@ -380,7 +398,8 @@ void GeneratedMessageReflection::ListFields(
const Message& message, const FieldDescriptor* field) const { \
USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE); \
if (field->is_extension()) { \
- return GetExtensionSet(message).Get##TYPENAME(field->number()); \
+ return GetExtensionSet(message).Get##TYPENAME( \
+ field->number(), field->default_value_##PASSTYPE()); \
} else { \
return GetField<TYPE>(message, field); \
} \
@@ -392,7 +411,7 @@ void GeneratedMessageReflection::ListFields(
USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \
if (field->is_extension()) { \
return MutableExtensionSet(message)->Set##TYPENAME( \
- field->number(), value); \
+ field->number(), field->type(), value); \
} else { \
SetField<TYPE>(message, field, value); \
} \
@@ -427,7 +446,8 @@ void GeneratedMessageReflection::ListFields(
PASSTYPE value) const { \
USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \
if (field->is_extension()) { \
- MutableExtensionSet(message)->Add##TYPENAME(field->number(), value); \
+ MutableExtensionSet(message)->Add##TYPENAME( \
+ field->number(), field->type(), field->options().packed(), value); \
} else { \
AddField<TYPE>(message, field, value); \
} \
@@ -448,7 +468,8 @@ string GeneratedMessageReflection::GetString(
const Message& message, const FieldDescriptor* field) const {
USAGE_CHECK_ALL(GetString, SINGULAR, STRING);
if (field->is_extension()) {
- return GetExtensionSet(message).GetString(field->number());
+ return GetExtensionSet(message).GetString(field->number(),
+ field->default_value_string());
} else {
return *GetField<const string*>(message, field);
}
@@ -459,7 +480,8 @@ const string& GeneratedMessageReflection::GetStringReference(
const FieldDescriptor* field, string* scratch) const {
USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING);
if (field->is_extension()) {
- return GetExtensionSet(message).GetString(field->number());
+ return GetExtensionSet(message).GetString(field->number(),
+ field->default_value_string());
} else {
return *GetField<const string*>(message, field);
}
@@ -471,7 +493,8 @@ void GeneratedMessageReflection::SetString(
const string& value) const {
USAGE_CHECK_ALL(SetString, SINGULAR, STRING);
if (field->is_extension()) {
- return MutableExtensionSet(message)->SetString(field->number(), value);
+ return MutableExtensionSet(message)->SetString(field->number(),
+ field->type(), value);
} else {
string** ptr = MutableField<string*>(message, field);
if (*ptr == DefaultRaw<const string*>(field)) {
@@ -523,7 +546,8 @@ void GeneratedMessageReflection::AddString(
const string& value) const {
USAGE_CHECK_ALL(AddString, REPEATED, STRING);
if (field->is_extension()) {
- MutableExtensionSet(message)->AddString(field->number(), value);
+ MutableExtensionSet(message)->AddString(field->number(),
+ field->type(), value);
} else {
AddField<string>(message, field, value);
}
@@ -538,7 +562,8 @@ const EnumValueDescriptor* GeneratedMessageReflection::GetEnum(
int value;
if (field->is_extension()) {
- value = GetExtensionSet(message).GetEnum(field->number());
+ value = GetExtensionSet(message).GetEnum(
+ field->number(), field->default_value_enum()->number());
} else {
value = GetField<int>(message, field);
}
@@ -555,7 +580,8 @@ void GeneratedMessageReflection::SetEnum(
USAGE_CHECK_ENUM_VALUE(SetEnum);
if (field->is_extension()) {
- MutableExtensionSet(message)->SetEnum(field->number(), value->number());
+ MutableExtensionSet(message)->SetEnum(field->number(), field->type(),
+ value->number());
} else {
SetField<int>(message, field, value->number());
}
@@ -599,7 +625,9 @@ void GeneratedMessageReflection::AddEnum(
USAGE_CHECK_ENUM_VALUE(AddEnum);
if (field->is_extension()) {
- MutableExtensionSet(message)->AddEnum(field->number(), value->number());
+ MutableExtensionSet(message)->AddEnum(field->number(), field->type(),
+ field->options().packed(),
+ value->number());
} else {
AddField<int>(message, field, value->number());
}
@@ -612,7 +640,9 @@ const Message& GeneratedMessageReflection::GetMessage(
USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
if (field->is_extension()) {
- return GetExtensionSet(message).GetMessage(field->number());
+ return GetExtensionSet(message).GetMessage(field->number(),
+ field->message_type(),
+ message_factory_);
} else {
const Message* result = GetRaw<const Message*>(message, field);
if (result == NULL) {
@@ -627,13 +657,15 @@ Message* GeneratedMessageReflection::MutableMessage(
USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
if (field->is_extension()) {
- return MutableExtensionSet(message)->MutableMessage(field->number());
+ return MutableExtensionSet(message)->MutableMessage(field->number(),
+ field->type(),
+ field->message_type(),
+ message_factory_);
} else {
Message** result = MutableField<Message*>(message, field);
if (*result == NULL) {
const Message* default_message = DefaultRaw<const Message*>(field);
*result = default_message->New();
- (*result)->CopyFrom(*default_message);
}
return *result;
}
@@ -667,7 +699,10 @@ Message* GeneratedMessageReflection::AddMessage(
USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
if (field->is_extension()) {
- return MutableExtensionSet(message)->AddMessage(field->number());
+ return MutableExtensionSet(message)->AddMessage(field->number(),
+ field->type(),
+ field->message_type(),
+ message_factory_);
} else {
return AddField<Message>(message, field);
}
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index 34383df8..8f1c9cfc 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -116,6 +116,7 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
// pool: DescriptorPool to search for extension definitions. Only
// used by FindKnownExtensionByName() and
// FindKnownExtensionByNumber().
+ // factory: MessageFactory to use to construct extension messages.
// object_size: The size of a message object of this type, as measured
// by sizeof().
GeneratedMessageReflection(const Descriptor* descriptor,
@@ -125,6 +126,7 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
int unknown_fields_offset,
int extensions_offset,
const DescriptorPool* pool,
+ MessageFactory* factory,
int object_size);
~GeneratedMessageReflection();
@@ -274,6 +276,7 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
int object_size_;
const DescriptorPool* descriptor_pool_;
+ MessageFactory* message_factory_;
template <typename Type>
inline const Type& GetRaw(const Message& message,
@@ -383,8 +386,31 @@ inline To dynamic_cast_if_available(From from) {
// Compute the space used by a string, not including sizeof(string) itself.
// This is slightly complicated because small strings store their data within
// the string object but large strings do not.
+LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
int StringSpaceUsedExcludingSelf(const string& str);
+// Helper for EnumType_Parse functions: try to parse the string 'name' as an
+// enum name of the given type, returning true and filling in value on success,
+// or returning false and leaving value unchanged on failure.
+bool ParseNamedEnum(const EnumDescriptor* descriptor,
+ const string& name,
+ int* value);
+
+template<typename EnumType>
+bool ParseNamedEnum(const EnumDescriptor* descriptor,
+ const string& name,
+ EnumType* value) {
+ int tmp;
+ if (!ParseNamedEnum(descriptor, name, &tmp)) return false;
+ *value = static_cast<EnumType>(tmp);
+ return true;
+}
+
+// Just a wrapper around printing the name of a value. The main point of this
+// function is not to be inlined, so that you can do this without including
+// descriptor.h.
+const string& NameOfEnum(const EnumDescriptor* descriptor, int value);
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index a0f08571..0a00d2bb 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -71,18 +71,13 @@ CodedInputStream::CodedInputStream(ZeroCopyInputStream* input)
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) {
}
@@ -514,7 +509,14 @@ CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output)
: output_(output),
buffer_(NULL),
buffer_size_(0),
- total_bytes_(0) {
+ total_bytes_(0),
+ had_error_(false) {
+ // Eagerly Refresh() so buffer space is immediately available.
+ Refresh();
+ // The Refresh() may have failed. If the client doesn't write any data,
+ // though, don't consider this an error. If the client does write data, then
+ // another Refresh() will be attempted and it will set the error once again.
+ had_error_ = false;
}
CodedOutputStream::~CodedOutputStream() {
@@ -543,21 +545,26 @@ bool CodedOutputStream::GetDirectBufferPointer(void** data, int* size) {
return true;
}
-bool CodedOutputStream::WriteRaw(const void* data, int size) {
+void CodedOutputStream::WriteRaw(const void* data, int size) {
while (buffer_size_ < size) {
memcpy(buffer_, data, buffer_size_);
size -= buffer_size_;
data = reinterpret_cast<const uint8*>(data) + buffer_size_;
- if (!Refresh()) return false;
+ if (!Refresh()) return;
}
memcpy(buffer_, data, size);
Advance(size);
- return true;
+}
+
+uint8* CodedOutputStream::WriteRawToArray(
+ const void* data, int size, uint8* target) {
+ memcpy(target, data, size);
+ return target + size;
}
-bool CodedOutputStream::WriteLittleEndian32(uint32 value) {
+void CodedOutputStream::WriteLittleEndian32(uint32 value) {
uint8 bytes[sizeof(value)];
bool use_fast = buffer_size_ >= sizeof(value);
@@ -570,13 +577,21 @@ bool CodedOutputStream::WriteLittleEndian32(uint32 value) {
if (use_fast) {
Advance(sizeof(value));
- return true;
} else {
- return WriteRaw(bytes, sizeof(value));
+ WriteRaw(bytes, sizeof(value));
}
}
-bool CodedOutputStream::WriteLittleEndian64(uint64 value) {
+uint8* CodedOutputStream::WriteLittleEndian32ToArray(
+ uint32 value, uint8* target) {
+ 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);
+ return target + sizeof(value);
+}
+
+void CodedOutputStream::WriteLittleEndian64(uint64 value) {
uint8 bytes[sizeof(value)];
uint32 part0 = static_cast<uint32>(value);
@@ -596,46 +611,66 @@ bool CodedOutputStream::WriteLittleEndian64(uint64 value) {
if (use_fast) {
Advance(sizeof(value));
- return true;
} else {
- return WriteRaw(bytes, sizeof(value));
+ WriteRaw(bytes, sizeof(value));
}
}
-bool CodedOutputStream::WriteVarint32Fallback(uint32 value) {
- if (buffer_size_ >= kMaxVarint32Bytes) {
- // Fast path: We have enough bytes left in the buffer to guarantee that
- // this write won't cross the end, so we can skip the checks.
- uint8* target = buffer_;
+uint8* CodedOutputStream::WriteLittleEndian64ToArray(
+ uint64 value, uint8* target) {
+ uint32 part0 = static_cast<uint32>(value);
+ uint32 part1 = static_cast<uint32>(value >> 32);
+
+ 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[5] = static_cast<uint8>(part1 >> 8);
+ target[6] = static_cast<uint8>(part1 >> 16);
+ target[7] = static_cast<uint8>(part1 >> 24);
+
+ return target + sizeof(value);
+}
- target[0] = static_cast<uint8>(value | 0x80);
- if (value >= (1 << 7)) {
- target[1] = static_cast<uint8>((value >> 7) | 0x80);
- if (value >= (1 << 14)) {
- target[2] = static_cast<uint8>((value >> 14) | 0x80);
- if (value >= (1 << 21)) {
- target[3] = static_cast<uint8>((value >> 21) | 0x80);
- if (value >= (1 << 28)) {
- target[4] = static_cast<uint8>(value >> 28);
- Advance(5);
- } else {
- target[3] &= 0x7F;
- Advance(4);
- }
+inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline(
+ uint32 value, uint8* target) {
+ target[0] = static_cast<uint8>(value | 0x80);
+ if (value >= (1 << 7)) {
+ target[1] = static_cast<uint8>((value >> 7) | 0x80);
+ if (value >= (1 << 14)) {
+ target[2] = static_cast<uint8>((value >> 14) | 0x80);
+ if (value >= (1 << 21)) {
+ target[3] = static_cast<uint8>((value >> 21) | 0x80);
+ if (value >= (1 << 28)) {
+ target[4] = static_cast<uint8>(value >> 28);
+ return target + 5;
} else {
- target[2] &= 0x7F;
- Advance(3);
+ target[3] &= 0x7F;
+ return target + 4;
}
} else {
- target[1] &= 0x7F;
- Advance(2);
+ target[2] &= 0x7F;
+ return target + 3;
}
} else {
- target[0] &= 0x7F;
- Advance(1);
+ target[1] &= 0x7F;
+ return target + 2;
}
+ } else {
+ target[0] &= 0x7F;
+ return target + 1;
+ }
+}
- return true;
+void CodedOutputStream::WriteVarint32(uint32 value) {
+ if (buffer_size_ >= kMaxVarint32Bytes) {
+ // Fast path: We have enough bytes left in the buffer to guarantee that
+ // this write won't cross the end, so we can skip the checks.
+ uint8* target = buffer_;
+ uint8* end = WriteVarint32FallbackToArrayInline(value, target);
+ int size = end - target;
+ Advance(size);
} else {
// Slow path: This write might cross the end of the buffer, so we
// compose the bytes first then use WriteRaw().
@@ -646,85 +681,96 @@ bool CodedOutputStream::WriteVarint32Fallback(uint32 value) {
value >>= 7;
}
bytes[size++] = static_cast<uint8>(value) & 0x7F;
- return WriteRaw(bytes, size);
+ WriteRaw(bytes, size);
}
}
-bool CodedOutputStream::WriteVarint64(uint64 value) {
- if (buffer_size_ >= kMaxVarintBytes) {
- // Fast path: We have enough bytes left in the buffer to guarantee that
- // this write won't cross the end, so we can skip the checks.
- uint8* target = buffer_;
+uint8* CodedOutputStream::WriteVarint32FallbackToArray(
+ uint32 value, uint8* target) {
+ return WriteVarint32FallbackToArrayInline(value, target);
+}
- // Splitting into 32-bit pieces gives better performance on 32-bit
- // processors.
- uint32 part0 = static_cast<uint32>(value );
- uint32 part1 = static_cast<uint32>(value >> 28);
- uint32 part2 = static_cast<uint32>(value >> 56);
-
- int size;
-
- // Here we can't really optimize for small numbers, since the value is
- // split into three parts. Cheking for numbers < 128, for instance,
- // would require three comparisons, since you'd have to make sure part1
- // and part2 are zero. However, if the caller is using 64-bit integers,
- // it is likely that they expect the numbers to often be very large, so
- // we probably don't want to optimize for small numbers anyway. Thus,
- // we end up with a hardcoded binary search tree...
- if (part2 == 0) {
- if (part1 == 0) {
- if (part0 < (1 << 14)) {
- if (part0 < (1 << 7)) {
- size = 1; goto size1;
- } else {
- size = 2; goto size2;
- }
+inline uint8* CodedOutputStream::WriteVarint64ToArrayInline(
+ uint64 value, uint8* target) {
+ // Splitting into 32-bit pieces gives better performance on 32-bit
+ // processors.
+ uint32 part0 = static_cast<uint32>(value );
+ uint32 part1 = static_cast<uint32>(value >> 28);
+ uint32 part2 = static_cast<uint32>(value >> 56);
+
+ int size;
+
+ // Here we can't really optimize for small numbers, since the value is
+ // split into three parts. Cheking for numbers < 128, for instance,
+ // would require three comparisons, since you'd have to make sure part1
+ // and part2 are zero. However, if the caller is using 64-bit integers,
+ // it is likely that they expect the numbers to often be very large, so
+ // we probably don't want to optimize for small numbers anyway. Thus,
+ // we end up with a hardcoded binary search tree...
+ if (part2 == 0) {
+ if (part1 == 0) {
+ if (part0 < (1 << 14)) {
+ if (part0 < (1 << 7)) {
+ size = 1; goto size1;
} else {
- if (part0 < (1 << 21)) {
- size = 3; goto size3;
- } else {
- size = 4; goto size4;
- }
+ size = 2; goto size2;
}
} else {
- if (part1 < (1 << 14)) {
- if (part1 < (1 << 7)) {
- size = 5; goto size5;
- } else {
- size = 6; goto size6;
- }
+ if (part0 < (1 << 21)) {
+ size = 3; goto size3;
} else {
- if (part1 < (1 << 21)) {
- size = 7; goto size7;
- } else {
- size = 8; goto size8;
- }
+ size = 4; goto size4;
}
}
} else {
- if (part2 < (1 << 7)) {
- size = 9; goto size9;
+ if (part1 < (1 << 14)) {
+ if (part1 < (1 << 7)) {
+ size = 5; goto size5;
+ } else {
+ size = 6; goto size6;
+ }
} else {
- size = 10; goto size10;
+ if (part1 < (1 << 21)) {
+ size = 7; goto size7;
+ } else {
+ size = 8; goto size8;
+ }
}
}
+ } else {
+ if (part2 < (1 << 7)) {
+ size = 9; goto size9;
+ } else {
+ size = 10; goto size10;
+ }
+ }
- GOOGLE_LOG(FATAL) << "Can't get here.";
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+
+ size10: target[9] = static_cast<uint8>((part2 >> 7) | 0x80);
+ size9 : target[8] = static_cast<uint8>((part2 ) | 0x80);
+ size8 : target[7] = static_cast<uint8>((part1 >> 21) | 0x80);
+ size7 : target[6] = static_cast<uint8>((part1 >> 14) | 0x80);
+ size6 : target[5] = static_cast<uint8>((part1 >> 7) | 0x80);
+ size5 : target[4] = static_cast<uint8>((part1 ) | 0x80);
+ size4 : target[3] = static_cast<uint8>((part0 >> 21) | 0x80);
+ size3 : target[2] = static_cast<uint8>((part0 >> 14) | 0x80);
+ size2 : target[1] = static_cast<uint8>((part0 >> 7) | 0x80);
+ size1 : target[0] = static_cast<uint8>((part0 ) | 0x80);
+
+ target[size-1] &= 0x7F;
+ return target + size;
+}
- size10: target[9] = static_cast<uint8>((part2 >> 7) | 0x80);
- size9 : target[8] = static_cast<uint8>((part2 ) | 0x80);
- size8 : target[7] = static_cast<uint8>((part1 >> 21) | 0x80);
- size7 : target[6] = static_cast<uint8>((part1 >> 14) | 0x80);
- size6 : target[5] = static_cast<uint8>((part1 >> 7) | 0x80);
- size5 : target[4] = static_cast<uint8>((part1 ) | 0x80);
- size4 : target[3] = static_cast<uint8>((part0 >> 21) | 0x80);
- size3 : target[2] = static_cast<uint8>((part0 >> 14) | 0x80);
- size2 : target[1] = static_cast<uint8>((part0 >> 7) | 0x80);
- size1 : target[0] = static_cast<uint8>((part0 ) | 0x80);
+void CodedOutputStream::WriteVarint64(uint64 value) {
+ if (buffer_size_ >= kMaxVarintBytes) {
+ // Fast path: We have enough bytes left in the buffer to guarantee that
+ // this write won't cross the end, so we can skip the checks.
+ uint8* target = buffer_;
- target[size-1] &= 0x7F;
+ uint8* end = WriteVarint64ToArrayInline(value, target);
+ int size = end - target;
Advance(size);
- return true;
} else {
// Slow path: This write might cross the end of the buffer, so we
// compose the bytes first then use WriteRaw().
@@ -735,10 +781,15 @@ bool CodedOutputStream::WriteVarint64(uint64 value) {
value >>= 7;
}
bytes[size++] = static_cast<uint8>(value) & 0x7F;
- return WriteRaw(bytes, size);
+ WriteRaw(bytes, size);
}
}
+uint8* CodedOutputStream::WriteVarint64ToArray(
+ uint64 value, uint8* target) {
+ return WriteVarint64ToArrayInline(value, target);
+}
+
bool CodedOutputStream::Refresh() {
void* void_buffer;
if (output_->Next(&void_buffer, &buffer_size_)) {
@@ -748,6 +799,7 @@ bool CodedOutputStream::Refresh() {
} else {
buffer_ = NULL;
buffer_size_ = 0;
+ had_error_ = true;
return false;
}
}
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index 8ebe4b35..9e450216 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -380,7 +380,46 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
//
// Most methods of CodedOutputStream which return a bool return false if an
// underlying I/O error occurs. Once such a failure occurs, the
-// CodedOutputStream is broken and is no longer useful.
+// CodedOutputStream is broken and is no longer useful. The Write* methods do
+// not return the stream status, but will invalidate the stream if an error
+// occurs. The client can probe HadError() to determine the status.
+//
+// Note that every method of CodedOutputStream which writes some data has
+// a corresponding static "ToArray" version. These versions write directly
+// to the provided buffer, returning a pointer past the last written byte.
+// They require that the buffer has sufficient capacity for the encoded data.
+// This allows an optimization where we check if an output stream has enough
+// space for an entire message before we start writing and, if there is, we
+// call only the ToArray methods to avoid doing bound checks for each
+// individual value.
+// i.e., in the example above:
+//
+// CodedOutputStream coded_output = new CodedOutputStream(raw_output);
+// int magic_number = 1234;
+// char text[] = "Hello world!";
+//
+// int coded_size = sizeof(magic_number) +
+// CodedOutputStream::Varint32Size(strlen(text)) +
+// strlen(text);
+//
+// uint8* buffer =
+// coded_output->GetDirectBufferForNBytesAndAdvance(coded_size);
+// if (buffer != NULL) {
+// // The output stream has enough space in the buffer: write directly to
+// // the array.
+// buffer = CodedOutputStream::WriteLittleEndian32ToArray(magic_number,
+// buffer);
+// buffer = CodedOutputStream::WriteVarint32ToArray(strlen(text), buffer);
+// buffer = CodedOutputStream::WriteRawToArray(text, strlen(text), buffer);
+// } else {
+// // Make bound-checked writes, which will ask the underlying stream for
+// // more space as needed.
+// coded_output->WriteLittleEndian32(magic_number);
+// coded_output->WriteVarint32(strlen(text));
+// coded_output->WriteRaw(text, strlen(text));
+// }
+//
+// delete coded_output;
class LIBPROTOBUF_EXPORT CodedOutputStream {
public:
// Create an CodedOutputStream that writes to the given ZeroCopyOutputStream.
@@ -405,35 +444,65 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// CodedOutputStream interface.
bool GetDirectBufferPointer(void** data, int* size);
+ // If there are at least "size" bytes available in the current buffer,
+ // returns a pointer directly into the buffer and advances over these bytes.
+ // The caller may then write directly into this buffer (e.g. using the
+ // *ToArray static methods) rather than go through CodedOutputStream. If
+ // there are not enough bytes available, returns NULL. The return pointer is
+ // invalidated as soon as any other non-const method of CodedOutputStream
+ // is called.
+ inline uint8* GetDirectBufferForNBytesAndAdvance(int size);
+
// Write raw bytes, copying them from the given buffer.
- bool WriteRaw(const void* buffer, int size);
+ void WriteRaw(const void* buffer, int size);
+ // Like WriteRaw() but writing directly to the target array.
+ // This is _not_ inlined, as the compiler often optimizes memcpy into inline
+ // copy loops. Since this gets called by every field with string or bytes
+ // type, inlining may lead to a significant amount of code bloat, with only a
+ // minor performance gain.
+ static uint8* WriteRawToArray(const void* buffer, int size, uint8* target);
// Equivalent to WriteRaw(str.data(), str.size()).
- bool WriteString(const string& str);
+ void WriteString(const string& str);
+ // Like WriteString() but writing directly to the target array.
+ static uint8* WriteStringToArray(const string& str, uint8* target);
// Write a 32-bit little-endian integer.
- bool WriteLittleEndian32(uint32 value);
+ void WriteLittleEndian32(uint32 value);
+ // Like WriteLittleEndian32() but writing directly to the target array.
+ static uint8* WriteLittleEndian32ToArray(uint32 value, uint8* target);
// Write a 64-bit little-endian integer.
- bool WriteLittleEndian64(uint64 value);
+ void WriteLittleEndian64(uint64 value);
+ // Like WriteLittleEndian64() but writing directly to the target array.
+ static uint8* WriteLittleEndian64ToArray(uint64 value, uint8* target);
// Write an unsigned integer with Varint encoding. Writing a 32-bit value
// is equivalent to casting it to uint64 and writing it as a 64-bit value,
// but may be more efficient.
- bool WriteVarint32(uint32 value);
+ void WriteVarint32(uint32 value);
+ // Like WriteVarint32() but writing directly to the target array.
+ static uint8* WriteVarint32ToArray(uint32 value, uint8* target);
// Write an unsigned integer with Varint encoding.
- bool WriteVarint64(uint64 value);
+ void WriteVarint64(uint64 value);
+ // Like WriteVarint64() but writing directly to the target array.
+ static uint8* WriteVarint64ToArray(uint64 value, uint8* target);
// Equivalent to WriteVarint32() except when the value is negative,
// in which case it must be sign-extended to a full 10 bytes.
- bool WriteVarint32SignExtended(int32 value);
+ void WriteVarint32SignExtended(int32 value);
+ // Like WriteVarint32SignExtended() but writing directly to the target array.
+ static uint8* WriteVarint32SignExtendedToArray(int32 value, uint8* target);
// This is identical to WriteVarint32(), but optimized for writing tags.
// In particular, if the input is a compile-time constant, this method
// compiles down to a couple instructions.
// Always inline because otherwise the aformentioned optimization can't work,
// but GCC by default doesn't want to inline this.
- bool WriteTag(uint32 value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ void WriteTag(uint32 value);
+ // Like WriteTag() but writing directly to the target array.
+ static uint8* WriteTagToArray(
+ uint32 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
// Returns the number of bytes needed to encode the given value as a varint.
static int VarintSize32(uint32 value);
@@ -446,6 +515,10 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// Returns the total number of bytes written since this object was created.
inline int ByteCount() const;
+ // Returns true if there was an underlying I/O error since this object was
+ // created.
+ bool HadError() const { return had_error_; }
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedOutputStream);
@@ -453,6 +526,7 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
uint8* buffer_;
int buffer_size_;
int total_bytes_; // Sum of sizes of all buffers seen so far.
+ bool had_error_; // Whether an error occurred during output.
// Advance the buffer by a given number of bytes.
void Advance(int amount);
@@ -461,7 +535,20 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// Advance(buffer_size_).
bool Refresh();
- bool WriteVarint32Fallback(uint32 value);
+ static uint8* WriteVarint32FallbackToArray(uint32 value, uint8* target);
+
+ // Always-inlined versions of WriteVarint* functions so that code can be
+ // reused, while still controlling size. For instance, WriteVarint32ToArray()
+ // should not directly call this: since it is inlined itself, doing so
+ // would greatly increase the size of generated code. Instead, it should call
+ // WriteVarint32FallbackToArray. Meanwhile, WriteVarint32() is already
+ // out-of-line, so it should just invoke this directly to avoid any extra
+ // function call overhead.
+ static uint8* WriteVarint32FallbackToArrayInline(
+ uint32 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ static uint8* WriteVarint64ToArrayInline(
+ uint64 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+
static int VarintSize32Fallback(uint32 value);
};
@@ -540,40 +627,59 @@ inline bool CodedInputStream::ExpectAtEnd() {
}
}
-inline bool CodedOutputStream::WriteVarint32(uint32 value) {
- if (value < 0x80 && buffer_size_ > 0) {
- *buffer_ = static_cast<uint8>(value);
- Advance(1);
- return true;
+inline uint8* CodedOutputStream::GetDirectBufferForNBytesAndAdvance(int size) {
+ if (buffer_size_ < size) {
+ return NULL;
+ } else {
+ uint8* result = buffer_;
+ Advance(size);
+ return result;
+ }
+}
+
+inline uint8* CodedOutputStream::WriteVarint32ToArray(uint32 value,
+ uint8* target) {
+ if (value < 0x80) {
+ *target = value;
+ return target + 1;
} else {
- return WriteVarint32Fallback(value);
+ return WriteVarint32FallbackToArray(value, target);
}
}
-inline bool CodedOutputStream::WriteVarint32SignExtended(int32 value) {
+inline void CodedOutputStream::WriteVarint32SignExtended(int32 value) {
if (value < 0) {
- return WriteVarint64(static_cast<uint64>(value));
+ WriteVarint64(static_cast<uint64>(value));
} else {
- return WriteVarint32(static_cast<uint32>(value));
+ WriteVarint32(static_cast<uint32>(value));
}
}
-inline bool CodedOutputStream::WriteTag(uint32 value) {
+inline uint8* CodedOutputStream::WriteVarint32SignExtendedToArray(
+ int32 value, uint8* target) {
+ if (value < 0) {
+ return WriteVarint64ToArray(static_cast<uint64>(value), target);
+ } else {
+ return WriteVarint32ToArray(static_cast<uint32>(value), target);
+ }
+}
+
+inline void CodedOutputStream::WriteTag(uint32 value) {
+ WriteVarint32(value);
+}
+
+inline uint8* CodedOutputStream::WriteTagToArray(
+ uint32 value, uint8* target) {
if (value < (1 << 7)) {
- if (buffer_size_ != 0) {
- buffer_[0] = static_cast<uint8>(value);
- Advance(1);
- return true;
- }
+ target[0] = value;
+ return target + 1;
} else if (value < (1 << 14)) {
- if (buffer_size_ >= 2) {
- buffer_[0] = static_cast<uint8>(value | 0x80);
- buffer_[1] = static_cast<uint8>(value >> 7);
- Advance(2);
- return true;
- }
+ target[0] = static_cast<uint8>(value | 0x80);
+ target[1] = static_cast<uint8>(value >> 7);
+ return target + 2;
+ } else {
+ return WriteVarint32FallbackToArray(value, target);
}
- return WriteVarint32Fallback(value);
}
inline int CodedOutputStream::VarintSize32(uint32 value) {
@@ -592,8 +698,13 @@ inline int CodedOutputStream::VarintSize32SignExtended(int32 value) {
}
}
-inline bool CodedOutputStream::WriteString(const string& str) {
- return WriteRaw(str.data(), str.size());
+inline void CodedOutputStream::WriteString(const string& str) {
+ WriteRaw(str.data(), str.size());
+}
+
+inline uint8* CodedOutputStream::WriteStringToArray(
+ const string& str, uint8* target) {
+ return WriteRawToArray(str.data(), str.size(), target);
}
inline int CodedOutputStream::ByteCount() const {
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index 6a6eafe9..e165fb93 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -268,8 +268,8 @@ TEST_2D(CodedStreamTest, WriteVarint32, kVarintCases, kBlockSizes) {
{
CodedOutputStream coded_output(&output);
- EXPECT_TRUE(coded_output.WriteVarint32(
- static_cast<uint32>(kVarintCases_case.value)));
+ coded_output.WriteVarint32(static_cast<uint32>(kVarintCases_case.value));
+ EXPECT_FALSE(coded_output.HadError());
EXPECT_EQ(kVarintCases_case.size, coded_output.ByteCount());
}
@@ -285,7 +285,8 @@ TEST_2D(CodedStreamTest, WriteVarint64, kVarintCases, kBlockSizes) {
{
CodedOutputStream coded_output(&output);
- EXPECT_TRUE(coded_output.WriteVarint64(kVarintCases_case.value));
+ coded_output.WriteVarint64(kVarintCases_case.value);
+ EXPECT_FALSE(coded_output.HadError());
EXPECT_EQ(kVarintCases_case.size, coded_output.ByteCount());
}
@@ -310,8 +311,8 @@ TEST_2D(CodedStreamTest, WriteVarint32SignExtended,
{
CodedOutputStream coded_output(&output);
- EXPECT_TRUE(coded_output.WriteVarint32SignExtended(
- kSignExtendedVarintCases_case));
+ coded_output.WriteVarint32SignExtended(kSignExtendedVarintCases_case);
+ EXPECT_FALSE(coded_output.HadError());
if (kSignExtendedVarintCases_case < 0) {
EXPECT_EQ(10, coded_output.ByteCount());
@@ -502,7 +503,8 @@ TEST_2D(CodedStreamTest, WriteLittleEndian32, kFixed32Cases, kBlockSizes) {
{
CodedOutputStream coded_output(&output);
- EXPECT_TRUE(coded_output.WriteLittleEndian32(kFixed32Cases_case.value));
+ coded_output.WriteLittleEndian32(kFixed32Cases_case.value);
+ EXPECT_FALSE(coded_output.HadError());
EXPECT_EQ(sizeof(uint32), coded_output.ByteCount());
}
@@ -517,7 +519,8 @@ TEST_2D(CodedStreamTest, WriteLittleEndian64, kFixed64Cases, kBlockSizes) {
{
CodedOutputStream coded_output(&output);
- EXPECT_TRUE(coded_output.WriteLittleEndian64(kFixed64Cases_case.value));
+ coded_output.WriteLittleEndian64(kFixed64Cases_case.value);
+ EXPECT_FALSE(coded_output.HadError());
EXPECT_EQ(sizeof(uint64), coded_output.ByteCount());
}
@@ -552,7 +555,8 @@ TEST_1D(CodedStreamTest, WriteRaw, kBlockSizes) {
{
CodedOutputStream coded_output(&output);
- EXPECT_TRUE(coded_output.WriteRaw(kRawBytes, sizeof(kRawBytes)));
+ coded_output.WriteRaw(kRawBytes, sizeof(kRawBytes));
+ EXPECT_FALSE(coded_output.HadError());
EXPECT_EQ(sizeof(kRawBytes), coded_output.ByteCount());
}
diff --git a/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc
index 730bd2f7..0b4516ef 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl.cc
@@ -185,11 +185,12 @@ bool StringOutputStream::Next(void** data, int* size) {
if (old_size < target_->capacity()) {
// Resize the string to match its capacity, since we can get away
// without a memory allocation this way.
- target_->resize(target_->capacity());
+ STLStringResizeUninitialized(target_, target_->capacity());
} else {
// Size has reached capacity, so double the size. Also make sure
// that the new size is at least kMinimumSize.
- target_->resize(
+ STLStringResizeUninitialized(
+ target_,
max(old_size * 2,
kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness.
}
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 097411cb..9df3d394 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -47,6 +47,7 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/stl_util-inl.h>
namespace google {
namespace protobuf {
@@ -205,9 +206,19 @@ bool Message::ParsePartialFromIstream(istream* input) {
-bool Message::SerializeWithCachedSizes(
+void Message::SerializeWithCachedSizes(
io::CodedOutputStream* output) const {
- return WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output);
+ WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output);
+}
+
+uint8* Message::SerializeWithCachedSizesToArray(uint8* target) const {
+ // We only optimize this when using optimize_for = SPEED.
+ int size = GetCachedSize();
+ io::ArrayOutputStream out(target, size);
+ io::CodedOutputStream coded_out(&out);
+ SerializeWithCachedSizes(&coded_out);
+ GOOGLE_CHECK(!coded_out.HadError());
+ return target + size;
}
int Message::ByteSize() const {
@@ -234,8 +245,8 @@ bool Message::SerializeToCodedStream(io::CodedOutputStream* output) const {
bool Message::SerializePartialToCodedStream(
io::CodedOutputStream* output) const {
ByteSize(); // Force size to be cached.
- if (!SerializeWithCachedSizes(output)) return false;
- return true;
+ SerializeWithCachedSizes(output);
+ return !output->HadError();
}
bool Message::SerializeToZeroCopyStream(
@@ -256,19 +267,12 @@ bool Message::AppendToString(string* output) const {
}
bool Message::AppendPartialToString(string* output) const {
- // For efficiency, we'd like to reserve the exact amount of space we need
- // in the string.
- int total_size = output->size() + ByteSize();
- output->reserve(total_size);
-
- io::StringOutputStream output_stream(output);
-
- {
- io::CodedOutputStream encoder(&output_stream);
- if (!SerializeWithCachedSizes(&encoder)) return false;
- }
-
- GOOGLE_CHECK_EQ(output_stream.ByteCount(), total_size);
+ int old_size = output->size();
+ int byte_size = ByteSize();
+ 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);
return true;
}
@@ -283,13 +287,17 @@ bool Message::SerializePartialToString(string* output) const {
}
bool Message::SerializeToArray(void* data, int size) const {
- io::ArrayOutputStream output_stream(data, size);
- return SerializeToZeroCopyStream(&output_stream);
+ GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
+ return SerializePartialToArray(data, size);
}
bool Message::SerializePartialToArray(void* data, int size) const {
- io::ArrayOutputStream output_stream(data, size);
- return SerializePartialToZeroCopyStream(&output_stream);
+ 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);
+ return true;
}
bool Message::SerializeToFileDescriptor(int file_descriptor) const {
@@ -347,12 +355,20 @@ class GeneratedMessageFactory : public MessageFactory {
static GeneratedMessageFactory* singleton();
+ typedef void RegistrationFunc();
+ void RegisterFile(const char* file, RegistrationFunc* registration_func);
void RegisterType(const Descriptor* descriptor, const Message* prototype);
// implements MessageFactory ---------------------------------------
const Message* GetPrototype(const Descriptor* type);
private:
+ // Only written at static init time, so does not require locking.
+ hash_map<const char*, RegistrationFunc*,
+ hash<const char*>, streq> file_map_;
+
+ // Initialized lazily, so requires locking.
+ Mutex mutex_;
hash_map<const Descriptor*, const Message*> type_map_;
};
@@ -366,19 +382,65 @@ GeneratedMessageFactory* GeneratedMessageFactory::singleton() {
return &singleton;
}
+void GeneratedMessageFactory::RegisterFile(
+ const char* file, RegistrationFunc* registration_func) {
+ if (!InsertIfNotPresent(&file_map_, file, registration_func)) {
+ GOOGLE_LOG(FATAL) << "File is already registered: " << file;
+ }
+}
+
void GeneratedMessageFactory::RegisterType(const Descriptor* descriptor,
const Message* prototype) {
GOOGLE_DCHECK_EQ(descriptor->file()->pool(), DescriptorPool::generated_pool())
<< "Tried to register a non-generated type with the generated "
"type registry.";
+ // This should only be called as a result of calling a file registration
+ // function during GetPrototype(), in which case we already have locked
+ // the mutex.
+ mutex_.AssertHeld();
if (!InsertIfNotPresent(&type_map_, descriptor, prototype)) {
GOOGLE_LOG(DFATAL) << "Type is already registered: " << descriptor->full_name();
}
}
const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) {
- return FindPtrOrNull(type_map_, type);
+ {
+ ReaderMutexLock lock(&mutex_);
+ const Message* result = FindPtrOrNull(type_map_, type);
+ if (result != NULL) return result;
+ }
+
+ // If the type is not in the generated pool, then we can't possibly handle
+ // it.
+ if (type->file()->pool() != DescriptorPool::generated_pool()) return NULL;
+
+ // Apparently the file hasn't been registered yet. Let's do that now.
+ RegistrationFunc* registration_func =
+ FindPtrOrNull(file_map_, type->file()->name().c_str());
+ if (registration_func == NULL) {
+ GOOGLE_LOG(DFATAL) << "File appears to be in generated pool but wasn't "
+ "registered: " << type->file()->name();
+ return NULL;
+ }
+
+ WriterMutexLock lock(&mutex_);
+
+ // Check if another thread preempted us.
+ const Message* result = FindPtrOrNull(type_map_, type);
+ if (result == NULL) {
+ // Nope. OK, register everything.
+ registration_func();
+ // Should be here now.
+ result = FindPtrOrNull(type_map_, type);
+ }
+
+ if (result == NULL) {
+ GOOGLE_LOG(DFATAL) << "Type appears to be in generated pool but wasn't "
+ << "registered: " << type->full_name();
+ }
+
+ return result;
}
} // namespace
@@ -387,6 +449,12 @@ MessageFactory* MessageFactory::generated_factory() {
return GeneratedMessageFactory::singleton();
}
+void MessageFactory::InternalRegisterGeneratedFile(
+ const char* filename, void (*register_messages)()) {
+ GeneratedMessageFactory::singleton()->RegisterFile(filename,
+ register_messages);
+}
+
void MessageFactory::InternalRegisterGeneratedMessage(
const Descriptor* descriptor, const Message* prototype) {
GeneratedMessageFactory::singleton()->RegisterType(descriptor, prototype);
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index b4209026..b05ea954 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -117,24 +117,24 @@
#else
#include <iosfwd>
#endif
-
-#if defined(_WIN32) && defined(GetMessage)
-// windows.h defines GetMessage() as a macro. Let's re-define it as an inline
-// function. This is necessary because Reflection has a method called
-// GetMessage() which we don't want overridden. The inline function should be
-// equivalent for C++ users.
-inline BOOL GetMessage_Win32(
- LPMSG lpMsg, HWND hWnd,
- UINT wMsgFilterMin, UINT wMsgFilterMax) {
- return GetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
-}
-#undef GetMessage
-inline BOOL GetMessage(
- LPMSG lpMsg, HWND hWnd,
- UINT wMsgFilterMin, UINT wMsgFilterMax) {
- return GetMessage_Win32(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
-}
-#endif
+
+#if defined(_WIN32) && defined(GetMessage)
+// windows.h defines GetMessage() as a macro. Let's re-define it as an inline
+// function. This is necessary because Reflection has a method called
+// GetMessage() which we don't want overridden. The inline function should be
+// equivalent for C++ users.
+inline BOOL GetMessage_Win32(
+ LPMSG lpMsg, HWND hWnd,
+ UINT wMsgFilterMin, UINT wMsgFilterMax) {
+ return GetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
+}
+#undef GetMessage
+inline BOOL GetMessage(
+ LPMSG lpMsg, HWND hWnd,
+ UINT wMsgFilterMin, UINT wMsgFilterMax) {
+ return GetMessage_Win32(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
+}
+#endif
#include <google/protobuf/stubs/common.h>
@@ -370,7 +370,12 @@ class LIBPROTOBUF_EXPORT Message {
// Serializes the message without recomputing the size. The message must
// not have changed since the last call to ByteSize(); if it has, the results
// are undefined.
- virtual bool SerializeWithCachedSizes(io::CodedOutputStream* output) const;
+ virtual void SerializeWithCachedSizes(io::CodedOutputStream* output) const;
+
+ // Like SerializeWithCachedSizes, but writes directly to *target, returning
+ // a pointer to the byte immediately after the last byte written. "target"
+ // must point at a byte array of at least ByteSize() bytes.
+ virtual uint8* SerializeWithCachedSizesToArray(uint8* target) const;
// Returns the result of the last call to ByteSize(). An embedded message's
// size is needed both to serialize it (because embedded messages are
@@ -731,8 +736,19 @@ class LIBPROTOBUF_EXPORT MessageFactory {
// This factory is a singleton. The caller must not delete the object.
static MessageFactory* generated_factory();
- // For internal use only: Registers a message type at static initialization
- // time, to be placed in generated_factory().
+ // For internal use only: Registers a .proto file at static initialization
+ // time, to be placed in generated_factory. The first time GetPrototype()
+ // is called with a descriptor from this file, |register_messages| will be
+ // called. It must call InternalRegisterGeneratedMessage() (below) to
+ // register each message type in the file. This strange mechanism is
+ // necessary because descriptors are built lazily, so we can't register
+ // types by their descriptor until we know that the descriptor exists.
+ static void InternalRegisterGeneratedFile(const char* filename,
+ void (*register_messages)());
+
+ // For internal use only: Registers a message type. Called only by the
+ // functions which are registered with InternalRegisterGeneratedFile(),
+ // above.
static void InternalRegisterGeneratedMessage(const Descriptor* descriptor,
const Message* prototype);
diff --git a/src/google/protobuf/reflection_ops_unittest.cc b/src/google/protobuf/reflection_ops_unittest.cc
index 2f2d5262..1cd56f1e 100644
--- a/src/google/protobuf/reflection_ops_unittest.cc
+++ b/src/google/protobuf/reflection_ops_unittest.cc
@@ -138,16 +138,18 @@ TEST(ReflectionOpsTest, MergeExtensions) {
TEST(ReflectionOpsTest, MergeUnknown) {
// Test that the messages' UnknownFieldSets are correctly merged.
unittest::TestEmptyMessage message1, message2;
- message1.mutable_unknown_fields()->AddField(1234)->add_varint(1);
- message2.mutable_unknown_fields()->AddField(1234)->add_varint(2);
+ message1.mutable_unknown_fields()->AddVarint(1234, 1);
+ message2.mutable_unknown_fields()->AddVarint(1234, 2);
ReflectionOps::Merge(message2, &message1);
- ASSERT_EQ(1, message1.unknown_fields().field_count());
- const UnknownField& field = message1.unknown_fields().field(0);
- ASSERT_EQ(2, field.varint_size());
- EXPECT_EQ(1, field.varint(0));
- EXPECT_EQ(2, field.varint(1));
+ ASSERT_EQ(2, message1.unknown_fields().field_count());
+ ASSERT_EQ(UnknownField::TYPE_VARINT,
+ message1.unknown_fields().field(0).type());
+ EXPECT_EQ(1, message1.unknown_fields().field(0).varint());
+ ASSERT_EQ(UnknownField::TYPE_VARINT,
+ message1.unknown_fields().field(1).type());
+ EXPECT_EQ(2, message1.unknown_fields().field(1).varint());
}
#ifdef GTEST_HAS_DEATH_TEST
@@ -211,7 +213,7 @@ TEST(ReflectionOpsTest, ClearExtensions) {
TEST(ReflectionOpsTest, ClearUnknown) {
// Test that the message's UnknownFieldSet is correctly cleared.
unittest::TestEmptyMessage message;
- message.mutable_unknown_fields()->AddField(1234)->add_varint(1);
+ message.mutable_unknown_fields()->AddVarint(1234, 1);
ReflectionOps::Clear(&message);
@@ -224,16 +226,13 @@ TEST(ReflectionOpsTest, DiscardUnknownFields) {
// Set some unknown fields in message.
message.mutable_unknown_fields()
- ->AddField(123456)
- ->add_varint(654321);
+ ->AddVarint(123456, 654321);
message.mutable_optional_nested_message()
->mutable_unknown_fields()
- ->AddField(123456)
- ->add_varint(654321);
+ ->AddVarint(123456, 654321);
message.mutable_repeated_nested_message(0)
->mutable_unknown_fields()
- ->AddField(123456)
- ->add_varint(654321);
+ ->AddVarint(123456, 654321);
EXPECT_EQ(1, message.unknown_fields().field_count());
EXPECT_EQ(1, message.optional_nested_message()
@@ -258,16 +257,13 @@ TEST(ReflectionOpsTest, DiscardUnknownExtensions) {
// Set some unknown fields.
message.mutable_unknown_fields()
- ->AddField(123456)
- ->add_varint(654321);
+ ->AddVarint(123456, 654321);
message.MutableExtension(unittest::optional_nested_message_extension)
->mutable_unknown_fields()
- ->AddField(123456)
- ->add_varint(654321);
+ ->AddVarint(123456, 654321);
message.MutableExtension(unittest::repeated_nested_message_extension, 0)
->mutable_unknown_fields()
- ->AddField(123456)
- ->add_varint(654321);
+ ->AddVarint(123456, 654321);
EXPECT_EQ(1, message.unknown_fields().field_count());
EXPECT_EQ(1,
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 44cd875b..8d5dc480 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -93,6 +93,7 @@ class LIBPROTOBUF_EXPORT GenericRepeatedField {
};
// We need this (from generated_message_reflection.cc).
+LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
int StringSpaceUsedExcludingSelf(const string& str);
} // namespace internal
@@ -865,6 +866,129 @@ RepeatedPtrField<Element>::end() const {
return iterator(elements_ + current_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:
+//
+// std::copy(some_sequence.begin(), some_sequence.end(),
+// google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence()));
+//
+// Ported by johannes from util/gtl/proto-array-iterators-inl.h
+
+namespace internal {
+// A back inserter for RepeatedField objects.
+template<typename T> class RepeatedFieldBackInsertIterator
+ : public std::iterator<std::output_iterator_tag, T> {
+ public:
+ explicit RepeatedFieldBackInsertIterator(
+ RepeatedField<T>* const mutable_field)
+ : field_(mutable_field) {
+ }
+ RepeatedFieldBackInsertIterator<T>& operator=(const T& value) {
+ field_->Add(value);
+ return *this;
+ }
+ RepeatedFieldBackInsertIterator<T>& operator*() {
+ return *this;
+ }
+ RepeatedFieldBackInsertIterator<T>& operator++() {
+ return *this;
+ }
+ RepeatedFieldBackInsertIterator<T>& operator++(int ignores_parameter) {
+ return *this;
+ }
+
+ private:
+ RepeatedField<T>* const field_;
+};
+
+// A back inserter for RepeatedPtrField objects.
+template<typename T> class RepeatedPtrFieldBackInsertIterator
+ : public std::iterator<std::output_iterator_tag, T> {
+ public:
+ RepeatedPtrFieldBackInsertIterator(
+ RepeatedPtrField<T>* const mutable_field)
+ : field_(mutable_field) {
+ }
+ RepeatedPtrFieldBackInsertIterator<T>& operator=(const T& value) {
+ *field_->Add() = value;
+ return *this;
+ }
+ RepeatedPtrFieldBackInsertIterator<T>& operator=(
+ const T* const ptr_to_value) {
+ *field_->Add() = *ptr_to_value;
+ return *this;
+ }
+ RepeatedPtrFieldBackInsertIterator<T>& operator*() {
+ return *this;
+ }
+ RepeatedPtrFieldBackInsertIterator<T>& operator++() {
+ return *this;
+ }
+ RepeatedPtrFieldBackInsertIterator<T>& operator++(int ignores_parameter) {
+ return *this;
+ }
+
+ private:
+ RepeatedPtrField<T>* const field_;
+};
+
+// A back inserter for RepeatedPtrFields that inserts by transfering ownership
+// of a pointer.
+template<typename T> class AllocatedRepeatedPtrFieldBackInsertIterator
+ : public std::iterator<std::output_iterator_tag, T> {
+ public:
+ explicit AllocatedRepeatedPtrFieldBackInsertIterator(
+ RepeatedPtrField<T>* const mutable_field)
+ : field_(mutable_field) {
+ }
+ AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator=(
+ T* const ptr_to_value) {
+ field_->AddAllocated(ptr_to_value);
+ return *this;
+ }
+ AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator*() {
+ return *this;
+ }
+ AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++() {
+ return *this;
+ }
+ AllocatedRepeatedPtrFieldBackInsertIterator<T>& operator++(
+ int ignores_parameter) {
+ return *this;
+ }
+
+ private:
+ RepeatedPtrField<T>* const field_;
+};
+} // namespace internal
+
+// Provides a back insert iterator for RepeatedField instances,
+// similar to std::back_inserter(). Note the identically named
+// function for RepeatedPtrField instances.
+template<typename T> internal::RepeatedFieldBackInsertIterator<T>
+RepeatedFieldBackInserter(RepeatedField<T>* const mutable_field) {
+ return internal::RepeatedFieldBackInsertIterator<T>(mutable_field);
+}
+
+// Provides a back insert iterator for RepeatedPtrField instances,
+// similar to std::back_inserter(). Note the identically named
+// function for RepeatedField instances.
+template<typename T> internal::RepeatedPtrFieldBackInsertIterator<T>
+RepeatedFieldBackInserter(RepeatedPtrField<T>* const mutable_field) {
+ return internal::RepeatedPtrFieldBackInsertIterator<T>(mutable_field);
+}
+
+// Provides a back insert iterator for RepeatedPtrField instances
+// similar to std::back_inserter() which transfers the ownership while
+// copying elements.
+template<typename T> internal::AllocatedRepeatedPtrFieldBackInsertIterator<T>
+AllocatedRepeatedPtrFieldBackInserter(
+ RepeatedPtrField<T>* const mutable_field) {
+ return internal::AllocatedRepeatedPtrFieldBackInsertIterator<T>(
+ mutable_field);
+}
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index 3ab97620..50f009b5 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -36,15 +36,22 @@
// other proto2 unittests.
#include <algorithm>
+#include <list>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/unittest.pb.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>
namespace google {
+using protobuf_unittest::TestAllTypes;
+
namespace protobuf {
+namespace {
// Test operations on a RepeatedField which is small enough that it does
// not allocate a separate array for storage.
@@ -621,5 +628,147 @@ TEST_F(RepeatedPtrFieldIteratorTest, Mutation) {
EXPECT_EQ("qux", proto_array_.Get(0));
}
+// -----------------------------------------------------------------------------
+// Unit-tests for the insert iterators
+// google::protobuf::RepeatedFieldBackInserter,
+// google::protobuf::AllocatedRepeatedPtrFieldBackInserter
+// Ported from util/gtl/proto-array-iterators_unittest.
+
+class RepeatedFieldInsertionIteratorsTest : public testing::Test {
+ protected:
+ std::list<double> halves;
+ std::list<int> fibonacci;
+ std::vector<string> words;
+ typedef TestAllTypes::NestedMessage Nested;
+ Nested nesteds[2];
+ std::vector<Nested*> nested_ptrs;
+ TestAllTypes protobuffer;
+
+ virtual void SetUp() {
+ fibonacci.push_back(1);
+ fibonacci.push_back(1);
+ fibonacci.push_back(2);
+ fibonacci.push_back(3);
+ fibonacci.push_back(5);
+ fibonacci.push_back(8);
+ std::copy(fibonacci.begin(), fibonacci.end(),
+ RepeatedFieldBackInserter(protobuffer.mutable_repeated_int32()));
+
+ halves.push_back(1.0);
+ halves.push_back(0.5);
+ halves.push_back(0.25);
+ halves.push_back(0.125);
+ halves.push_back(0.0625);
+ std::copy(halves.begin(), halves.end(),
+ RepeatedFieldBackInserter(protobuffer.mutable_repeated_double()));
+
+ words.push_back("Able");
+ words.push_back("was");
+ words.push_back("I");
+ words.push_back("ere");
+ words.push_back("I");
+ words.push_back("saw");
+ words.push_back("Elba");
+ std::copy(words.begin(), words.end(),
+ RepeatedFieldBackInserter(protobuffer.mutable_repeated_string()));
+
+ nesteds[0].set_bb(17);
+ nesteds[1].set_bb(4711);
+ std::copy(&nesteds[0], &nesteds[2],
+ RepeatedFieldBackInserter(
+ protobuffer.mutable_repeated_nested_message()));
+
+ nested_ptrs.push_back(new Nested);
+ nested_ptrs.back()->set_bb(170);
+ nested_ptrs.push_back(new Nested);
+ nested_ptrs.back()->set_bb(47110);
+ std::copy(nested_ptrs.begin(), nested_ptrs.end(),
+ RepeatedFieldBackInserter(
+ protobuffer.mutable_repeated_nested_message()));
+
+ }
+
+ virtual void TearDown() {
+ STLDeleteContainerPointers(nested_ptrs.begin(), nested_ptrs.end());
+ }
+};
+
+TEST_F(RepeatedFieldInsertionIteratorsTest, Fibonacci) {
+ EXPECT_TRUE(std::equal(fibonacci.begin(),
+ fibonacci.end(),
+ protobuffer.repeated_int32().begin()));
+ EXPECT_TRUE(std::equal(protobuffer.repeated_int32().begin(),
+ protobuffer.repeated_int32().end(),
+ fibonacci.begin()));
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest, Halves) {
+ EXPECT_TRUE(std::equal(halves.begin(),
+ halves.end(),
+ protobuffer.repeated_double().begin()));
+ EXPECT_TRUE(std::equal(protobuffer.repeated_double().begin(),
+ protobuffer.repeated_double().end(),
+ halves.begin()));
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest, Words) {
+ ASSERT_EQ(words.size(), protobuffer.repeated_string_size());
+ EXPECT_EQ(words.at(0), protobuffer.repeated_string(0));
+ EXPECT_EQ(words.at(1), protobuffer.repeated_string(1));
+ EXPECT_EQ(words.at(2), protobuffer.repeated_string(2));
+ EXPECT_EQ(words.at(3), protobuffer.repeated_string(3));
+ EXPECT_EQ(words.at(4), protobuffer.repeated_string(4));
+ EXPECT_EQ(words.at(5), protobuffer.repeated_string(5));
+ EXPECT_EQ(words.at(6), protobuffer.repeated_string(6));
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest, Nesteds) {
+ ASSERT_EQ(protobuffer.repeated_nested_message_size(), 4);
+ EXPECT_EQ(protobuffer.repeated_nested_message(0).bb(), 17);
+ EXPECT_EQ(protobuffer.repeated_nested_message(1).bb(), 4711);
+ EXPECT_EQ(protobuffer.repeated_nested_message(2).bb(), 170);
+ EXPECT_EQ(protobuffer.repeated_nested_message(3).bb(), 47110);
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest,
+ AllocatedRepeatedPtrFieldWithStringIntData) {
+ vector<Nested*> data;
+ TestAllTypes goldenproto;
+ for (int i = 0; i < 10; ++i) {
+ Nested* new_data = new Nested;
+ new_data->set_bb(i);
+ data.push_back(new_data);
+
+ new_data = goldenproto.add_repeated_nested_message();
+ new_data->set_bb(i);
+ }
+ TestAllTypes testproto;
+ copy(data.begin(), data.end(),
+ AllocatedRepeatedPtrFieldBackInserter(
+ testproto.mutable_repeated_nested_message()));
+ EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest,
+ AllocatedRepeatedPtrFieldWithString) {
+ vector<string*> data;
+ TestAllTypes goldenproto;
+ for (int i = 0; i < 10; ++i) {
+ string* new_data = new string;
+ *new_data = "name-" + SimpleItoa(i);
+ data.push_back(new_data);
+
+ new_data = goldenproto.add_repeated_string();
+ *new_data = "name-" + SimpleItoa(i);
+ }
+ TestAllTypes testproto;
+ copy(data.begin(), data.end(),
+ AllocatedRepeatedPtrFieldBackInserter(
+ testproto.mutable_repeated_string()));
+ EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
+}
+
+} // namespace
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index cadb3b93..4a55e004 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -1039,6 +1039,10 @@ class LIBPROTOBUF_EXPORT MutexLock {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock);
};
+// TODO(kenton): Implement these? Hard to implement portably.
+typedef MutexLock ReaderMutexLock;
+typedef MutexLock WriterMutexLock;
+
// MutexLockMaybe is like MutexLock, but is a no-op when mu is NULL.
class LIBPROTOBUF_EXPORT MutexLockMaybe {
public:
@@ -1056,6 +1060,8 @@ class LIBPROTOBUF_EXPORT MutexLockMaybe {
// but we don't want to stick "internal::" in front of them everywhere.
using internal::Mutex;
using internal::MutexLock;
+using internal::ReaderMutexLock;
+using internal::WriterMutexLock;
using internal::MutexLockMaybe;
// ===================================================================
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
index efbeeedd..c3414138 100644
--- a/src/google/protobuf/stubs/hash.h
+++ b/src/google/protobuf/stubs/hash.h
@@ -178,6 +178,33 @@ struct hash<string> {
}
};
+template <typename First, typename Second>
+struct hash<pair<First, Second> > {
+ inline size_t operator()(const pair<First, Second>& key) const {
+ size_t first_hash = hash<First>()(key.first);
+ size_t second_hash = hash<Second>()(key.second);
+
+ // FIXME(kenton): What is the best way to compute this hash? I have
+ // no idea! This seems a bit better than an XOR.
+ return first_hash * ((1 << 16) - 1) + second_hash;
+ }
+
+ static const size_t bucket_size = 4;
+ static const size_t min_buckets = 8;
+ inline size_t operator()(const pair<First, Second>& a,
+ const pair<First, Second>& b) const {
+ return a < b;
+ }
+};
+
+// Used by GCC/SGI STL only. (Why isn't this provided by the standard
+// library? :( )
+struct streq {
+ inline bool operator()(const char* a, const char* b) const {
+ return strcmp(a, b) == 0;
+ }
+};
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/stubs/map-util.h b/src/google/protobuf/stubs/map-util.h
index 3ceecec5..f5c9d6b6 100644
--- a/src/google/protobuf/stubs/map-util.h
+++ b/src/google/protobuf/stubs/map-util.h
@@ -40,6 +40,21 @@ namespace google {
namespace protobuf {
// Perform a lookup in a map or hash_map.
+// If the key is present in the map then the value associated with that
+// key is returned, otherwise the value passed as a default is returned.
+template <class Collection>
+const typename Collection::value_type::second_type&
+FindWithDefault(const Collection& collection,
+ const typename Collection::value_type::first_type& key,
+ const typename Collection::value_type::second_type& value) {
+ typename Collection::const_iterator it = collection.find(key);
+ if (it == collection.end()) {
+ return value;
+ }
+ return it->second;
+}
+
+// Perform a lookup in a map or hash_map.
// If the key is present a const pointer to the associated value is returned,
// otherwise a NULL pointer is returned.
template <class Collection>
diff --git a/src/google/protobuf/stubs/once.cc b/src/google/protobuf/stubs/once.cc
new file mode 100644
index 00000000..b47a031c
--- /dev/null
+++ b/src/google/protobuf/stubs/once.cc
@@ -0,0 +1,82 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// emulates google3/base/once.h
+//
+// This header is intended to be included only by internal .cc files and
+// generated .pb.cc files. Users should not use this directly.
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <google/protobuf/stubs/once.h>
+
+namespace google {
+namespace protobuf {
+
+#ifdef _WIN32
+
+struct GoogleOnceInternal {
+ GoogleOnceInternal() {
+ InitializeCriticalSection(&critical_section);
+ }
+ ~GoogleOnceInternal() {
+ DeleteCriticalSection(&critical_section);
+ }
+ CRITICAL_SECTION critical_section;
+};
+
+GoogleOnceType::GoogleOnceType() {
+ // internal_ may be non-NULL if Init() was already called.
+ if (internal_ == NULL) internal_ = new GoogleOnceInternal;
+}
+
+void GoogleOnceType::Init(void (*init_func)()) {
+ // internal_ may be NULL if we're still in dynamic initialization and the
+ // constructor has not been called yet. As mentioned in once.h, we assume
+ // that the program is still single-threaded at this time, and therefore it
+ // should be safe to initialize internal_ like so.
+ if (internal_ == NULL) internal_ = new GoogleOnceInternal;
+
+ EnterCriticalSection(&internal_->critical_section);
+ if (!initialized_) {
+ init_func();
+ initialized_ = true;
+ }
+ LeaveCriticalSection(&internal_->critical_section);
+}
+
+#endif
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/stubs/once.h b/src/google/protobuf/stubs/once.h
new file mode 100644
index 00000000..58f1ea91
--- /dev/null
+++ b/src/google/protobuf/stubs/once.h
@@ -0,0 +1,122 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// emulates google3/base/once.h
+//
+// This header is intended to be included only by internal .cc files and
+// generated .pb.cc files. Users should not use this directly.
+//
+// This is basically a portable version of pthread_once().
+//
+// This header declares three things:
+// * A type called GoogleOnceType.
+// * A macro GOOGLE_PROTOBUF_DECLARE_ONCE() which declares a variable of type
+// GoogleOnceType. This is the only legal way to declare such a variable.
+// The macro may only be used at the global scope (you cannot create local
+// or class member variables of this type).
+// * A function GogoleOnceInit(GoogleOnceType* once, void (*init_func)()).
+// This function, when invoked multiple times given the same GoogleOnceType
+// object, will invoke init_func on the first call only, and will make sure
+// none of the calls return before that first call to init_func has finished.
+//
+// This implements a way to perform lazy initialization. It's more efficient
+// than using mutexes as no lock is needed if initialization has already
+// happened.
+//
+// Example usage:
+// void Init();
+// GOOGLE_PROTOBUF_DECLARE_ONCE(once_init);
+//
+// // Calls Init() exactly once.
+// void InitOnce() {
+// GoogleOnceInit(&once_init, &Init);
+// }
+//
+// Note that if GoogleOnceInit() is called before main() has begun, it must
+// only be called by the thread that will eventually call main() -- that is,
+// the thread that performs dynamic initialization. In general this is a safe
+// assumption since people don't usually construct threads before main() starts,
+// but it is technically not guaranteed. Unfortunately, Win32 provides no way
+// whatsoever to statically-initialize its synchronization primitives, so our
+// only choice is to assume that dynamic initialization is single-threaded.
+
+#ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__
+#define GOOGLE_PROTOBUF_STUBS_ONCE_H__
+
+#include <google/protobuf/stubs/common.h>
+
+#ifndef _WIN32
+#include <pthread.h>
+#endif
+
+namespace google {
+namespace protobuf {
+
+#ifdef _WIN32
+
+struct GoogleOnceInternal;
+
+struct GoogleOnceType {
+ GoogleOnceType();
+ void Init(void (*init_func)());
+
+ volatile bool initialized_;
+ GoogleOnceInternal* internal_;
+};
+
+#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \
+ ::google::protobuf::GoogleOnceType NAME
+
+inline void GoogleOnceInit(GoogleOnceType* once, void (*init_func)()) {
+ // Note: Double-checked locking is safe on x86.
+ if (!once->initialized_) {
+ once->Init(init_func);
+ }
+}
+
+#else
+
+typedef pthread_once_t GoogleOnceType;
+
+#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \
+ pthread_once_t NAME = PTHREAD_ONCE_INIT
+
+inline void GoogleOnceInit(GoogleOnceType* once, void (*init_func)()) {
+ pthread_once(once, init_func);
+}
+
+#endif
+
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_ONCE_H__
diff --git a/src/google/protobuf/stubs/once_unittest.cc b/src/google/protobuf/stubs/once_unittest.cc
new file mode 100644
index 00000000..86e06478
--- /dev/null
+++ b/src/google/protobuf/stubs/once_unittest.cc
@@ -0,0 +1,253 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <pthread.h>
+#endif
+
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+class OnceInitTest : public testing::Test {
+ protected:
+ void SetUp() {
+ state_ = INIT_NOT_STARTED;
+ current_test_ = this;
+ }
+
+ // Since GoogleOnceType is only allowed to be allocated in static storage,
+ // each test must use a different pair of GoogleOnceType objects which it
+ // must declare itself.
+ void SetOnces(GoogleOnceType* once, GoogleOnceType* recursive_once) {
+ once_ = once;
+ recursive_once_ = recursive_once;
+ }
+
+ void InitOnce() {
+ GoogleOnceInit(once_, &InitStatic);
+ }
+ void InitRecursiveOnce() {
+ GoogleOnceInit(recursive_once_, &InitRecursiveStatic);
+ }
+
+ void BlockInit() { init_blocker_.Lock(); }
+ void UnblockInit() { init_blocker_.Unlock(); }
+
+ class TestThread {
+ public:
+ TestThread(Closure* callback)
+ : done_(false), joined_(false), callback_(callback) {
+#ifdef _WIN32
+ thread_ = CreateThread(NULL, 0, &Start, this, 0, NULL);
+#else
+ pthread_create(&thread_, NULL, &Start, this);
+#endif
+ }
+ ~TestThread() {
+ if (!joined_) Join();
+ }
+
+ bool IsDone() {
+ MutexLock lock(&done_mutex_);
+ return done_;
+ }
+ void Join() {
+ joined_ = true;
+#ifdef _WIN32
+ WaitForSingleObject(thread_, INFINITE);
+ CloseHandle(thread_);
+#else
+ pthread_join(thread_, NULL);
+#endif
+ }
+
+ private:
+#ifdef _WIN32
+ HANDLE thread_;
+#else
+ pthread_t thread_;
+#endif
+
+ Mutex done_mutex_;
+ bool done_;
+ bool joined_;
+ Closure* callback_;
+
+#ifdef _WIN32
+ static DWORD WINAPI Start(LPVOID arg) {
+#else
+ static void* Start(void* arg) {
+#endif
+ reinterpret_cast<TestThread*>(arg)->Run();
+ return 0;
+ }
+
+ void Run() {
+ callback_->Run();
+ MutexLock lock(&done_mutex_);
+ done_ = true;
+ }
+ };
+
+ TestThread* RunInitOnceInNewThread() {
+ return new TestThread(NewCallback(this, &OnceInitTest::InitOnce));
+ }
+ TestThread* RunInitRecursiveOnceInNewThread() {
+ return new TestThread(NewCallback(this, &OnceInitTest::InitRecursiveOnce));
+ }
+
+ enum State {
+ INIT_NOT_STARTED,
+ INIT_STARTED,
+ INIT_DONE
+ };
+ State CurrentState() {
+ MutexLock lock(&mutex_);
+ return state_;
+ }
+
+ void WaitABit() {
+#ifdef _WIN32
+ Sleep(1000);
+#else
+ sleep(1);
+#endif
+ }
+
+ private:
+ Mutex mutex_;
+ Mutex init_blocker_;
+ State state_;
+ GoogleOnceType* once_;
+ GoogleOnceType* recursive_once_;
+
+ void Init() {
+ MutexLock lock(&mutex_);
+ EXPECT_EQ(INIT_NOT_STARTED, state_);
+ state_ = INIT_STARTED;
+ mutex_.Unlock();
+ init_blocker_.Lock();
+ init_blocker_.Unlock();
+ mutex_.Lock();
+ state_ = INIT_DONE;
+ }
+
+ static OnceInitTest* current_test_;
+ static void InitStatic() { current_test_->Init(); }
+ static void InitRecursiveStatic() { current_test_->InitOnce(); }
+};
+
+OnceInitTest* OnceInitTest::current_test_ = NULL;
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(simple_once);
+
+TEST_F(OnceInitTest, Simple) {
+ SetOnces(&simple_once, NULL);
+
+ EXPECT_EQ(INIT_NOT_STARTED, CurrentState());
+ InitOnce();
+ EXPECT_EQ(INIT_DONE, CurrentState());
+
+ // Calling again has no effect.
+ InitOnce();
+ EXPECT_EQ(INIT_DONE, CurrentState());
+}
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(recursive_once1);
+GOOGLE_PROTOBUF_DECLARE_ONCE(recursive_once2);
+
+TEST_F(OnceInitTest, Recursive) {
+ SetOnces(&recursive_once1, &recursive_once2);
+
+ EXPECT_EQ(INIT_NOT_STARTED, CurrentState());
+ InitRecursiveOnce();
+ EXPECT_EQ(INIT_DONE, CurrentState());
+}
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_once);
+
+TEST_F(OnceInitTest, MultipleThreads) {
+ SetOnces(&multiple_threads_once, NULL);
+
+ scoped_ptr<TestThread> threads[4];
+ EXPECT_EQ(INIT_NOT_STARTED, CurrentState());
+ for (int i = 0; i < 4; i++) {
+ threads[i].reset(RunInitOnceInNewThread());
+ }
+ for (int i = 0; i < 4; i++) {
+ threads[i]->Join();
+ }
+ EXPECT_EQ(INIT_DONE, CurrentState());
+}
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_blocked_once1);
+GOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_blocked_once2);
+
+TEST_F(OnceInitTest, MultipleThreadsBlocked) {
+ SetOnces(&multiple_threads_blocked_once1, &multiple_threads_blocked_once2);
+
+ scoped_ptr<TestThread> threads[8];
+ EXPECT_EQ(INIT_NOT_STARTED, CurrentState());
+
+ BlockInit();
+ for (int i = 0; i < 4; i++) {
+ threads[i].reset(RunInitOnceInNewThread());
+ }
+ for (int i = 4; i < 8; i++) {
+ threads[i].reset(RunInitRecursiveOnceInNewThread());
+ }
+
+ WaitABit();
+
+ // We should now have one thread blocked inside Init(), four blocked waiting
+ // for Init() to complete, and three blocked waiting for InitRecursive() to
+ // complete.
+ EXPECT_EQ(INIT_STARTED, CurrentState());
+ UnblockInit();
+
+ for (int i = 0; i < 8; i++) {
+ threads[i]->Join();
+ }
+ EXPECT_EQ(INIT_DONE, CurrentState());
+}
+
+} // anonymous namespace
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc
index 60413f6d..8b15ce5e 100644
--- a/src/google/protobuf/test_util.cc
+++ b/src/google/protobuf/test_util.cc
@@ -1871,6 +1871,15 @@ void TestUtil::ReflectionTester::SetPackedFieldsViaReflection(
void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection(
const Message& message) {
+ // We have to split this into three function otherwise it creates a stack
+ // frame so large that it triggers a warning.
+ ExpectAllFieldsSetViaReflection1(message);
+ ExpectAllFieldsSetViaReflection2(message);
+ ExpectAllFieldsSetViaReflection3(message);
+}
+
+void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection1(
+ const Message& message) {
const Reflection* reflection = message.GetReflection();
string scratch;
const Message* sub_message;
@@ -1949,6 +1958,13 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection(
EXPECT_EQ("125", reflection->GetString(message, F("optional_cord")));
EXPECT_EQ("125", reflection->GetStringReference(message, F("optional_cord"), &scratch));
+}
+
+void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection2(
+ const Message& message) {
+ const Reflection* reflection = message.GetReflection();
+ string scratch;
+ const Message* sub_message;
// -----------------------------------------------------------------
@@ -2060,6 +2076,12 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection(
EXPECT_EQ("325", reflection->GetRepeatedString(message, F("repeated_cord"), 1));
EXPECT_EQ("325", reflection->GetRepeatedStringReference(
message, F("repeated_cord"), 1, &scratch));
+}
+
+void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection3(
+ const Message& message) {
+ const Reflection* reflection = message.GetReflection();
+ string scratch;
// -----------------------------------------------------------------
diff --git a/src/google/protobuf/test_util.h b/src/google/protobuf/test_util.h
index ca840c71..1bedb788 100644
--- a/src/google/protobuf/test_util.h
+++ b/src/google/protobuf/test_util.h
@@ -137,6 +137,12 @@ class TestUtil {
const EnumValueDescriptor* import_bar_;
const EnumValueDescriptor* import_baz_;
+ // We have to split this into three function otherwise it creates a stack
+ // frame so large that it triggers a warning.
+ void ExpectAllFieldsSetViaReflection1(const Message& message);
+ void ExpectAllFieldsSetViaReflection2(const Message& message);
+ void ExpectAllFieldsSetViaReflection3(const Message& message);
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionTester);
};
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index b7101661..ae88cdff 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -62,29 +62,20 @@ string Message::DebugString() const {
}
string Message::ShortDebugString() const {
- // TODO(kenton): Make TextFormat support this natively instead of using
- // DebugString() and munging the result.
- string result = DebugString();
-
- // Replace each contiguous range of whitespace (including newlines, and
- // starting with a newline) with a single space.
- int out = 0;
- for (int i = 0; i < result.size(); ++i) {
- if (result[i] != '\n') {
- result[out++] = result[i];
- } else {
- while (i < result.size() && isspace(result[i])) ++i;
- --i;
- result[out++] = ' ';
- }
- }
- // Remove trailing space, if there is one.
- if (out > 0 && isspace(result[out - 1])) {
- --out;
+ string debug_string;
+ io::StringOutputStream output_stream(&debug_string);
+
+ TextFormat::Printer printer;
+ printer.SetSingleLineMode(true);
+
+ printer.Print(*this, &output_stream);
+ // Single line mode currently might have an extra space at the end.
+ if (debug_string.size() > 0 &&
+ debug_string[debug_string.size() - 1] == ' ') {
+ debug_string.resize(debug_string.size() - 1);
}
- result.resize(out);
- return result;
+ return debug_string;
}
void Message::PrintDebugString() const {
@@ -429,9 +420,13 @@ class TextFormat::Parser::ParserImpl {
return false;
}
- io::Tokenizer::ParseString(tokenizer_.current().text, text);
+ text->clear();
+ while (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+ io::Tokenizer::ParseStringAppend(tokenizer_.current().text, text);
+
+ tokenizer_.Next();
+ }
- tokenizer_.Next();
return true;
}
@@ -591,15 +586,18 @@ class TextFormat::Parser::ParserImpl {
// ===========================================================================
// Internal class for writing text to the io::ZeroCopyOutputStream. Adapted
// from the Printer found in //google/protobuf/io/printer.h
-class TextFormat::TextGenerator {
+class TextFormat::Printer::TextGenerator {
public:
- explicit TextGenerator(io::ZeroCopyOutputStream* output)
+ explicit TextGenerator(io::ZeroCopyOutputStream* output,
+ int initial_indent_level)
: output_(output),
buffer_(NULL),
buffer_size_(0),
at_start_of_line_(true),
failed_(false),
- indent_("") {
+ indent_(""),
+ initial_indent_level_(initial_indent_level) {
+ indent_.resize(initial_indent_level_ * 2, ' ');
}
~TextGenerator() {
@@ -620,7 +618,8 @@ class TextFormat::TextGenerator {
// Reduces the current indent level by two spaces, or crashes if the indent
// level is zero.
void Outdent() {
- if (indent_.empty()) {
+ if (indent_.empty() ||
+ indent_.size() < initial_indent_level_ * 2) {
GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent().";
return;
}
@@ -699,6 +698,7 @@ class TextFormat::TextGenerator {
bool failed_;
string indent_;
+ int initial_indent_level_;
};
// ===========================================================================
@@ -770,8 +770,16 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input,
return Parser().MergeFromString(input, output);
}
-/* static */ bool TextFormat::PrintToString(const Message& message,
- string* output) {
+// ===========================================================================
+
+TextFormat::Printer::Printer()
+ : initial_indent_level_(0),
+ single_line_mode_(false) {}
+
+TextFormat::Printer::~Printer() {}
+
+bool TextFormat::Printer::PrintToString(const Message& message,
+ string* output) {
GOOGLE_DCHECK(output) << "output specified is NULL";
output->clear();
@@ -782,7 +790,7 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input,
return result;
}
-/* static */ bool TextFormat::PrintUnknownFieldsToString(
+bool TextFormat::Printer::PrintUnknownFieldsToString(
const UnknownFieldSet& unknown_fields,
string* output) {
GOOGLE_DCHECK(output) << "output specified is NULL";
@@ -792,9 +800,9 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input,
return PrintUnknownFields(unknown_fields, &output_stream);
}
-/* static */ bool TextFormat::Print(const Message& message,
- io::ZeroCopyOutputStream* output) {
- TextGenerator generator(output);
+bool TextFormat::Printer::Print(const Message& message,
+ io::ZeroCopyOutputStream* output) {
+ TextGenerator generator(output, initial_indent_level_);
Print(message, generator);
@@ -802,10 +810,10 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input,
return !generator.failed();
}
-/* static */ bool TextFormat::PrintUnknownFields(
+bool TextFormat::Printer::PrintUnknownFields(
const UnknownFieldSet& unknown_fields,
io::ZeroCopyOutputStream* output) {
- TextGenerator generator(output);
+ TextGenerator generator(output, initial_indent_level_);
PrintUnknownFields(unknown_fields, generator);
@@ -813,8 +821,8 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input,
return !generator.failed();
}
-/* static */ void TextFormat::Print(const Message& message,
- TextGenerator& generator) {
+void TextFormat::Printer::Print(const Message& message,
+ TextGenerator& generator) {
const Reflection* reflection = message.GetReflection();
vector<const FieldDescriptor*> fields;
reflection->ListFields(message, &fields);
@@ -824,7 +832,7 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input,
PrintUnknownFields(reflection->GetUnknownFields(message), generator);
}
-/* static */ void TextFormat::PrintFieldValueToString(
+void TextFormat::Printer::PrintFieldValueToString(
const Message& message,
const FieldDescriptor* field,
int index,
@@ -834,15 +842,15 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input,
output->clear();
io::StringOutputStream output_stream(output);
- TextGenerator generator(&output_stream);
+ TextGenerator generator(&output_stream, initial_indent_level_);
PrintFieldValue(message, message.GetReflection(), field, index, generator);
}
-/* static */ void TextFormat::PrintField(const Message& message,
- const Reflection* reflection,
- const FieldDescriptor* field,
- TextGenerator& generator) {
+void TextFormat::Printer::PrintField(const Message& message,
+ const Reflection* reflection,
+ const FieldDescriptor* field,
+ TextGenerator& generator) {
int count = 0;
if (field->is_repeated()) {
@@ -874,8 +882,12 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input,
}
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (single_line_mode_) {
+ generator.Print(" { ");
+ } else {
generator.Print(" {\n");
generator.Indent();
+ }
} else {
generator.Print(": ");
}
@@ -889,15 +901,21 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input,
PrintFieldValue(message, reflection, field, field_index, generator);
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (!single_line_mode_) {
generator.Outdent();
- generator.Print("}");
+ }
+ generator.Print("}");
}
- generator.Print("\n");
+ if (single_line_mode_) {
+ generator.Print(" ");
+ } else {
+ generator.Print("\n");
+ }
}
}
-/* static */ void TextFormat::PrintFieldValue(
+void TextFormat::Printer::PrintFieldValue(
const Message& message,
const Reflection* reflection,
const FieldDescriptor* field,
@@ -961,6 +979,35 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* input,
}
}
+/* static */ bool TextFormat::Print(const Message& message,
+ io::ZeroCopyOutputStream* output) {
+ return Printer().Print(message, output);
+}
+
+/* static */ bool TextFormat::PrintUnknownFields(
+ const UnknownFieldSet& unknown_fields,
+ io::ZeroCopyOutputStream* output) {
+ return Printer().PrintUnknownFields(unknown_fields, output);
+}
+
+/* static */ bool TextFormat::PrintToString(
+ const Message& message, string* output) {
+ return Printer().PrintToString(message, output);
+}
+
+/* static */ bool TextFormat::PrintUnknownFieldsToString(
+ const UnknownFieldSet& unknown_fields, string* output) {
+ return Printer().PrintUnknownFieldsToString(unknown_fields, output);
+}
+
+/* static */ void TextFormat::PrintFieldValueToString(
+ const Message& message,
+ const FieldDescriptor* field,
+ int index,
+ string* output) {
+ return Printer().PrintFieldValueToString(message, field, index, output);
+}
+
// Prints an integer as hex with a fixed number of digits dependent on the
// integer type.
template<typename IntType>
@@ -973,59 +1020,97 @@ static string PaddedHex(IntType value) {
return result;
}
-/* static */ void TextFormat::PrintUnknownFields(
+void TextFormat::Printer::PrintUnknownFields(
const UnknownFieldSet& unknown_fields, TextGenerator& generator) {
for (int i = 0; i < unknown_fields.field_count(); i++) {
const UnknownField& field = unknown_fields.field(i);
string field_number = SimpleItoa(field.number());
- for (int j = 0; j < field.varint_size(); j++) {
- generator.Print(field_number);
- generator.Print(": ");
- generator.Print(SimpleItoa(field.varint(j)));
- generator.Print("\n");
- }
- for (int j = 0; j < field.fixed32_size(); j++) {
- generator.Print(field_number);
- generator.Print(": 0x");
- char buffer[kFastToBufferSize];
- generator.Print(FastHex32ToBuffer(field.fixed32(j), buffer));
- generator.Print("\n");
- }
- for (int j = 0; j < field.fixed64_size(); j++) {
- generator.Print(field_number);
- generator.Print(": 0x");
- char buffer[kFastToBufferSize];
- generator.Print(FastHex64ToBuffer(field.fixed64(j), buffer));
- generator.Print("\n");
- }
- for (int j = 0; j < field.length_delimited_size(); j++) {
- generator.Print(field_number);
- const string& value = field.length_delimited(j);
- UnknownFieldSet embedded_unknown_fields;
- if (!value.empty() && embedded_unknown_fields.ParseFromString(value)) {
- // This field is parseable as a Message.
- // So it is probably an embedded message.
- generator.Print(" {\n");
- generator.Indent();
- PrintUnknownFields(embedded_unknown_fields, generator);
- generator.Outdent();
- generator.Print("}\n");
- } else {
- // This field is not parseable as a Message.
- // So it is probably just a plain string.
- generator.Print(": \"");
- generator.Print(CEscape(value));
- generator.Print("\"\n");
+ switch (field.type()) {
+ case UnknownField::TYPE_VARINT:
+ generator.Print(field_number);
+ generator.Print(": ");
+ generator.Print(SimpleItoa(field.varint()));
+ if (single_line_mode_) {
+ generator.Print(" ");
+ } else {
+ generator.Print("\n");
+ }
+ break;
+ case UnknownField::TYPE_FIXED32: {
+ generator.Print(field_number);
+ generator.Print(": 0x");
+ char buffer[kFastToBufferSize];
+ generator.Print(FastHex32ToBuffer(field.fixed32(), buffer));
+ if (single_line_mode_) {
+ generator.Print(" ");
+ } else {
+ generator.Print("\n");
+ }
+ break;
}
- }
- for (int j = 0; j < field.group_size(); j++) {
- generator.Print(field_number);
- generator.Print(" {\n");
- generator.Indent();
- PrintUnknownFields(field.group(j), generator);
- generator.Outdent();
- generator.Print("}\n");
+ case UnknownField::TYPE_FIXED64: {
+ generator.Print(field_number);
+ generator.Print(": 0x");
+ char buffer[kFastToBufferSize];
+ generator.Print(FastHex64ToBuffer(field.fixed64(), buffer));
+ if (single_line_mode_) {
+ generator.Print(" ");
+ } else {
+ generator.Print("\n");
+ }
+ break;
+ }
+ case UnknownField::TYPE_LENGTH_DELIMITED: {
+ generator.Print(field_number);
+ const string& value = field.length_delimited();
+ UnknownFieldSet embedded_unknown_fields;
+ if (!value.empty() && embedded_unknown_fields.ParseFromString(value)) {
+ // This field is parseable as a Message.
+ // So it is probably an embedded message.
+ if (single_line_mode_) {
+ generator.Print(" { ");
+ } else {
+ generator.Print(" {\n");
+ generator.Indent();
+ }
+ PrintUnknownFields(embedded_unknown_fields, generator);
+ if (single_line_mode_) {
+ generator.Print("} ");
+ } else {
+ generator.Outdent();
+ generator.Print("}\n");
+ }
+ } else {
+ // This field is not parseable as a Message.
+ // So it is probably just a plain string.
+ generator.Print(": \"");
+ generator.Print(CEscape(value));
+ generator.Print("\"");
+ if (single_line_mode_) {
+ generator.Print(" ");
+ } else {
+ generator.Print("\n");
+ }
+ }
+ break;
+ }
+ case UnknownField::TYPE_GROUP:
+ generator.Print(field_number);
+ if (single_line_mode_) {
+ generator.Print(" { ");
+ } else {
+ generator.Print(" {\n");
+ generator.Indent();
+ }
+ PrintUnknownFields(field.group(), generator);
+ if (single_line_mode_) {
+ generator.Print("} ");
+ } else {
+ generator.Outdent();
+ generator.Print("}\n");
+ }
+ break;
}
}
}
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index aa349b10..e2b27c68 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -82,6 +82,76 @@ class LIBPROTOBUF_EXPORT TextFormat {
int index,
string* output);
+ // Class for those users which require more fine-grained control over how
+ // a protobuffer message is printed out.
+ class LIBPROTOBUF_EXPORT Printer {
+ public:
+ Printer();
+ ~Printer();
+
+ // Like TextFormat::Print
+ bool Print(const Message& message, io::ZeroCopyOutputStream* output);
+ // Like TextFormat::PrintUnknownFields
+ bool PrintUnknownFields(const UnknownFieldSet& unknown_fields,
+ io::ZeroCopyOutputStream* output);
+ // Like TextFormat::PrintToString
+ bool PrintToString(const Message& message, string* output);
+ // Like TextFormat::PrintUnknownFieldsToString
+ bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields,
+ string* output);
+ // Like TextFormat::PrintFieldValueToString
+ void PrintFieldValueToString(const Message& message,
+ const FieldDescriptor* field,
+ int index,
+ string* output);
+
+ // Adjust the initial indent level of all output. Each indent level is
+ // equal to two spaces.
+ void SetInitialIndentLevel(int indent_level) {
+ initial_indent_level_ = indent_level;
+ }
+
+ // If printing in single line mode, then the entire message will be output
+ // on a single line with no line breaks.
+ void SetSingleLineMode(bool single_line_mode) {
+ single_line_mode_ = single_line_mode;
+ }
+
+ private:
+ // Forward declaration of an internal class used to print the text
+ // output to the OutputStream (see text_format.cc for implementation).
+ class TextGenerator;
+
+ // Internal Print method, used for writing to the OutputStream via
+ // the TextGenerator class.
+ void Print(const Message& message,
+ TextGenerator& generator);
+
+ // Print a single field.
+ void PrintField(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,
+ const Reflection* reflection,
+ const FieldDescriptor* field,
+ int index,
+ TextGenerator& generator);
+
+ // Print the fields in an UnknownFieldSet. They are printed by tag number
+ // only. Embedded messages are heuristically identified by attempting to
+ // parse them.
+ void PrintUnknownFields(const UnknownFieldSet& unknown_fields,
+ TextGenerator& generator);
+
+ int initial_indent_level_;
+
+ bool single_line_mode_;
+ };
+
// Parses a text-format protocol message from the given input stream to
// the given message object. This function parses the format written
// by Print().
@@ -138,35 +208,6 @@ class LIBPROTOBUF_EXPORT TextFormat {
};
private:
- // Forward declaration of an internal class used to print the text
- // output to the OutputStream (see text_format.cc for implementation).
- class TextGenerator;
-
- // Internal Print method, used for writing to the OutputStream via
- // the TextGenerator class.
- static void Print(const Message& message,
- TextGenerator& generator);
-
- // Print a single field.
- static void PrintField(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.
- static void PrintFieldValue(const Message& message,
- const Reflection* reflection,
- const FieldDescriptor* field,
- int index,
- TextGenerator& generator);
-
- // Print the fields in an UnknownFieldSet. They are printed by tag number
- // only. Embedded messages are heuristically identified by attempting to
- // parse them.
- static void PrintUnknownFields(const UnknownFieldSet& unknown_fields,
- TextGenerator& generator);
-
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormat);
};
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 3d2cda9d..eaa278bc 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -163,18 +163,16 @@ TEST_F(TextFormatTest, PrintUnknownFields) {
unittest::TestEmptyMessage message;
UnknownFieldSet* unknown_fields = message.mutable_unknown_fields();
- UnknownField* field5 = unknown_fields->AddField(5);
- field5->add_varint(1);
- field5->add_fixed32(2);
- field5->add_fixed64(3);
- field5->add_length_delimited("4");
- field5->add_group()->AddField(10)->add_varint(5);
+ unknown_fields->AddVarint(5, 1);
+ unknown_fields->AddFixed32(5, 2);
+ unknown_fields->AddFixed64(5, 3);
+ unknown_fields->AddLengthDelimited(5, "4");
+ unknown_fields->AddGroup(5)->AddVarint(10, 5);
- UnknownField* field8 = unknown_fields->AddField(8);
- field8->add_varint(1);
- field8->add_varint(2);
- field8->add_varint(3);
+ unknown_fields->AddVarint(8, 1);
+ unknown_fields->AddVarint(8, 2);
+ unknown_fields->AddVarint(8, 3);
EXPECT_EQ(
"5: 1\n"
@@ -234,6 +232,48 @@ TEST_F(TextFormatTest, PrintUnknownMessage) {
text);
}
+TEST_F(TextFormatTest, PrintMessageWithIndent) {
+ // Test adding an initial indent to printing.
+
+ protobuf_unittest::TestAllTypes message;
+
+ message.add_repeated_string("abc");
+ message.add_repeated_string("def");
+ message.add_repeated_nested_message()->set_bb(123);
+
+ string text;
+ TextFormat::Printer printer;
+ printer.SetInitialIndentLevel(1);
+ EXPECT_TRUE(printer.PrintToString(message, &text));
+ EXPECT_EQ(
+ " repeated_string: \"abc\"\n"
+ " repeated_string: \"def\"\n"
+ " repeated_nested_message {\n"
+ " bb: 123\n"
+ " }\n",
+ text);
+}
+
+TEST_F(TextFormatTest, PrintMessageSingleLine) {
+ // Test printing a message on a single line.
+
+ protobuf_unittest::TestAllTypes message;
+
+ message.add_repeated_string("abc");
+ message.add_repeated_string("def");
+ message.add_repeated_nested_message()->set_bb(123);
+
+ string text;
+ TextFormat::Printer printer;
+ printer.SetInitialIndentLevel(1);
+ printer.SetSingleLineMode(true);
+ EXPECT_TRUE(printer.PrintToString(message, &text));
+ EXPECT_EQ(
+ " repeated_string: \"abc\" repeated_string: \"def\" "
+ "repeated_nested_message { bb: 123 } ",
+ text);
+}
+
TEST_F(TextFormatTest, ParseBasic) {
io::ArrayInputStream input_stream(proto_debug_string_.data(),
proto_debug_string_.size());
@@ -262,6 +302,29 @@ TEST_F(TextFormatTest, ParseStringEscape) {
EXPECT_EQ(kEscapeTestString, proto_.optional_string());
}
+TEST_F(TextFormatTest, ParseConcatenatedString) {
+ // Create a parse string with multiple parts on one line.
+ string parse_string = "optional_string: \"foo\" \"bar\"\n";
+
+ io::ArrayInputStream input_stream1(parse_string.data(),
+ parse_string.size());
+ TextFormat::Parse(&input_stream1, &proto_);
+
+ // Compare.
+ EXPECT_EQ("foobar", proto_.optional_string());
+
+ // Create a parse string with multiple parts on seperate lines.
+ parse_string = "optional_string: \"foo\"\n"
+ "\"bar\"\n";
+
+ io::ArrayInputStream input_stream2(parse_string.data(),
+ parse_string.size());
+ TextFormat::Parse(&input_stream2, &proto_);
+
+ // Compare.
+ EXPECT_EQ("foobar", proto_.optional_string());
+}
+
TEST_F(TextFormatTest, ParseFloatWithSuffix) {
// Test that we can parse a floating-point value with 'f' appended to the
// end. This is needed for backwards-compatibility with proto1.
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index 46ce77c3..85a14652 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -269,6 +269,14 @@ extend TestAllExtensions {
optional string default_cord_extension = 85 [ctype=CORD, default="123"];
}
+message TestNestedExtension {
+ extend TestAllExtensions {
+ // Check for bug where string extensions declared in tested scope did not
+ // compile.
+ optional string test = 1002 [default="test"];
+ }
+}
+
// We have separate messages for testing required fields because it's
// annoying to have to fill in required fields in TestProto in order to
// do anything with it. Note that we don't need to test every type of
diff --git a/src/google/protobuf/unittest_empty.proto b/src/google/protobuf/unittest_empty.proto
new file mode 100644
index 00000000..ab12d1fb
--- /dev/null
+++ b/src/google/protobuf/unittest_empty.proto
@@ -0,0 +1,37 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file intentionally left blank. (At one point this wouldn't compile
+// correctly.)
+
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index f42f9a59..318ffafe 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -43,38 +43,106 @@ namespace google {
namespace protobuf {
UnknownFieldSet::UnknownFieldSet()
- : internal_(NULL) {}
+ : fields_(NULL) {}
UnknownFieldSet::~UnknownFieldSet() {
- if (internal_ != NULL) {
- STLDeleteValues(&internal_->fields_);
- delete internal_;
- }
+ Clear();
+ delete fields_;
}
void UnknownFieldSet::Clear() {
- if (internal_ == NULL) return;
-
- if (internal_->fields_.size() > kMaxInactiveFields) {
- STLDeleteValues(&internal_->fields_);
- } else {
- // Don't delete the UnknownField objects. Just remove them from the active
- // set.
- for (int i = 0; i < internal_->active_fields_.size(); i++) {
- internal_->active_fields_[i]->Clear();
- internal_->active_fields_[i]->index_ = -1;
+ if (fields_ != NULL) {
+ for (int i = 0; i < fields_->size(); i++) {
+ (*fields_)[i].Delete();
}
+ fields_->clear();
}
-
- internal_->active_fields_.clear();
}
void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
for (int i = 0; i < other.field_count(); i++) {
- AddField(other.field(i).number())->MergeFrom(other.field(i));
+ AddField(other.field(i));
}
}
+int UnknownFieldSet::SpaceUsedExcludingSelf() const {
+ if (fields_ == NULL) return 0;
+
+ int total_size = sizeof(*fields_) + sizeof(UnknownField) * fields_->size();
+ for (int i = 0; i < fields_->size(); i++) {
+ const UnknownField& field = (*fields_)[i];
+ switch (field.type()) {
+ case UnknownField::TYPE_LENGTH_DELIMITED:
+ total_size += sizeof(*field.length_delimited_) +
+ internal::StringSpaceUsedExcludingSelf(*field.length_delimited_);
+ break;
+ case UnknownField::TYPE_GROUP:
+ total_size += field.group_->SpaceUsed();
+ break;
+ default:
+ break;
+ }
+ }
+ return total_size;
+}
+
+int UnknownFieldSet::SpaceUsed() const {
+ return sizeof(*this) + SpaceUsedExcludingSelf();
+}
+
+void UnknownFieldSet::AddVarint(int number, uint64 value) {
+ if (fields_ == NULL) fields_ = new vector<UnknownField>;
+ UnknownField field;
+ field.number_ = number;
+ field.type_ = UnknownField::TYPE_VARINT;
+ field.varint_ = value;
+ fields_->push_back(field);
+}
+
+void UnknownFieldSet::AddFixed32(int number, uint32 value) {
+ if (fields_ == NULL) fields_ = new vector<UnknownField>;
+ UnknownField field;
+ field.number_ = number;
+ field.type_ = UnknownField::TYPE_FIXED32;
+ field.fixed32_ = value;
+ fields_->push_back(field);
+}
+
+void UnknownFieldSet::AddFixed64(int number, uint64 value) {
+ if (fields_ == NULL) fields_ = new vector<UnknownField>;
+ UnknownField field;
+ field.number_ = number;
+ field.type_ = UnknownField::TYPE_FIXED64;
+ field.fixed64_ = value;
+ fields_->push_back(field);
+}
+
+string* UnknownFieldSet::AddLengthDelimited(int number) {
+ if (fields_ == NULL) fields_ = new vector<UnknownField>;
+ UnknownField field;
+ field.number_ = number;
+ field.type_ = UnknownField::TYPE_LENGTH_DELIMITED;
+ field.length_delimited_ = new string;
+ fields_->push_back(field);
+ return field.length_delimited_;
+}
+
+UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
+ if (fields_ == NULL) fields_ = new vector<UnknownField>;
+ UnknownField field;
+ field.number_ = number;
+ field.type_ = UnknownField::TYPE_GROUP;
+ field.group_ = new UnknownFieldSet;
+ fields_->push_back(field);
+ return field.group_;
+}
+
+void UnknownFieldSet::AddField(const UnknownField& field) {
+ if (fields_ == NULL) fields_ = new vector<UnknownField>;
+ fields_->push_back(field);
+ fields_->back().DeepCopy();
+}
+
bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {
UnknownFieldSet other;
@@ -103,129 +171,33 @@ bool UnknownFieldSet::ParseFromArray(const void* data, int size) {
return ParseFromZeroCopyStream(&input);
}
-const UnknownField* UnknownFieldSet::FindFieldByNumber(int number) const {
- if (internal_ == NULL) return NULL;
-
- map<int, UnknownField*>::iterator iter = internal_->fields_.find(number);
- if (iter != internal_->fields_.end() && iter->second->index() != -1) {
- return iter->second;
- } else {
- return NULL;
+void UnknownField::Delete() {
+ switch (type()) {
+ case UnknownField::TYPE_LENGTH_DELIMITED:
+ delete length_delimited_;
+ break;
+ case UnknownField::TYPE_GROUP:
+ delete group_;
+ break;
+ default:
+ break;
}
}
-UnknownField* UnknownFieldSet::AddField(int number) {
- if (internal_ == NULL) internal_ = new Internal;
-
- UnknownField** map_slot = &internal_->fields_[number];
- if (*map_slot == NULL) {
- *map_slot = new UnknownField(number);
- }
-
- UnknownField* field = *map_slot;
- if (field->index() == -1) {
- field->index_ = internal_->active_fields_.size();
- internal_->active_fields_.push_back(field);
- }
- return field;
-}
-
-int UnknownFieldSet::SpaceUsedExcludingSelf() const {
- int total_size = 0;
- if (internal_ != NULL) {
- total_size += sizeof(*internal_);
- total_size += internal_->active_fields_.capacity() *
- sizeof(Internal::FieldVector::value_type);
- total_size += internal_->fields_.size() *
- sizeof(Internal::FieldMap::value_type);
-
- // Account for the UnknownField objects themselves.
- for (Internal::FieldMap::const_iterator it = internal_->fields_.begin(),
- end = internal_->fields_.end();
- it != end;
- ++it) {
- total_size += it->second->SpaceUsed();
+void UnknownField::DeepCopy() {
+ switch (type()) {
+ case UnknownField::TYPE_LENGTH_DELIMITED:
+ length_delimited_ = new string(*length_delimited_);
+ break;
+ case UnknownField::TYPE_GROUP: {
+ UnknownFieldSet* group = new UnknownFieldSet;
+ group->MergeFrom(*group_);
+ group_ = group;
+ break;
}
+ default:
+ break;
}
- return total_size;
-}
-
-int UnknownFieldSet::SpaceUsed() const {
- return sizeof(*this) + SpaceUsedExcludingSelf();
-}
-
-UnknownFieldSet::Internal::FieldMap UnknownFieldSet::kEmptyMap;
-const UnknownFieldSet::iterator UnknownFieldSet::kEmptyIterator(
- kEmptyMap.end(), &kEmptyMap);
-const UnknownFieldSet::const_iterator UnknownFieldSet::kEmptyConstIterator(
- kEmptyMap.end(), &kEmptyMap);
-
-void UnknownFieldSet::iterator::AdvanceToNonEmpty() {
- while (inner_iterator_ != inner_map_->end() &&
- (inner_iterator_->second->index() == -1 ||
- inner_iterator_->second->empty())) {
- ++inner_iterator_;
- }
-}
-
-void UnknownFieldSet::const_iterator::AdvanceToNonEmpty() {
- while (inner_iterator_ != inner_map_->end() &&
- (inner_iterator_->second->index() == -1 ||
- inner_iterator_->second->empty())) {
- ++inner_iterator_;
- }
-}
-
-UnknownFieldSet::iterator UnknownFieldSet::begin() {
- if (internal_ == NULL) return kEmptyIterator;
-
- UnknownFieldSet::iterator result(internal_->fields_.begin(),
- &internal_->fields_);
- result.AdvanceToNonEmpty();
- return result;
-}
-
-UnknownFieldSet::const_iterator UnknownFieldSet::begin() const {
- if (internal_ == NULL) return kEmptyIterator;
-
- UnknownFieldSet::const_iterator result(internal_->fields_.begin(),
- &internal_->fields_);
- result.AdvanceToNonEmpty();
- return result;
-}
-
-UnknownField::UnknownField(int number)
- : number_(number),
- index_(-1) {
-}
-
-UnknownField::~UnknownField() {
-}
-
-void UnknownField::Clear() {
- clear_varint();
- clear_fixed32();
- clear_fixed64();
- clear_length_delimited();
- clear_group();
-}
-
-void UnknownField::MergeFrom(const UnknownField& other) {
- varint_ .MergeFrom(other.varint_ );
- fixed32_ .MergeFrom(other.fixed32_ );
- fixed64_ .MergeFrom(other.fixed64_ );
- length_delimited_.MergeFrom(other.length_delimited_);
- group_ .MergeFrom(other.group_ );
-}
-
-int UnknownField::SpaceUsed() const {
- int total_size = sizeof(*this);
- total_size += varint_.SpaceUsedExcludingSelf();
- total_size += fixed32_.SpaceUsedExcludingSelf();
- total_size += fixed64_.SpaceUsedExcludingSelf();
- total_size += length_delimited_.SpaceUsedExcludingSelf();
- total_size += group_.SpaceUsedExcludingSelf();
- return total_size;
}
} // namespace protobuf
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index f17012df..d6ca70fc 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -39,7 +39,6 @@
#define GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
#include <string>
-#include <map>
#include <vector>
#include <google/protobuf/repeated_field.h>
@@ -70,13 +69,6 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
void Clear();
// Is this set empty?
- //
- // Note that this is equivalent to field_count() == 0 but is NOT necessarily
- // equivalent to begin() == end(). The iterator class skips fields which are
- // themselves empty, so if field_count() is non-zero but field(i)->empty() is
- // true for all i, then begin() will be equal to end() but empty() will return
- // false. This inconsistency almost never occurs in practice because typical
- // code does not add empty fields to an UnknownFieldSet.
inline bool empty() const;
// Merge the contents of some other UnknownFieldSet with this one.
@@ -85,13 +77,6 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
// Swaps the contents of some other UnknownFieldSet with this one.
inline void Swap(UnknownFieldSet* x);
- // Find a field by field number. Returns NULL if not found.
- const UnknownField* FindFieldByNumber(int number) const;
-
- // Add a field by field number. If the field number already exists, returns
- // the existing UnknownField.
- UnknownField* AddField(int number);
-
// Computes (an estimate of) the total number of bytes currently used for
// storing the unknown fields in memory. Does NOT include
// sizeof(*this) in the calculation.
@@ -100,111 +85,28 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
// Version of SpaceUsed() including sizeof(*this).
int SpaceUsed() const;
- // STL-style iteration ---------------------------------------------
- // These iterate over the non-empty UnknownFields in order by field
- // number. All iterators are invalidated whenever the UnknownFieldSet
- // is modified.
-
- class const_iterator;
-
- class LIBPROTOBUF_EXPORT iterator {
- public:
- iterator() {}
-
- bool operator==(const iterator& other) {
- return inner_iterator_ == other.inner_iterator_;
- }
- bool operator!=(const iterator& other) {
- return inner_iterator_ != other.inner_iterator_;
- }
-
- UnknownField& operator*() { return *inner_iterator_->second; }
- UnknownField* operator->() { return inner_iterator_->second; }
- iterator& operator++() {
- ++inner_iterator_;
- AdvanceToNonEmpty();
- return *this;
- }
- iterator operator++(int) {
- iterator copy(*this);
- ++*this;
- return copy;
- }
-
- private:
- friend class UnknownFieldSet;
- friend class LIBPROTOBUF_EXPORT UnknownFieldSet::const_iterator;
- iterator(map<int, UnknownField*>::iterator inner_iterator,
- map<int, UnknownField*>* inner_map)
- : inner_iterator_(inner_iterator), inner_map_(inner_map) {}
-
- void AdvanceToNonEmpty();
-
- map<int, UnknownField*>::iterator inner_iterator_;
- map<int, UnknownField*>* inner_map_;
- };
-
- class LIBPROTOBUF_EXPORT const_iterator {
- public:
- const_iterator() {}
- const_iterator(const iterator& other)
- : inner_iterator_(other.inner_iterator_), inner_map_(other.inner_map_) {}
-
- bool operator==(const const_iterator& other) {
- return inner_iterator_ == other.inner_iterator_;
- }
- bool operator!=(const const_iterator& other) {
- return inner_iterator_ != other.inner_iterator_;
- }
-
- UnknownField& operator*() { return *inner_iterator_->second; }
- UnknownField* operator->() { return inner_iterator_->second; }
- const_iterator& operator++() {
- ++inner_iterator_;
- AdvanceToNonEmpty();
- return *this;
- }
- const_iterator operator++(int) {
- const_iterator copy(*this);
- ++*this;
- return copy;
- }
-
- private:
- friend class UnknownFieldSet;
- const_iterator(map<int, UnknownField*>::const_iterator inner_iterator,
- const map<int, UnknownField*>* inner_map)
- : inner_iterator_(inner_iterator), inner_map_(inner_map) {}
-
- void AdvanceToNonEmpty();
-
- map<int, UnknownField*>::const_iterator inner_iterator_;
- const map<int, UnknownField*>* inner_map_;
- };
-
- iterator begin();
- iterator end() {
- return internal_ == NULL ? kEmptyIterator :
- iterator(internal_->fields_.end(), &internal_->fields_);
- }
- const_iterator begin() const;
- const_iterator end() const {
- return internal_ == NULL ? kEmptyConstIterator :
- const_iterator(internal_->fields_.end(), &internal_->fields_);
- }
-
- // Old-style iteration ---------------------------------------------
- // New code should use begin() and end() rather than these methods.
-
// Returns the number of fields present in the UnknownFieldSet.
inline int field_count() const;
// Get a field in the set, where 0 <= index < field_count(). The fields
- // appear in arbitrary order.
+ // appear in the order in which they were added.
inline const UnknownField& field(int index) const;
// Get a mutable pointer to a field in the set, where
- // 0 <= index < field_count(). The fields appear in arbitrary order.
+ // 0 <= index < field_count(). The fields appear in the order in which
+ // they were added.
inline UnknownField* mutable_field(int index);
+ // Adding fields ---------------------------------------------------
+
+ void AddVarint(int number, uint64 value);
+ void AddFixed32(int number, uint32 value);
+ void AddFixed64(int number, uint64 value);
+ void AddLengthDelimited(int number, const string& value);
+ string* AddLengthDelimited(int number);
+ UnknownFieldSet* AddGroup(int number);
+
+ // Adds an unknown field from another set.
+ void AddField(const UnknownField& field);
+
// Parsing helpers -------------------------------------------------
// These work exactly like the similarly-named methods of Message.
@@ -217,268 +119,139 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
}
private:
- // "Active" fields are ones which have been added since the last time Clear()
- // was called. Inactive fields are objects we are keeping around incase
- // they become active again.
-
- struct Internal {
- // Contains all UnknownFields that have been allocated for this
- // UnknownFieldSet, including ones not currently active. Keyed by
- // field number. We intentionally try to reuse UnknownField objects for
- // the same field number they were used for originally because this makes
- // it more likely that the previously-allocated memory will have the right
- // layout.
- typedef map<int, UnknownField*> FieldMap;
- FieldMap fields_;
-
- // Contains the fields from fields_ that are currently active.
- typedef vector<UnknownField*> FieldVector;
- FieldVector active_fields_;
- };
-
- // We want an UnknownFieldSet to use no more space than a single pointer
- // until the first field is added.
- Internal* internal_;
-
- // Don't keep more inactive fields than this.
- static const int kMaxInactiveFields = 100;
-
- // Used by begin() and end() when internal_ is NULL.
- static Internal::FieldMap kEmptyMap;
- static const iterator kEmptyIterator;
- static const const_iterator kEmptyConstIterator;
+ vector<UnknownField>* fields_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet);
};
// Represents one field in an UnknownFieldSet.
-//
-// UnknownField's accessors are similar to those that would be produced by the
-// protocol compiler for the fields:
-// repeated uint64 varint;
-// repeated fixed32 fixed32;
-// repeated fixed64 fixed64;
-// repeated bytes length_delimited;
-// repeated UnknownFieldSet group;
-// (OK, so the last one isn't actually a valid field type but you get the
-// idea.)
class LIBPROTOBUF_EXPORT UnknownField {
public:
- ~UnknownField();
+ enum Type {
+ TYPE_VARINT,
+ TYPE_FIXED32,
+ TYPE_FIXED64,
+ TYPE_LENGTH_DELIMITED,
+ TYPE_GROUP
+ };
- // Clears all fields.
- void Clear();
+ // The field's tag number, as seen on the wire.
+ inline int number() const;
- // Is this field empty? (I.e. all of the *_size() methods return zero.)
- inline bool empty() const;
+ // The field type.
+ inline Type type() const;
- // Merge the contents of some other UnknownField with this one. For each
- // wire type, the values are simply concatenated.
- void MergeFrom(const UnknownField& other);
+ // Accessors -------------------------------------------------------
+ // Each method works only for UnknownFields of the corresponding type.
- // The field's tag number, as seen on the wire.
- inline int number() const;
+ inline uint64 varint() const;
+ inline uint32 fixed32() const;
+ inline uint64 fixed64() const;
+ inline const string& length_delimited() const;
+ inline const UnknownFieldSet& group() const;
- // The index of this UnknownField within the UnknownFieldSet (e.g.
- // set.field(field.index()) == field).
- inline int index() const;
-
- inline int varint_size () const;
- inline int fixed32_size () const;
- inline int fixed64_size () const;
- inline int length_delimited_size() const;
- inline int group_size () const;
-
- inline uint64 varint (int index) const;
- inline uint32 fixed32(int index) const;
- inline uint64 fixed64(int index) const;
- inline const string& length_delimited(int index) const;
- inline const UnknownFieldSet& group(int index) const;
-
- inline void set_varint (int index, uint64 value);
- inline void set_fixed32(int index, uint32 value);
- inline void set_fixed64(int index, uint64 value);
- inline void set_length_delimited(int index, const string& value);
- inline string* mutable_length_delimited(int index);
- inline UnknownFieldSet* mutable_group(int index);
-
- inline void add_varint (uint64 value);
- inline void add_fixed32(uint32 value);
- inline void add_fixed64(uint64 value);
- inline void add_length_delimited(const string& value);
- inline string* add_length_delimited();
- inline UnknownFieldSet* add_group();
-
- inline void clear_varint ();
- inline void clear_fixed32();
- inline void clear_fixed64();
- inline void clear_length_delimited();
- inline void clear_group();
-
- inline const RepeatedField <uint64 >& varint () const;
- inline const RepeatedField <uint32 >& fixed32 () const;
- inline const RepeatedField <uint64 >& fixed64 () const;
- inline const RepeatedPtrField<string >& length_delimited() const;
- inline const RepeatedPtrField<UnknownFieldSet>& group () const;
-
- inline RepeatedField <uint64 >* mutable_varint ();
- inline RepeatedField <uint32 >* mutable_fixed32 ();
- inline RepeatedField <uint64 >* mutable_fixed64 ();
- inline RepeatedPtrField<string >* mutable_length_delimited();
- inline RepeatedPtrField<UnknownFieldSet>* mutable_group ();
-
- // Returns (an estimate of) the total number of bytes used to represent the
- // unknown field.
- int SpaceUsed() const;
+ inline void set_varint(uint64 value);
+ inline void set_fixed32(uint32 value);
+ inline void set_fixed64(uint64 value);
+ inline void set_length_delimited(const string& value);
+ inline string* mutable_length_delimited();
+ inline UnknownFieldSet* mutable_group();
private:
friend class UnknownFieldSet;
- UnknownField(int number);
- int number_;
- int index_;
+ // If this UnknownField contains a pointer, delete it.
+ void Delete();
- RepeatedField <uint64 > varint_;
- RepeatedField <uint32 > fixed32_;
- RepeatedField <uint64 > fixed64_;
- RepeatedPtrField<string > length_delimited_;
- RepeatedPtrField<UnknownFieldSet> group_;
+ // Make a deep copy of any pointers in this UnknownField.
+ void DeepCopy();
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownField);
+ unsigned int number_ : 29;
+ unsigned int type_ : 3;
+ union {
+ uint64 varint_;
+ uint32 fixed32_;
+ uint64 fixed64_;
+ string* length_delimited_;
+ UnknownFieldSet* group_;
+ };
};
// ===================================================================
// inline implementations
inline bool UnknownFieldSet::empty() const {
- return internal_ == NULL || internal_->active_fields_.empty();
+ return fields_ == NULL || fields_->empty();
}
inline void UnknownFieldSet::Swap(UnknownFieldSet* x) {
- std::swap(internal_, x->internal_);
+ std::swap(fields_, x->fields_);
}
inline int UnknownFieldSet::field_count() const {
- return (internal_ == NULL) ? 0 : internal_->active_fields_.size();
+ return (fields_ == NULL) ? 0 : fields_->size();
}
inline const UnknownField& UnknownFieldSet::field(int index) const {
- return *(internal_->active_fields_[index]);
+ return (*fields_)[index];
}
inline UnknownField* UnknownFieldSet::mutable_field(int index) {
- return internal_->active_fields_[index];
+ return &(*fields_)[index];
}
-inline bool UnknownField::empty() const {
- return varint_.size() == 0 &&
- fixed32_.size() == 0 &&
- fixed64_.size() == 0 &&
- length_delimited_.size() == 0 &&
- group_.size() == 0;
+inline void UnknownFieldSet::AddLengthDelimited(
+ int number, const string& value) {
+ AddLengthDelimited(number)->assign(value);
}
inline int UnknownField::number() const { return number_; }
-inline int UnknownField::index () const { return index_; }
-
-inline int UnknownField::varint_size () const {return varint_.size();}
-inline int UnknownField::fixed32_size () const {return fixed32_.size();}
-inline int UnknownField::fixed64_size () const {return fixed64_.size();}
-inline int UnknownField::length_delimited_size() const {
- return length_delimited_.size();
+inline UnknownField::Type UnknownField::type() const {
+ return static_cast<Type>(type_);
}
-inline int UnknownField::group_size () const {return group_.size();}
-inline uint64 UnknownField::varint (int index) const {
- return varint_.Get(index);
-}
-inline uint32 UnknownField::fixed32(int index) const {
- return fixed32_.Get(index);
-}
-inline uint64 UnknownField::fixed64(int index) const {
- return fixed64_.Get(index);
-}
-inline const string& UnknownField::length_delimited(int index) const {
- return length_delimited_.Get(index);
-}
-inline const UnknownFieldSet& UnknownField::group(int index) const {
- return group_.Get(index);
-}
-
-inline void UnknownField::set_varint (int index, uint64 value) {
- varint_.Set(index, value);
-}
-inline void UnknownField::set_fixed32(int index, uint32 value) {
- fixed32_.Set(index, value);
-}
-inline void UnknownField::set_fixed64(int index, uint64 value) {
- fixed64_.Set(index, value);
-}
-inline void UnknownField::set_length_delimited(int index, const string& value) {
- length_delimited_.Mutable(index)->assign(value);
-}
-inline string* UnknownField::mutable_length_delimited(int index) {
- return length_delimited_.Mutable(index);
-}
-inline UnknownFieldSet* UnknownField::mutable_group(int index) {
- return group_.Mutable(index);
-}
-
-inline void UnknownField::add_varint (uint64 value) {
- varint_.Add(value);
-}
-inline void UnknownField::add_fixed32(uint32 value) {
- fixed32_.Add(value);
-}
-inline void UnknownField::add_fixed64(uint64 value) {
- fixed64_.Add(value);
-}
-inline void UnknownField::add_length_delimited(const string& value) {
- length_delimited_.Add()->assign(value);
-}
-inline string* UnknownField::add_length_delimited() {
- return length_delimited_.Add();
-}
-inline UnknownFieldSet* UnknownField::add_group() {
- return group_.Add();
-}
-
-inline void UnknownField::clear_varint () { varint_.Clear(); }
-inline void UnknownField::clear_fixed32() { fixed32_.Clear(); }
-inline void UnknownField::clear_fixed64() { fixed64_.Clear(); }
-inline void UnknownField::clear_length_delimited() {
- length_delimited_.Clear();
-}
-inline void UnknownField::clear_group() { group_.Clear(); }
-
-inline const RepeatedField<uint64>& UnknownField::varint () const {
+inline uint64 UnknownField::varint () const {
+ GOOGLE_DCHECK_EQ(type_, TYPE_VARINT);
return varint_;
}
-inline const RepeatedField<uint32>& UnknownField::fixed32() const {
+inline uint32 UnknownField::fixed32() const {
+ GOOGLE_DCHECK_EQ(type_, TYPE_FIXED32);
return fixed32_;
}
-inline const RepeatedField<uint64>& UnknownField::fixed64() const {
+inline uint64 UnknownField::fixed64() const {
+ GOOGLE_DCHECK_EQ(type_, TYPE_FIXED64);
return fixed64_;
}
-inline const RepeatedPtrField<string>& UnknownField::length_delimited() const {
- return length_delimited_;
+inline const string& UnknownField::length_delimited() const {
+ GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED);
+ return *length_delimited_;
}
-inline const RepeatedPtrField<UnknownFieldSet>& UnknownField::group() const {
- return group_;
+inline const UnknownFieldSet& UnknownField::group() const {
+ GOOGLE_DCHECK_EQ(type_, TYPE_GROUP);
+ return *group_;
}
-inline RepeatedField<uint64>* UnknownField::mutable_varint () {
- return &varint_;
+inline void UnknownField::set_varint(uint64 value) {
+ GOOGLE_DCHECK_EQ(type_, TYPE_VARINT);
+ varint_ = value;
}
-inline RepeatedField<uint32>* UnknownField::mutable_fixed32() {
- return &fixed32_;
+inline void UnknownField::set_fixed32(uint32 value) {
+ GOOGLE_DCHECK_EQ(type_, TYPE_FIXED32);
+ fixed32_ = value;
}
-inline RepeatedField<uint64>* UnknownField::mutable_fixed64() {
- return &fixed64_;
+inline void UnknownField::set_fixed64(uint64 value) {
+ GOOGLE_DCHECK_EQ(type_, TYPE_FIXED64);
+ fixed64_ = value;
}
-inline RepeatedPtrField<string>* UnknownField::mutable_length_delimited() {
- return &length_delimited_;
+inline void UnknownField::set_length_delimited(const string& value) {
+ GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED);
+ length_delimited_->assign(value);
}
-inline RepeatedPtrField<UnknownFieldSet>* UnknownField::mutable_group() {
- return &group_;
+inline string* UnknownField::mutable_length_delimited() {
+ GOOGLE_DCHECK_EQ(type_, TYPE_LENGTH_DELIMITED);
+ return length_delimited_;
+}
+inline UnknownFieldSet* UnknownField::mutable_group() {
+ GOOGLE_DCHECK_EQ(type_, TYPE_GROUP);
+ return group_;
}
} // namespace protobuf
diff --git a/src/google/protobuf/unknown_field_set_unittest.cc b/src/google/protobuf/unknown_field_set_unittest.cc
index 0a75af9f..1235c9ee 100644
--- a/src/google/protobuf/unknown_field_set_unittest.cc
+++ b/src/google/protobuf/unknown_field_set_unittest.cc
@@ -37,8 +37,8 @@
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/test_util.h>
@@ -46,6 +46,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util-inl.h>
namespace google {
namespace protobuf {
@@ -67,7 +68,12 @@ class UnknownFieldSetTest : public testing::Test {
const UnknownField* GetField(const string& name) {
const FieldDescriptor* field = descriptor_->FindFieldByName(name);
if (field == NULL) return NULL;
- return unknown_fields_->FindFieldByNumber(field->number());
+ for (int i = 0; i < unknown_fields_->field_count(); i++) {
+ if (unknown_fields_->field(i).number() == field->number()) {
+ return &unknown_fields_->field(i);
+ }
+ }
+ return NULL;
}
// Constructs a protocol buffer which contains fields with all the same
@@ -79,12 +85,10 @@ class UnknownFieldSetTest : public testing::Test {
bizarro_message.mutable_unknown_fields();
for (int i = 0; i < unknown_fields_->field_count(); i++) {
const UnknownField& unknown_field = unknown_fields_->field(i);
- UnknownField* bizarro_field =
- bizarro_unknown_fields->AddField(unknown_field.number());
- if (unknown_field.varint_size() == 0) {
- bizarro_field->add_varint(1);
+ if (unknown_field.type() == UnknownField::TYPE_VARINT) {
+ bizarro_unknown_fields->AddFixed32(unknown_field.number(), 1);
} else {
- bizarro_field->add_fixed32(1);
+ bizarro_unknown_fields->AddVarint(unknown_field.number(), 1);
}
}
@@ -103,71 +107,98 @@ class UnknownFieldSetTest : public testing::Test {
UnknownFieldSet* unknown_fields_;
};
-TEST_F(UnknownFieldSetTest, Index) {
- for (int i = 0; i < unknown_fields_->field_count(); i++) {
- EXPECT_EQ(i, unknown_fields_->field(i).index());
- }
-}
+TEST_F(UnknownFieldSetTest, AllFieldsPresent) {
+ // All fields of TestAllTypes should be present, in numeric order (because
+ // that's the order we parsed them in). Fields that are not valid field
+ // numbers of TestAllTypes should NOT be present.
-TEST_F(UnknownFieldSetTest, FindFieldByNumber) {
- // All fields of TestAllTypes should be present. Fields that are not valid
- // field numbers of TestAllTypes should NOT be present.
+ int pos = 0;
for (int i = 0; i < 1000; i++) {
- if (descriptor_->FindFieldByNumber(i) == NULL) {
- EXPECT_TRUE(unknown_fields_->FindFieldByNumber(i) == NULL);
- } else {
- EXPECT_TRUE(unknown_fields_->FindFieldByNumber(i) != NULL);
+ const FieldDescriptor* field = descriptor_->FindFieldByNumber(i);
+ if (field != NULL) {
+ ASSERT_LT(pos, unknown_fields_->field_count());
+ EXPECT_EQ(i, unknown_fields_->field(pos++).number());
+ if (field->is_repeated()) {
+ // Should have a second instance.
+ ASSERT_LT(pos, unknown_fields_->field_count());
+ EXPECT_EQ(i, unknown_fields_->field(pos++).number());
+ }
}
}
+ EXPECT_EQ(unknown_fields_->field_count(), pos);
}
TEST_F(UnknownFieldSetTest, Varint) {
const UnknownField* field = GetField("optional_int32");
ASSERT_TRUE(field != NULL);
- ASSERT_EQ(1, field->varint_size());
- EXPECT_EQ(all_fields_.optional_int32(), field->varint(0));
+ ASSERT_EQ(UnknownField::TYPE_VARINT, field->type());
+ EXPECT_EQ(all_fields_.optional_int32(), field->varint());
}
TEST_F(UnknownFieldSetTest, Fixed32) {
const UnknownField* field = GetField("optional_fixed32");
ASSERT_TRUE(field != NULL);
- ASSERT_EQ(1, field->fixed32_size());
- EXPECT_EQ(all_fields_.optional_fixed32(), field->fixed32(0));
+ ASSERT_EQ(UnknownField::TYPE_FIXED32, field->type());
+ EXPECT_EQ(all_fields_.optional_fixed32(), field->fixed32());
}
TEST_F(UnknownFieldSetTest, Fixed64) {
const UnknownField* field = GetField("optional_fixed64");
ASSERT_TRUE(field != NULL);
- ASSERT_EQ(1, field->fixed64_size());
- EXPECT_EQ(all_fields_.optional_fixed64(), field->fixed64(0));
+ ASSERT_EQ(UnknownField::TYPE_FIXED64, field->type());
+ EXPECT_EQ(all_fields_.optional_fixed64(), field->fixed64());
}
TEST_F(UnknownFieldSetTest, LengthDelimited) {
const UnknownField* field = GetField("optional_string");
ASSERT_TRUE(field != NULL);
- ASSERT_EQ(1, field->length_delimited_size());
- EXPECT_EQ(all_fields_.optional_string(), field->length_delimited(0));
+ ASSERT_EQ(UnknownField::TYPE_LENGTH_DELIMITED, field->type());
+ EXPECT_EQ(all_fields_.optional_string(), field->length_delimited());
}
TEST_F(UnknownFieldSetTest, Group) {
const UnknownField* field = GetField("optionalgroup");
ASSERT_TRUE(field != NULL);
- ASSERT_EQ(1, field->group_size());
- EXPECT_EQ(1, field->group(0).field_count());
+ ASSERT_EQ(UnknownField::TYPE_GROUP, field->type());
+ ASSERT_EQ(1, field->group().field_count());
- const UnknownField& nested_field = field->group(0).field(0);
+ const UnknownField& nested_field = field->group().field(0);
const FieldDescriptor* nested_field_descriptor =
unittest::TestAllTypes::OptionalGroup::descriptor()->FindFieldByName("a");
ASSERT_TRUE(nested_field_descriptor != NULL);
EXPECT_EQ(nested_field_descriptor->number(), nested_field.number());
- EXPECT_EQ(all_fields_.optionalgroup().a(), nested_field.varint(0));
+ ASSERT_EQ(UnknownField::TYPE_VARINT, nested_field.type());
+ EXPECT_EQ(all_fields_.optionalgroup().a(), nested_field.varint());
+}
+
+TEST_F(UnknownFieldSetTest, SerializeFastAndSlowAreEquivalent) {
+ int size = WireFormat::ComputeUnknownFieldsSize(
+ empty_message_.unknown_fields());
+ string slow_buffer;
+ string fast_buffer;
+ slow_buffer.resize(size);
+ fast_buffer.resize(size);
+
+ uint8* target = reinterpret_cast<uint8*>(string_as_array(&fast_buffer));
+ uint8* result = WireFormat::SerializeUnknownFieldsToArray(
+ empty_message_.unknown_fields(), target);
+ EXPECT_EQ(size, result - target);
+
+ {
+ io::ArrayOutputStream raw_stream(string_as_array(&slow_buffer), size, 1);
+ io::CodedOutputStream output_stream(&raw_stream);
+ WireFormat::SerializeUnknownFields(empty_message_.unknown_fields(),
+ &output_stream);
+ ASSERT_FALSE(output_stream.HadError());
+ }
+ EXPECT_TRUE(fast_buffer == slow_buffer);
}
TEST_F(UnknownFieldSetTest, Serialize) {
@@ -205,8 +236,8 @@ TEST_F(UnknownFieldSetTest, SerializeViaReflection) {
io::StringOutputStream raw_output(&data);
io::CodedOutputStream output(&raw_output);
int size = WireFormat::ByteSize(empty_message_);
- ASSERT_TRUE(
- WireFormat::SerializeWithCachedSizes(empty_message_, size, &output));
+ WireFormat::SerializeWithCachedSizes(empty_message_, size, &output);
+ ASSERT_FALSE(output.HadError());
}
// Don't use EXPECT_EQ because we don't want to dump raw binary data to
@@ -249,10 +280,10 @@ TEST_F(UnknownFieldSetTest, SwapWithSelf) {
TEST_F(UnknownFieldSetTest, MergeFrom) {
unittest::TestEmptyMessage source, destination;
- destination.mutable_unknown_fields()->AddField(1)->add_varint(1);
- destination.mutable_unknown_fields()->AddField(3)->add_varint(2);
- source.mutable_unknown_fields()->AddField(2)->add_varint(3);
- source.mutable_unknown_fields()->AddField(3)->add_varint(4);
+ destination.mutable_unknown_fields()->AddVarint(1, 1);
+ destination.mutable_unknown_fields()->AddVarint(3, 2);
+ source.mutable_unknown_fields()->AddVarint(2, 3);
+ source.mutable_unknown_fields()->AddVarint(3, 4);
destination.MergeFrom(source);
@@ -261,34 +292,22 @@ TEST_F(UnknownFieldSetTest, MergeFrom) {
// and merging, above.
"1: 1\n"
"3: 2\n"
- "3: 4\n"
- "2: 3\n",
+ "2: 3\n"
+ "3: 4\n",
destination.DebugString());
}
TEST_F(UnknownFieldSetTest, Clear) {
- // Get a pointer to a contained field object.
- const UnknownField* field = GetField("optional_int32");
- ASSERT_TRUE(field != NULL);
- ASSERT_EQ(1, field->varint_size());
- int number = field->number();
-
// Clear the set.
empty_message_.Clear();
EXPECT_EQ(0, unknown_fields_->field_count());
-
- // If we add that field again we should get the same object.
- ASSERT_EQ(field, unknown_fields_->AddField(number));
-
- // But it should be cleared.
- EXPECT_EQ(0, field->varint_size());
}
TEST_F(UnknownFieldSetTest, ParseKnownAndUnknown) {
// Test mixing known and unknown fields when parsing.
unittest::TestEmptyMessage source;
- source.mutable_unknown_fields()->AddField(123456)->add_varint(654321);
+ source.mutable_unknown_fields()->AddVarint(123456, 654321);
string data;
ASSERT_TRUE(source.SerializeToString(&data));
@@ -297,8 +316,9 @@ TEST_F(UnknownFieldSetTest, ParseKnownAndUnknown) {
TestUtil::ExpectAllFieldsSet(destination);
ASSERT_EQ(1, destination.unknown_fields().field_count());
- ASSERT_EQ(1, destination.unknown_fields().field(0).varint_size());
- EXPECT_EQ(654321, destination.unknown_fields().field(0).varint(0));
+ ASSERT_EQ(UnknownField::TYPE_VARINT,
+ destination.unknown_fields().field(0).type());
+ EXPECT_EQ(654321, destination.unknown_fields().field(0).varint());
}
TEST_F(UnknownFieldSetTest, WrongTypeTreatedAsUnknown) {
@@ -384,16 +404,12 @@ TEST_F(UnknownFieldSetTest, UnknownEnumValue) {
{
TestEmptyMessage empty_message;
UnknownFieldSet* unknown_fields = empty_message.mutable_unknown_fields();
- UnknownField* singular_unknown_field =
- unknown_fields->AddField(singular_field->number());
- singular_unknown_field->add_varint(TestAllTypes::BAR);
- singular_unknown_field->add_varint(5); // not valid
- UnknownField* repeated_unknown_field =
- unknown_fields->AddField(repeated_field->number());
- repeated_unknown_field->add_varint(TestAllTypes::FOO);
- repeated_unknown_field->add_varint(4); // not valid
- repeated_unknown_field->add_varint(TestAllTypes::BAZ);
- repeated_unknown_field->add_varint(6); // not valid
+ unknown_fields->AddVarint(singular_field->number(), TestAllTypes::BAR);
+ unknown_fields->AddVarint(singular_field->number(), 5); // not valid
+ unknown_fields->AddVarint(repeated_field->number(), TestAllTypes::FOO);
+ unknown_fields->AddVarint(repeated_field->number(), 4); // not valid
+ unknown_fields->AddVarint(repeated_field->number(), TestAllTypes::BAZ);
+ unknown_fields->AddVarint(repeated_field->number(), 6); // not valid
empty_message.SerializeToString(&data);
}
@@ -406,18 +422,19 @@ TEST_F(UnknownFieldSetTest, UnknownEnumValue) {
EXPECT_EQ(TestAllTypes::BAZ, message.repeated_nested_enum(1));
const UnknownFieldSet& unknown_fields = message.unknown_fields();
- ASSERT_EQ(2, unknown_fields.field_count());
-
- const UnknownField& singular_unknown_field = unknown_fields.field(0);
- ASSERT_EQ(singular_field->number(), singular_unknown_field.number());
- ASSERT_EQ(1, singular_unknown_field.varint_size());
- EXPECT_EQ(5, singular_unknown_field.varint(0));
-
- const UnknownField& repeated_unknown_field = unknown_fields.field(1);
- ASSERT_EQ(repeated_field->number(), repeated_unknown_field.number());
- ASSERT_EQ(2, repeated_unknown_field.varint_size());
- EXPECT_EQ(4, repeated_unknown_field.varint(0));
- EXPECT_EQ(6, repeated_unknown_field.varint(1));
+ ASSERT_EQ(3, unknown_fields.field_count());
+
+ EXPECT_EQ(singular_field->number(), unknown_fields.field(0).number());
+ ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(0).type());
+ EXPECT_EQ(5, unknown_fields.field(0).varint());
+
+ EXPECT_EQ(repeated_field->number(), unknown_fields.field(1).number());
+ ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(1).type());
+ EXPECT_EQ(4, unknown_fields.field(1).varint());
+
+ EXPECT_EQ(repeated_field->number(), unknown_fields.field(2).number());
+ ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(2).type());
+ EXPECT_EQ(6, unknown_fields.field(2).varint());
}
{
@@ -435,173 +452,61 @@ TEST_F(UnknownFieldSetTest, UnknownEnumValue) {
message.GetExtension(repeated_nested_enum_extension, 1));
const UnknownFieldSet& unknown_fields = message.unknown_fields();
- ASSERT_EQ(2, unknown_fields.field_count());
-
- const UnknownField& singular_unknown_field = unknown_fields.field(0);
- ASSERT_EQ(singular_field->number(), singular_unknown_field.number());
- ASSERT_EQ(1, singular_unknown_field.varint_size());
- EXPECT_EQ(5, singular_unknown_field.varint(0));
-
- const UnknownField& repeated_unknown_field = unknown_fields.field(1);
- ASSERT_EQ(repeated_field->number(), repeated_unknown_field.number());
- ASSERT_EQ(2, repeated_unknown_field.varint_size());
- EXPECT_EQ(4, repeated_unknown_field.varint(0));
- EXPECT_EQ(6, repeated_unknown_field.varint(1));
- }
-}
+ ASSERT_EQ(3, unknown_fields.field_count());
-TEST_F(UnknownFieldSetTest, SpaceUsedExcludingSelf) {
- {
- // Make sure an unknown field set has zero space used until a field is
- // actually added.
- unittest::TestEmptyMessage empty_message;
- const int empty_message_size = empty_message.SpaceUsed();
- UnknownFieldSet* unknown_fields = empty_message.mutable_unknown_fields();
- EXPECT_EQ(empty_message_size, empty_message.SpaceUsed());
- unknown_fields->AddField(1)->add_varint(0);
- EXPECT_LT(empty_message_size, empty_message.SpaceUsed());
- }
- {
- // Test varints.
- UnknownFieldSet unknown_fields;
- UnknownField* field = unknown_fields.AddField(1);
- const int base_size = unknown_fields.SpaceUsedExcludingSelf();
- for (int i = 0; i < 16; ++i) {
- field->add_varint(i);
- }
- // Should just defer computation to the RepeatedField.
- int expected_size = base_size + field->varint().SpaceUsedExcludingSelf();
- EXPECT_EQ(expected_size, unknown_fields.SpaceUsedExcludingSelf());
- }
- {
- // Test fixed32s.
- UnknownFieldSet unknown_fields;
- UnknownField* field = unknown_fields.AddField(1);
- const int base_size = unknown_fields.SpaceUsedExcludingSelf();
- for (int i = 0; i < 16; ++i) {
- field->add_fixed32(i);
- }
- int expected_size = base_size + field->fixed32().SpaceUsedExcludingSelf();
- EXPECT_EQ(expected_size, unknown_fields.SpaceUsedExcludingSelf());
- }
- {
- // Test fixed64s.
- UnknownFieldSet unknown_fields;
- UnknownField* field = unknown_fields.AddField(1);
- const int base_size = unknown_fields.SpaceUsedExcludingSelf();
- for (int i = 0; i < 16; ++i) {
- field->add_fixed64(i);
- }
- int expected_size = base_size + field->fixed64().SpaceUsedExcludingSelf();
- EXPECT_EQ(expected_size, unknown_fields.SpaceUsedExcludingSelf());
- }
- {
- // Test length-delimited types.
- UnknownFieldSet unknown_fields;
- UnknownField* field = unknown_fields.AddField(1);
- const int base_size = unknown_fields.SpaceUsedExcludingSelf();
- for (int i = 0; i < 16; ++i) {
- field->add_length_delimited()->assign("my length delimited string");
- }
- int expected_size = base_size +
- field->length_delimited().SpaceUsedExcludingSelf();
- EXPECT_EQ(expected_size, unknown_fields.SpaceUsedExcludingSelf());
+ EXPECT_EQ(singular_field->number(), unknown_fields.field(0).number());
+ ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(0).type());
+ EXPECT_EQ(5, unknown_fields.field(0).varint());
+
+ EXPECT_EQ(repeated_field->number(), unknown_fields.field(1).number());
+ ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(1).type());
+ EXPECT_EQ(4, unknown_fields.field(1).varint());
+
+ EXPECT_EQ(repeated_field->number(), unknown_fields.field(2).number());
+ ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(2).type());
+ EXPECT_EQ(6, unknown_fields.field(2).varint());
}
}
TEST_F(UnknownFieldSetTest, SpaceUsed) {
- UnknownFieldSet unknown_fields;
- const int expected_size = sizeof(unknown_fields) +
- unknown_fields.SpaceUsedExcludingSelf();
- EXPECT_EQ(expected_size, unknown_fields.SpaceUsed());
+ unittest::TestEmptyMessage empty_message;
+
+ // Make sure an unknown field set has zero space used until a field is
+ // actually added.
+ int base_size = empty_message.SpaceUsed();
+ UnknownFieldSet* unknown_fields = empty_message.mutable_unknown_fields();
+ EXPECT_EQ(base_size, empty_message.SpaceUsed());
+
+ // Make sure each thing we add to the set increases the SpaceUsed().
+ unknown_fields->AddVarint(1, 0);
+ EXPECT_LT(base_size, empty_message.SpaceUsed());
+ base_size = empty_message.SpaceUsed();
+
+ string* str = unknown_fields->AddLengthDelimited(1);
+ EXPECT_LT(base_size, empty_message.SpaceUsed());
+ base_size = empty_message.SpaceUsed();
+
+ str->assign(sizeof(string) + 1, 'x');
+ EXPECT_LT(base_size, empty_message.SpaceUsed());
+ base_size = empty_message.SpaceUsed();
+
+ UnknownFieldSet* group = unknown_fields->AddGroup(1);
+ EXPECT_LT(base_size, empty_message.SpaceUsed());
+ base_size = empty_message.SpaceUsed();
+
+ group->AddVarint(1, 0);
+ EXPECT_LT(base_size, empty_message.SpaceUsed());
}
TEST_F(UnknownFieldSetTest, Empty) {
UnknownFieldSet unknown_fields;
EXPECT_TRUE(unknown_fields.empty());
- unknown_fields.AddField(6)->add_varint(123);
+ unknown_fields.AddVarint(6, 123);
EXPECT_FALSE(unknown_fields.empty());
unknown_fields.Clear();
EXPECT_TRUE(unknown_fields.empty());
}
-TEST_F(UnknownFieldSetTest, FieldEmpty) {
- UnknownFieldSet unknown_fields;
- UnknownField* field = unknown_fields.AddField(1);
-
- EXPECT_TRUE(field->empty());
-
- field->add_varint(1);
- EXPECT_FALSE(field->empty());
- field->Clear();
- EXPECT_TRUE(field->empty());
-
- field->add_fixed32(1);
- EXPECT_FALSE(field->empty());
- field->Clear();
- EXPECT_TRUE(field->empty());
-
- field->add_fixed64(1);
- EXPECT_FALSE(field->empty());
- field->Clear();
- EXPECT_TRUE(field->empty());
-
- field->add_length_delimited("foo");
- EXPECT_FALSE(field->empty());
- field->Clear();
- EXPECT_TRUE(field->empty());
-
- field->add_group();
- EXPECT_FALSE(field->empty());
- field->Clear();
- EXPECT_TRUE(field->empty());
-}
-
-TEST_F(UnknownFieldSetTest, Iterator) {
- UnknownFieldSet unknown_fields;
- EXPECT_TRUE(unknown_fields.begin() == unknown_fields.end());
-
- // Populate the UnknownFieldSet with some inactive fields by adding some
- // fields and then clearing.
- unknown_fields.AddField(6);
- unknown_fields.AddField(4);
- unknown_fields.Clear();
-
- // Add a bunch of "active" fields.
- UnknownField* a = unknown_fields.AddField(5);
- unknown_fields.AddField(3);
- unknown_fields.AddField(9);
- unknown_fields.AddField(1);
- UnknownField* b = unknown_fields.AddField(2);
-
- // Only make some of them non-empty.
- a->add_varint(1);
- b->add_length_delimited("foo");
-
- // Iterate!
- {
- UnknownFieldSet::iterator iter = unknown_fields.begin();
- ASSERT_TRUE(iter != unknown_fields.end());
- EXPECT_EQ(b, &*iter);
- ++iter;
- ASSERT_TRUE(iter != unknown_fields.end());
- EXPECT_EQ(a, &*iter);
- ++iter;
- EXPECT_TRUE(iter == unknown_fields.end());
- }
-
- {
- UnknownFieldSet::const_iterator iter = unknown_fields.begin();
- ASSERT_TRUE(iter != unknown_fields.end());
- EXPECT_EQ(b, &*iter);
- ++iter;
- ASSERT_TRUE(iter != unknown_fields.end());
- EXPECT_EQ(a, &*iter);
- ++iter;
- EXPECT_TRUE(iter == unknown_fields.end());
- }
-}
-
} // namespace
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index aeea3ccb..dbd39b83 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -109,29 +109,29 @@ WireFormat::kWireTypeForFieldType[FieldDescriptor::MAX_TYPE + 1] = {
bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag,
UnknownFieldSet* unknown_fields) {
- UnknownField* field = (unknown_fields == NULL) ? NULL :
- unknown_fields->AddField(GetTagFieldNumber(tag));
+ int number = GetTagFieldNumber(tag);
switch (GetTagWireType(tag)) {
case WIRETYPE_VARINT: {
uint64 value;
if (!input->ReadVarint64(&value)) return false;
- if (field != NULL) field->add_varint(value);
+ if (unknown_fields != NULL) unknown_fields->AddVarint(number, value);
return true;
}
case WIRETYPE_FIXED64: {
uint64 value;
if (!input->ReadLittleEndian64(&value)) return false;
- if (field != NULL) field->add_fixed64(value);
+ if (unknown_fields != NULL) unknown_fields->AddFixed64(number, value);
return true;
}
case WIRETYPE_LENGTH_DELIMITED: {
uint32 length;
if (!input->ReadVarint32(&length)) return false;
- if (field == NULL) {
+ if (unknown_fields == NULL) {
if (!input->Skip(length)) return false;
} else {
- if (!input->ReadString(field->add_length_delimited(), length)) {
+ if (!input->ReadString(unknown_fields->AddLengthDelimited(number),
+ length)) {
return false;
}
}
@@ -139,7 +139,8 @@ bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag,
}
case WIRETYPE_START_GROUP: {
if (!input->IncrementRecursionDepth()) return false;
- if (!SkipMessage(input, (field == NULL) ? NULL : field->add_group())) {
+ if (!SkipMessage(input, (unknown_fields == NULL) ?
+ NULL : unknown_fields->AddGroup(number))) {
return false;
}
input->DecrementRecursionDepth();
@@ -156,7 +157,7 @@ bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag,
case WIRETYPE_FIXED32: {
uint32 value;
if (!input->ReadLittleEndian32(&value)) return false;
- if (field != NULL) field->add_fixed32(value);
+ if (unknown_fields != NULL) unknown_fields->AddFixed32(number, value);
return true;
}
default: {
@@ -185,72 +186,130 @@ bool WireFormat::SkipMessage(io::CodedInputStream* input,
}
}
-bool WireFormat::SerializeUnknownFields(const UnknownFieldSet& unknown_fields,
+void WireFormat::SerializeUnknownFields(const UnknownFieldSet& unknown_fields,
io::CodedOutputStream* output) {
for (int i = 0; i < unknown_fields.field_count(); i++) {
const UnknownField& field = unknown_fields.field(i);
-
-#define DO(EXPRESSION) if (!(EXPRESSION)) return false
- for (int j = 0; j < field.varint_size(); j++) {
- DO(output->WriteVarint32(MakeTag(field.number(), WIRETYPE_VARINT)));
- DO(output->WriteVarint64(field.varint(j)));
- }
- for (int j = 0; j < field.fixed32_size(); j++) {
- DO(output->WriteVarint32(MakeTag(field.number(), WIRETYPE_FIXED32)));
- DO(output->WriteLittleEndian32(field.fixed32(j)));
- }
- for (int j = 0; j < field.fixed64_size(); j++) {
- DO(output->WriteVarint32(MakeTag(field.number(), WIRETYPE_FIXED64)));
- DO(output->WriteLittleEndian64(field.fixed64(j)));
- }
- for (int j = 0; j < field.length_delimited_size(); j++) {
- DO(output->WriteVarint32(
- MakeTag(field.number(), WIRETYPE_LENGTH_DELIMITED)));
- DO(output->WriteVarint32(field.length_delimited(j).size()));
- DO(output->WriteString(field.length_delimited(j)));
- }
- for (int j = 0; j < field.group_size(); j++) {
- DO(output->WriteVarint32(MakeTag(field.number(), WIRETYPE_START_GROUP)));
- DO(SerializeUnknownFields(field.group(j), output));
- DO(output->WriteVarint32(MakeTag(field.number(), WIRETYPE_END_GROUP)));
+ switch (field.type()) {
+ case UnknownField::TYPE_VARINT:
+ output->WriteVarint32(MakeTag(field.number(), WIRETYPE_VARINT));
+ output->WriteVarint64(field.varint());
+ break;
+ case UnknownField::TYPE_FIXED32:
+ output->WriteVarint32(MakeTag(field.number(), WIRETYPE_FIXED32));
+ output->WriteLittleEndian32(field.fixed32());
+ break;
+ case UnknownField::TYPE_FIXED64:
+ output->WriteVarint32(MakeTag(field.number(), WIRETYPE_FIXED64));
+ output->WriteLittleEndian64(field.fixed64());
+ break;
+ case UnknownField::TYPE_LENGTH_DELIMITED:
+ output->WriteVarint32(
+ MakeTag(field.number(), WIRETYPE_LENGTH_DELIMITED));
+ output->WriteVarint32(field.length_delimited().size());
+ output->WriteString(field.length_delimited());
+ break;
+ case UnknownField::TYPE_GROUP:
+ output->WriteVarint32(MakeTag(field.number(),WIRETYPE_START_GROUP));
+ SerializeUnknownFields(field.group(), output);
+ output->WriteVarint32(MakeTag(field.number(), WIRETYPE_END_GROUP));
+ break;
}
-#undef DO
}
+}
- return true;
+uint8* WireFormat::SerializeUnknownFieldsToArray(
+ const UnknownFieldSet& unknown_fields,
+ uint8* target) {
+ for (int i = 0; i < unknown_fields.field_count(); i++) {
+ const UnknownField& field = unknown_fields.field(i);
+
+ switch (field.type()) {
+ case UnknownField::TYPE_VARINT:
+ target = WriteInt64ToArray(field.number(), field.varint(), target);
+ break;
+ case UnknownField::TYPE_FIXED32:
+ target = WriteFixed32ToArray(field.number(), field.fixed32(), target);
+ break;
+ case UnknownField::TYPE_FIXED64:
+ target = WriteFixed64ToArray(field.number(), field.fixed64(), target);
+ break;
+ case UnknownField::TYPE_LENGTH_DELIMITED:
+ target =
+ WriteBytesToArray(field.number(), field.length_delimited(), target);
+ break;
+ case UnknownField::TYPE_GROUP:
+ target = WriteTagToArray(field.number(), WIRETYPE_START_GROUP, target);
+ target = SerializeUnknownFieldsToArray(field.group(), target);
+ target = WriteTagToArray(field.number(), WIRETYPE_END_GROUP, target);
+ break;
+ }
+ }
+ return target;
}
-bool WireFormat::SerializeUnknownMessageSetItems(
+void WireFormat::SerializeUnknownMessageSetItems(
const UnknownFieldSet& unknown_fields,
io::CodedOutputStream* output) {
for (int i = 0; i < unknown_fields.field_count(); i++) {
const UnknownField& field = unknown_fields.field(i);
+ // The only unknown fields that are allowed to exist in a MessageSet are
+ // messages, which are length-delimited.
+ if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) {
+ const string& data = field.length_delimited();
+
+ // Start group.
+ output->WriteVarint32(kMessageSetItemStartTag);
+
+ // Write type ID.
+ output->WriteVarint32(kMessageSetTypeIdTag);
+ output->WriteVarint32(field.number());
+
+ // Write message.
+ output->WriteVarint32(kMessageSetMessageTag);
+ output->WriteVarint32(data.size());
+ output->WriteString(data);
+
+ // End group.
+ output->WriteVarint32(kMessageSetItemEndTag);
+ }
+ }
+}
+
+uint8* WireFormat::SerializeUnknownMessageSetItemsToArray(
+ const UnknownFieldSet& unknown_fields,
+ uint8* target) {
+ for (int i = 0; i < unknown_fields.field_count(); i++) {
+ const UnknownField& field = unknown_fields.field(i);
-#define DO(EXPRESSION) if (!(EXPRESSION)) return false
// The only unknown fields that are allowed to exist in a MessageSet are
// messages, which are length-delimited.
- for (int j = 0; j < field.length_delimited_size(); j++) {
- const string& data = field.length_delimited(j);
+ if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) {
+ const string& data = field.length_delimited();
// Start group.
- DO(output->WriteVarint32(kMessageSetItemStartTag));
+ target =
+ io::CodedOutputStream::WriteTagToArray(kMessageSetItemStartTag, target);
// Write type ID.
- DO(output->WriteVarint32(kMessageSetTypeIdTag));
- DO(output->WriteVarint32(field.number()));
+ target =
+ io::CodedOutputStream::WriteTagToArray(kMessageSetTypeIdTag, target);
+ target =
+ io::CodedOutputStream::WriteVarint32ToArray(field.number(), target);
// Write message.
- DO(output->WriteVarint32(kMessageSetMessageTag));
- DO(output->WriteVarint32(data.size()));
- DO(output->WriteString(data));
+ target =
+ io::CodedOutputStream::WriteTagToArray(kMessageSetMessageTag, target);
+ target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target);
+ target = io::CodedOutputStream::WriteStringToArray(data, target);
// End group.
- DO(output->WriteVarint32(kMessageSetItemEndTag));
+ target =
+ io::CodedOutputStream::WriteTagToArray(kMessageSetItemEndTag, target);
}
-#undef DO
}
- return true;
+ return target;
}
int WireFormat::ComputeUnknownFieldsSize(
@@ -259,34 +318,36 @@ int WireFormat::ComputeUnknownFieldsSize(
for (int i = 0; i < unknown_fields.field_count(); i++) {
const UnknownField& field = unknown_fields.field(i);
- for (int j = 0; j < field.varint_size(); j++) {
- size += io::CodedOutputStream::VarintSize32(
- MakeTag(field.number(), WIRETYPE_VARINT));
- size += io::CodedOutputStream::VarintSize64(field.varint(j));
- }
- for (int j = 0; j < field.fixed32_size(); j++) {
- size += io::CodedOutputStream::VarintSize32(
- MakeTag(field.number(), WIRETYPE_FIXED32));
- size += sizeof(int32);
- }
- for (int j = 0; j < field.fixed64_size(); j++) {
- size += io::CodedOutputStream::VarintSize32(
- MakeTag(field.number(), WIRETYPE_FIXED64));
- size += sizeof(int64);
- }
- for (int j = 0; j < field.length_delimited_size(); j++) {
- size += io::CodedOutputStream::VarintSize32(
- MakeTag(field.number(), WIRETYPE_LENGTH_DELIMITED));
- size += io::CodedOutputStream::VarintSize32(
- field.length_delimited(j).size());
- size += field.length_delimited(j).size();
- }
- for (int j = 0; j < field.group_size(); j++) {
- size += io::CodedOutputStream::VarintSize32(
- MakeTag(field.number(), WIRETYPE_START_GROUP));
- size += ComputeUnknownFieldsSize(field.group(j));
- size += io::CodedOutputStream::VarintSize32(
- MakeTag(field.number(), WIRETYPE_END_GROUP));
+ switch (field.type()) {
+ case UnknownField::TYPE_VARINT:
+ size += io::CodedOutputStream::VarintSize32(
+ MakeTag(field.number(), WIRETYPE_VARINT));
+ size += io::CodedOutputStream::VarintSize64(field.varint());
+ break;
+ case UnknownField::TYPE_FIXED32:
+ size += io::CodedOutputStream::VarintSize32(
+ MakeTag(field.number(), WIRETYPE_FIXED32));
+ size += sizeof(int32);
+ break;
+ case UnknownField::TYPE_FIXED64:
+ size += io::CodedOutputStream::VarintSize32(
+ MakeTag(field.number(), WIRETYPE_FIXED64));
+ size += sizeof(int64);
+ break;
+ case UnknownField::TYPE_LENGTH_DELIMITED:
+ size += io::CodedOutputStream::VarintSize32(
+ MakeTag(field.number(), WIRETYPE_LENGTH_DELIMITED));
+ size += io::CodedOutputStream::VarintSize32(
+ field.length_delimited().size());
+ size += field.length_delimited().size();
+ break;
+ case UnknownField::TYPE_GROUP:
+ size += io::CodedOutputStream::VarintSize32(
+ MakeTag(field.number(), WIRETYPE_START_GROUP));
+ size += ComputeUnknownFieldsSize(field.group());
+ size += io::CodedOutputStream::VarintSize32(
+ MakeTag(field.number(), WIRETYPE_END_GROUP));
+ break;
}
}
@@ -301,12 +362,12 @@ int WireFormat::ComputeUnknownMessageSetItemsSize(
// The only unknown fields that are allowed to exist in a MessageSet are
// messages, which are length-delimited.
- for (int j = 0; j < field.length_delimited_size(); j++) {
+ if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) {
size += kMessageSetItemTagsSize;
size += io::CodedOutputStream::VarintSize32(field.number());
size += io::CodedOutputStream::VarintSize32(
- field.length_delimited(j).size());
- size += field.length_delimited(j).size();
+ field.length_delimited().size());
+ size += field.length_delimited().size();
}
}
@@ -487,8 +548,8 @@ bool WireFormat::ParseAndMergeField(
// UnknownFieldSet.
int64 sign_extended_value = static_cast<int64>(value);
message_reflection->MutableUnknownFields(message)
- ->AddField(GetTagFieldNumber(tag))
- ->add_varint(sign_extended_value);
+ ->AddVarint(GetTagFieldNumber(tag),
+ sign_extended_value);
}
break;
}
@@ -607,7 +668,7 @@ bool WireFormat::ParseAndMergeMessageSetItem(
// ===================================================================
-bool WireFormat::SerializeWithCachedSizes(
+void WireFormat::SerializeWithCachedSizes(
const Message& message,
int size, io::CodedOutputStream* output) {
const Descriptor* descriptor = message.GetDescriptor();
@@ -617,32 +678,24 @@ bool WireFormat::SerializeWithCachedSizes(
vector<const FieldDescriptor*> fields;
message_reflection->ListFields(message, &fields);
for (int i = 0; i < fields.size(); i++) {
- if (!SerializeFieldWithCachedSizes(fields[i], message, output)) {
- return false;
- }
+ SerializeFieldWithCachedSizes(fields[i], message, output);
}
if (descriptor->options().message_set_wire_format()) {
- if (!SerializeUnknownMessageSetItems(
- message_reflection->GetUnknownFields(message), output)) {
- return false;
- }
+ SerializeUnknownMessageSetItems(
+ message_reflection->GetUnknownFields(message), output);
} else {
- if (!SerializeUnknownFields(
- message_reflection->GetUnknownFields(message), output)) {
- return false;
- }
+ SerializeUnknownFields(
+ message_reflection->GetUnknownFields(message), output);
}
GOOGLE_CHECK_EQ(output->ByteCount(), expected_endpoint)
<< ": Protocol message serialized to a size different from what was "
"originally expected. Perhaps it was modified by another thread "
"during serialization?";
-
- return true;
}
-bool WireFormat::SerializeFieldWithCachedSizes(
+void WireFormat::SerializeFieldWithCachedSizes(
const FieldDescriptor* field,
const Message& message,
io::CodedOutputStream* output) {
@@ -652,8 +705,8 @@ bool WireFormat::SerializeFieldWithCachedSizes(
field->containing_type()->options().message_set_wire_format() &&
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
!field->is_repeated()) {
- return SerializeMessageSetItemWithCachedSizes(
- field, message, output);
+ SerializeMessageSetItemWithCachedSizes(field, message, output);
+ return;
}
int count = 0;
@@ -666,10 +719,9 @@ bool WireFormat::SerializeFieldWithCachedSizes(
const bool is_packed = field->options().packed();
if (is_packed && count > 0) {
- if (!WriteTag(field->number(), WIRETYPE_LENGTH_DELIMITED, output))
- return false;
+ WriteTag(field->number(), WIRETYPE_LENGTH_DELIMITED, output);
const int data_size = FieldDataOnlyByteSize(field, message);
- if (!output->WriteVarint32(data_size)) return false;
+ output->WriteVarint32(data_size);
}
for (int j = 0; j < count; j++) {
@@ -682,13 +734,9 @@ bool WireFormat::SerializeFieldWithCachedSizes(
message_reflection->Get##CPPTYPE_METHOD( \
message, field); \
if (is_packed) { \
- if (!Write##TYPE_METHOD##NoTag(value, output)) { \
- return false; \
- } \
+ Write##TYPE_METHOD##NoTag(value, output); \
} else { \
- if (!Write##TYPE_METHOD(field->number(), value, output)) { \
- return false; \
- } \
+ Write##TYPE_METHOD(field->number(), value, output); \
} \
break; \
}
@@ -713,15 +761,13 @@ bool WireFormat::SerializeFieldWithCachedSizes(
#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD) \
case FieldDescriptor::TYPE_##TYPE: \
- if (!Write##TYPE_METHOD( \
+ Write##TYPE_METHOD( \
field->number(), \
field->is_repeated() ? \
message_reflection->GetRepeated##CPPTYPE_METHOD( \
message, field, j) : \
message_reflection->Get##CPPTYPE_METHOD(message, field), \
- output)) { \
- return false; \
- } \
+ output); \
break;
HANDLE_TYPE(GROUP , Group , Message)
@@ -733,10 +779,9 @@ bool WireFormat::SerializeFieldWithCachedSizes(
message_reflection->GetRepeatedEnum(message, field, j) :
message_reflection->GetEnum(message, field);
if (is_packed) {
- if (!WriteEnumNoTag(value->number(), output)) return false;
+ WriteEnumNoTag(value->number(), output);
} else {
- if (!WriteEnum(field->number(), value->number(), output))
- return false;
+ WriteEnum(field->number(), value->number(), output);
}
break;
}
@@ -749,7 +794,7 @@ bool WireFormat::SerializeFieldWithCachedSizes(
message_reflection->GetRepeatedStringReference(
message, field, j, &scratch) :
message_reflection->GetStringReference(message, field, &scratch);
- if (!WriteString(field->number(), value, output)) return false;
+ WriteString(field->number(), value, output);
break;
}
@@ -759,39 +804,35 @@ bool WireFormat::SerializeFieldWithCachedSizes(
message_reflection->GetRepeatedStringReference(
message, field, j, &scratch) :
message_reflection->GetStringReference(message, field, &scratch);
- if (!WriteBytes(field->number(), value, output)) return false;
+ WriteBytes(field->number(), value, output);
break;
}
}
}
-
- return true;
}
-bool WireFormat::SerializeMessageSetItemWithCachedSizes(
+void WireFormat::SerializeMessageSetItemWithCachedSizes(
const FieldDescriptor* field,
const Message& message,
io::CodedOutputStream* output) {
const Reflection* message_reflection = message.GetReflection();
// Start group.
- if (!output->WriteVarint32(kMessageSetItemStartTag)) return false;
+ output->WriteVarint32(kMessageSetItemStartTag);
// Write type ID.
- if (!output->WriteVarint32(kMessageSetTypeIdTag)) return false;
- if (!output->WriteVarint32(field->number())) return false;
+ output->WriteVarint32(kMessageSetTypeIdTag);
+ output->WriteVarint32(field->number());
// Write message.
- if (!output->WriteVarint32(kMessageSetMessageTag)) return false;
+ output->WriteVarint32(kMessageSetMessageTag);
const Message& sub_message = message_reflection->GetMessage(message, field);
- if (!output->WriteVarint32(sub_message.GetCachedSize())) return false;
- if (!sub_message.SerializeWithCachedSizes(output)) return false;
+ output->WriteVarint32(sub_message.GetCachedSize());
+ sub_message.SerializeWithCachedSizes(output);
// End group.
- if (!output->WriteVarint32(kMessageSetItemEndTag)) return false;
-
- return true;
+ output->WriteVarint32(kMessageSetItemEndTag);
}
// ===================================================================
diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h
index 9004caaa..963f427a 100644
--- a/src/google/protobuf/wire_format.h
+++ b/src/google/protobuf/wire_format.h
@@ -93,7 +93,7 @@ class LIBPROTOBUF_EXPORT WireFormat {
// a parameter to this procedure.
//
// These return false iff the underlying stream returns a write error.
- static bool SerializeWithCachedSizes(
+ static void SerializeWithCachedSizes(
const Message& message,
int size, io::CodedOutputStream* output);
@@ -119,14 +119,30 @@ class LIBPROTOBUF_EXPORT WireFormat {
UnknownFieldSet* unknown_fields);
// Write the contents of an UnknownFieldSet to the output.
- static bool SerializeUnknownFields(const UnknownFieldSet& unknown_fields,
+ static void SerializeUnknownFields(const UnknownFieldSet& unknown_fields,
io::CodedOutputStream* output);
+ // Same as above, except writing directly to the provided buffer.
+ // Requires that the buffer have sufficient capacity for
+ // ComputeUnknownFieldsSize(unknown_fields).
+ //
+ // Returns a pointer past the last written byte.
+ static uint8* SerializeUnknownFieldsToArray(
+ const UnknownFieldSet& unknown_fields,
+ uint8* target);
// Same thing except for messages that have the message_set_wire_format
// option.
- static bool SerializeUnknownMessageSetItems(
+ static void SerializeUnknownMessageSetItems(
const UnknownFieldSet& unknown_fields,
io::CodedOutputStream* output);
+ // Same as above, except writing directly to the provided buffer.
+ // Requires that the buffer have sufficient capacity for
+ // ComputeUnknownMessageSetItemsSize(unknown_fields).
+ //
+ // Returns a pointer past the last written byte.
+ static uint8* SerializeUnknownMessageSetItemsToArray(
+ const UnknownFieldSet& unknown_fields,
+ uint8* target);
// Compute the size of the UnknownFieldSet on the wire.
static int ComputeUnknownFieldsSize(const UnknownFieldSet& unknown_fields);
@@ -210,7 +226,7 @@ class LIBPROTOBUF_EXPORT WireFormat {
io::CodedInputStream* input);
// Serialize a single field.
- static bool SerializeFieldWithCachedSizes(
+ static void SerializeFieldWithCachedSizes(
const FieldDescriptor* field, // Cannot be NULL
const Message& message,
io::CodedOutputStream* output);
@@ -268,61 +284,139 @@ class LIBPROTOBUF_EXPORT WireFormat {
// Write a tag. The Write*() functions typically include the tag, so
// normally there's no need to call this unless using the Write*NoTag()
// variants.
- static inline bool WriteTag(field_number, WireType type, output) INL;
+ static inline void WriteTag(field_number, WireType type, output) INL;
// Write fields, without tags.
- static inline bool WriteInt32NoTag (int32 value, output) INL;
- static inline bool WriteInt64NoTag (int64 value, output) INL;
- static inline bool WriteUInt32NoTag (uint32 value, output) INL;
- static inline bool WriteUInt64NoTag (uint64 value, output) INL;
- static inline bool WriteSInt32NoTag (int32 value, output) INL;
- static inline bool WriteSInt64NoTag (int64 value, output) INL;
- static inline bool WriteFixed32NoTag (uint32 value, output) INL;
- static inline bool WriteFixed64NoTag (uint64 value, output) INL;
- static inline bool WriteSFixed32NoTag(int32 value, output) INL;
- static inline bool WriteSFixed64NoTag(int64 value, output) INL;
- static inline bool WriteFloatNoTag (float value, output) INL;
- static inline bool WriteDoubleNoTag (double value, output) INL;
- static inline bool WriteBoolNoTag (bool value, output) INL;
- static inline bool WriteEnumNoTag (int value, output) INL;
+ static inline void WriteInt32NoTag (int32 value, output) INL;
+ static inline void WriteInt64NoTag (int64 value, output) INL;
+ static inline void WriteUInt32NoTag (uint32 value, output) INL;
+ static inline void WriteUInt64NoTag (uint64 value, output) INL;
+ static inline void WriteSInt32NoTag (int32 value, output) INL;
+ static inline void WriteSInt64NoTag (int64 value, output) INL;
+ static inline void WriteFixed32NoTag (uint32 value, output) INL;
+ static inline void WriteFixed64NoTag (uint64 value, output) INL;
+ static inline void WriteSFixed32NoTag(int32 value, output) INL;
+ static inline void WriteSFixed64NoTag(int64 value, output) INL;
+ static inline void WriteFloatNoTag (float value, output) INL;
+ static inline void WriteDoubleNoTag (double value, output) INL;
+ static inline void WriteBoolNoTag (bool value, output) INL;
+ static inline void WriteEnumNoTag (int value, output) INL;
// Write fields, including tags.
- static inline bool WriteInt32 (field_number, int32 value, output) INL;
- static inline bool WriteInt64 (field_number, int64 value, output) INL;
- static inline bool WriteUInt32 (field_number, uint32 value, output) INL;
- static inline bool WriteUInt64 (field_number, uint64 value, output) INL;
- static inline bool WriteSInt32 (field_number, int32 value, output) INL;
- static inline bool WriteSInt64 (field_number, int64 value, output) INL;
- static inline bool WriteFixed32 (field_number, uint32 value, output) INL;
- static inline bool WriteFixed64 (field_number, uint64 value, output) INL;
- static inline bool WriteSFixed32(field_number, int32 value, output) INL;
- static inline bool WriteSFixed64(field_number, int64 value, output) INL;
- static inline bool WriteFloat (field_number, float value, output) INL;
- static inline bool WriteDouble (field_number, double value, output) INL;
- static inline bool WriteBool (field_number, bool value, output) INL;
- static inline bool WriteEnum (field_number, int value, output) INL;
-
- static inline bool WriteString(field_number, const string& value, output) INL;
- static inline bool WriteBytes (field_number, const string& value, output) INL;
-
- static inline bool WriteGroup(field_number, const Message& value, output) INL;
- static inline bool WriteMessage(
+ static inline void WriteInt32 (field_number, int32 value, output) INL;
+ static inline void WriteInt64 (field_number, int64 value, output) INL;
+ static inline void WriteUInt32 (field_number, uint32 value, output) INL;
+ static inline void WriteUInt64 (field_number, uint64 value, output) INL;
+ static inline void WriteSInt32 (field_number, int32 value, output) INL;
+ static inline void WriteSInt64 (field_number, int64 value, output) INL;
+ static inline void WriteFixed32 (field_number, uint32 value, output) INL;
+ static inline void WriteFixed64 (field_number, uint64 value, output) INL;
+ static inline void WriteSFixed32(field_number, int32 value, output) INL;
+ static inline void WriteSFixed64(field_number, int64 value, output) INL;
+ static inline void WriteFloat (field_number, float value, output) INL;
+ static inline void WriteDouble (field_number, double value, output) INL;
+ static inline void WriteBool (field_number, bool value, output) INL;
+ static inline void WriteEnum (field_number, int value, output) INL;
+
+ static inline void WriteString(field_number, const string& value, output) INL;
+ static inline void WriteBytes (field_number, const string& value, output) INL;
+
+ static inline void WriteGroup(field_number, const Message& value, output) INL;
+ static inline void WriteMessage(
field_number, const Message& value, output) INL;
// Like above, but de-virtualize the call to SerializeWithCachedSizes(). The
// pointer must point at an instance of MessageType, *not* a subclass (or
// the subclass must not override SerializeWithCachedSizes()).
template<typename MessageType>
- static inline bool WriteGroupNoVirtual(
+ static inline void WriteGroupNoVirtual(
+ field_number, const MessageType& value, output) INL;
+ template<typename MessageType>
+ static inline void WriteMessageNoVirtual(
+ field_number, const MessageType& value, output) INL;
+
+#undef output
+#define output uint8* target
+
+ // Like above, but use only *ToArray methods of CodedOutputStream.
+ static inline uint8* WriteTagToArray(field_number, WireType type, output) INL;
+
+ // Write fields, without tags.
+ static inline uint8* WriteInt32NoTagToArray (int32 value, output) INL;
+ static inline uint8* WriteInt64NoTagToArray (int64 value, output) INL;
+ static inline uint8* WriteUInt32NoTagToArray (uint32 value, output) INL;
+ static inline uint8* WriteUInt64NoTagToArray (uint64 value, output) INL;
+ static inline uint8* WriteSInt32NoTagToArray (int32 value, output) INL;
+ static inline uint8* WriteSInt64NoTagToArray (int64 value, output) INL;
+ static inline uint8* WriteFixed32NoTagToArray (uint32 value, output) INL;
+ static inline uint8* WriteFixed64NoTagToArray (uint64 value, output) INL;
+ static inline uint8* WriteSFixed32NoTagToArray(int32 value, output) INL;
+ static inline uint8* WriteSFixed64NoTagToArray(int64 value, output) INL;
+ static inline uint8* WriteFloatNoTagToArray (float value, output) INL;
+ static inline uint8* WriteDoubleNoTagToArray (double value, output) INL;
+ static inline uint8* WriteBoolNoTagToArray (bool value, output) INL;
+ static inline uint8* WriteEnumNoTagToArray (int value, output) INL;
+
+ // Write fields, including tags.
+ static inline uint8* WriteInt32ToArray(
+ field_number, int32 value, output) INL;
+ static inline uint8* WriteInt64ToArray(
+ field_number, int64 value, output) INL;
+ static inline uint8* WriteUInt32ToArray(
+ field_number, uint32 value, output) INL;
+ static inline uint8* WriteUInt64ToArray(
+ field_number, uint64 value, output) INL;
+ static inline uint8* WriteSInt32ToArray(
+ field_number, int32 value, output) INL;
+ static inline uint8* WriteSInt64ToArray(
+ field_number, int64 value, output) INL;
+ static inline uint8* WriteFixed32ToArray(
+ field_number, uint32 value, output) INL;
+ static inline uint8* WriteFixed64ToArray(
+ field_number, uint64 value, output) INL;
+ static inline uint8* WriteSFixed32ToArray(
+ field_number, int32 value, output) INL;
+ static inline uint8* WriteSFixed64ToArray(
+ field_number, int64 value, output) INL;
+ static inline uint8* WriteFloatToArray(
+ field_number, float value, output) INL;
+ static inline uint8* WriteDoubleToArray(
+ field_number, double value, output) INL;
+ static inline uint8* WriteBoolToArray(
+ field_number, bool value, output) INL;
+ static inline uint8* WriteEnumToArray(
+ field_number, int value, output) INL;
+
+ static inline uint8* WriteStringToArray(
+ field_number, const string& value, output) INL;
+ static inline uint8* WriteBytesToArray(
+ field_number, const string& value, output) INL;
+
+ static inline uint8* WriteGroupToArray(
+ field_number, const Message& value, output) INL;
+ static inline uint8* WriteMessageToArray(
+ field_number, const Message& value, output) INL;
+
+ // Like above, but de-virtualize the call to SerializeWithCachedSizes(). The
+ // pointer must point at an instance of MessageType, *not* a subclass (or
+ // the subclass must not override SerializeWithCachedSizes()).
+ template<typename MessageType>
+ static inline uint8* WriteGroupNoVirtualToArray(
field_number, const MessageType& value, output) INL;
template<typename MessageType>
- static inline bool WriteMessageNoVirtual(
+ static inline uint8* WriteMessageNoVirtualToArray(
field_number, const MessageType& value, output) INL;
+#undef output
+#undef input
+#undef INL
+
// Compute the byte size of a tag. For groups, this includes both the start
// and end tags.
static inline int TagSize(field_number, FieldDescriptor::Type type);
+#undef field_number
+
// Compute the byte size of a field. The XxSize() functions do NOT include
// the tag, so you must also call TagSize(). (This is because, for repeated
// fields, you should only call TagSize() once and multiply it by the element
@@ -358,11 +452,6 @@ class LIBPROTOBUF_EXPORT WireFormat {
template<typename MessageType>
static inline int MessageSizeNoVirtual(const MessageType& value);
-#undef input
-#undef output
-#undef field_number
-#undef INL
-
private:
static const WireType kWireTypeForFieldType[];
@@ -371,7 +460,7 @@ class LIBPROTOBUF_EXPORT WireFormat {
static bool ParseAndMergeMessageSetItem(
io::CodedInputStream* input,
Message* message);
- static bool SerializeMessageSetItemWithCachedSizes(
+ static void SerializeMessageSetItemWithCachedSizes(
const FieldDescriptor* field,
const Message& message,
io::CodedOutputStream* output);
diff --git a/src/google/protobuf/wire_format_inl.h b/src/google/protobuf/wire_format_inl.h
index 451ac11c..69256080 100644
--- a/src/google/protobuf/wire_format_inl.h
+++ b/src/google/protobuf/wire_format_inl.h
@@ -164,7 +164,8 @@ inline bool WireFormat::ReadBytes(io::CodedInputStream* input, string* value) {
}
-inline bool WireFormat::ReadGroup(int field_number, io::CodedInputStream* input,
+inline bool WireFormat::ReadGroup(int field_number,
+ io::CodedInputStream* input,
Message* value) {
if (!input->IncrementRecursionDepth()) return false;
if (!value->MergePartialFromCodedStream(input)) return false;
@@ -175,7 +176,8 @@ inline bool WireFormat::ReadGroup(int field_number, io::CodedInputStream* input,
}
return true;
}
-inline bool WireFormat::ReadMessage(io::CodedInputStream* input, Message* value) {
+inline bool WireFormat::ReadMessage(io::CodedInputStream* input,
+ Message* value) {
uint32 length;
if (!input->ReadVarint32(&length)) return false;
if (!input->IncrementRecursionDepth()) return false;
@@ -220,140 +222,140 @@ inline bool WireFormat::ReadMessageNoVirtual(io::CodedInputStream* input,
// ===================================================================
-inline bool WireFormat::WriteTag(int field_number, WireType type,
+inline void WireFormat::WriteTag(int field_number, WireType type,
io::CodedOutputStream* output) {
- return output->WriteTag(MakeTag(field_number, type));
+ output->WriteTag(MakeTag(field_number, type));
}
-inline bool WireFormat::WriteInt32NoTag(int32 value,
+inline void WireFormat::WriteInt32NoTag(int32 value,
io::CodedOutputStream* output) {
- return output->WriteVarint32SignExtended(value);
+ output->WriteVarint32SignExtended(value);
}
-inline bool WireFormat::WriteInt64NoTag(int64 value,
+inline void WireFormat::WriteInt64NoTag(int64 value,
io::CodedOutputStream* output) {
- return output->WriteVarint64(static_cast<uint64>(value));
+ output->WriteVarint64(static_cast<uint64>(value));
}
-inline bool WireFormat::WriteUInt32NoTag(uint32 value,
+inline void WireFormat::WriteUInt32NoTag(uint32 value,
io::CodedOutputStream* output) {
- return output->WriteVarint32(value);
+ output->WriteVarint32(value);
}
-inline bool WireFormat::WriteUInt64NoTag(uint64 value,
+inline void WireFormat::WriteUInt64NoTag(uint64 value,
io::CodedOutputStream* output) {
- return output->WriteVarint64(value);
+ output->WriteVarint64(value);
}
-inline bool WireFormat::WriteSInt32NoTag(int32 value,
+inline void WireFormat::WriteSInt32NoTag(int32 value,
io::CodedOutputStream* output) {
- return output->WriteVarint32(ZigZagEncode32(value));
+ output->WriteVarint32(ZigZagEncode32(value));
}
-inline bool WireFormat::WriteSInt64NoTag(int64 value,
+inline void WireFormat::WriteSInt64NoTag(int64 value,
io::CodedOutputStream* output) {
- return output->WriteVarint64(ZigZagEncode64(value));
+ output->WriteVarint64(ZigZagEncode64(value));
}
-inline bool WireFormat::WriteFixed32NoTag(uint32 value,
+inline void WireFormat::WriteFixed32NoTag(uint32 value,
io::CodedOutputStream* output) {
- return output->WriteLittleEndian32(value);
+ output->WriteLittleEndian32(value);
}
-inline bool WireFormat::WriteFixed64NoTag(uint64 value,
+inline void WireFormat::WriteFixed64NoTag(uint64 value,
io::CodedOutputStream* output) {
- return output->WriteLittleEndian64(value);
+ output->WriteLittleEndian64(value);
}
-inline bool WireFormat::WriteSFixed32NoTag(int32 value,
+inline void WireFormat::WriteSFixed32NoTag(int32 value,
io::CodedOutputStream* output) {
- return output->WriteLittleEndian32(static_cast<uint32>(value));
+ output->WriteLittleEndian32(static_cast<uint32>(value));
}
-inline bool WireFormat::WriteSFixed64NoTag(int64 value,
+inline void WireFormat::WriteSFixed64NoTag(int64 value,
io::CodedOutputStream* output) {
- return output->WriteLittleEndian64(static_cast<uint64>(value));
+ output->WriteLittleEndian64(static_cast<uint64>(value));
}
-inline bool WireFormat::WriteFloatNoTag(float value,
+inline void WireFormat::WriteFloatNoTag(float value,
io::CodedOutputStream* output) {
- return output->WriteLittleEndian32(EncodeFloat(value));
+ output->WriteLittleEndian32(EncodeFloat(value));
}
-inline bool WireFormat::WriteDoubleNoTag(double value,
+inline void WireFormat::WriteDoubleNoTag(double value,
io::CodedOutputStream* output) {
- return output->WriteLittleEndian64(EncodeDouble(value));
+ output->WriteLittleEndian64(EncodeDouble(value));
}
-inline bool WireFormat::WriteBoolNoTag(bool value,
+inline void WireFormat::WriteBoolNoTag(bool value,
io::CodedOutputStream* output) {
- return output->WriteVarint32(value ? 1 : 0);
+ output->WriteVarint32(value ? 1 : 0);
}
-inline bool WireFormat::WriteEnumNoTag(int value,
+inline void WireFormat::WriteEnumNoTag(int value,
io::CodedOutputStream* output) {
- return output->WriteVarint32SignExtended(value);
+ output->WriteVarint32SignExtended(value);
}
-inline bool WireFormat::WriteInt32(int field_number, int32 value,
+inline void WireFormat::WriteInt32(int field_number, int32 value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- WriteInt32NoTag(value, output);
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteInt32NoTag(value, output);
}
-inline bool WireFormat::WriteInt64(int field_number, int64 value,
+inline void WireFormat::WriteInt64(int field_number, int64 value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- WriteInt64NoTag(value, output);
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteInt64NoTag(value, output);
}
-inline bool WireFormat::WriteUInt32(int field_number, uint32 value,
+inline void WireFormat::WriteUInt32(int field_number, uint32 value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- WriteUInt32NoTag(value, output);
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteUInt32NoTag(value, output);
}
-inline bool WireFormat::WriteUInt64(int field_number, uint64 value,
+inline void WireFormat::WriteUInt64(int field_number, uint64 value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- WriteUInt64NoTag(value, output);
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteUInt64NoTag(value, output);
}
-inline bool WireFormat::WriteSInt32(int field_number, int32 value,
+inline void WireFormat::WriteSInt32(int field_number, int32 value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- WriteSInt32NoTag(value, output);
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteSInt32NoTag(value, output);
}
-inline bool WireFormat::WriteSInt64(int field_number, int64 value,
+inline void WireFormat::WriteSInt64(int field_number, int64 value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- WriteSInt64NoTag(value, output);
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteSInt64NoTag(value, output);
}
-inline bool WireFormat::WriteFixed32(int field_number, uint32 value,
+inline void WireFormat::WriteFixed32(int field_number, uint32 value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_FIXED32, output) &&
- WriteFixed32NoTag(value, output);
+ WriteTag(field_number, WIRETYPE_FIXED32, output);
+ WriteFixed32NoTag(value, output);
}
-inline bool WireFormat::WriteFixed64(int field_number, uint64 value,
+inline void WireFormat::WriteFixed64(int field_number, uint64 value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_FIXED64, output) &&
- WriteFixed64NoTag(value, output);
+ WriteTag(field_number, WIRETYPE_FIXED64, output);
+ WriteFixed64NoTag(value, output);
}
-inline bool WireFormat::WriteSFixed32(int field_number, int32 value,
+inline void WireFormat::WriteSFixed32(int field_number, int32 value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_FIXED32, output) &&
- WriteSFixed32NoTag(value, output);
+ WriteTag(field_number, WIRETYPE_FIXED32, output);
+ WriteSFixed32NoTag(value, output);
}
-inline bool WireFormat::WriteSFixed64(int field_number, int64 value,
+inline void WireFormat::WriteSFixed64(int field_number, int64 value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_FIXED64, output) &&
- WriteSFixed64NoTag(value, output);
+ WriteTag(field_number, WIRETYPE_FIXED64, output);
+ WriteSFixed64NoTag(value, output);
}
-inline bool WireFormat::WriteFloat(int field_number, float value,
+inline void WireFormat::WriteFloat(int field_number, float value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_FIXED32, output) &&
- WriteFloatNoTag(value, output);
+ WriteTag(field_number, WIRETYPE_FIXED32, output);
+ WriteFloatNoTag(value, output);
}
-inline bool WireFormat::WriteDouble(int field_number, double value,
+inline void WireFormat::WriteDouble(int field_number, double value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_FIXED64, output) &&
- WriteDoubleNoTag(value, output);
+ WriteTag(field_number, WIRETYPE_FIXED64, output);
+ WriteDoubleNoTag(value, output);
}
-inline bool WireFormat::WriteBool(int field_number, bool value,
+inline void WireFormat::WriteBool(int field_number, bool value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- WriteBoolNoTag(value, output);
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteBoolNoTag(value, output);
}
-inline bool WireFormat::WriteEnum(int field_number, int value,
+inline void WireFormat::WriteEnum(int field_number, int value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_VARINT, output) &&
- WriteEnumNoTag(value, output);
+ WriteTag(field_number, WIRETYPE_VARINT, output);
+ WriteEnumNoTag(value, output);
}
-inline bool WireFormat::WriteString(int field_number, const string& value,
+inline void WireFormat::WriteString(int field_number, const string& value,
io::CodedOutputStream* output) {
// String is for UTF-8 text only
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
@@ -363,46 +365,256 @@ inline bool WireFormat::WriteString(int field_number, const string& value,
"use the 'bytes' type for raw bytes.";
}
#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
- return WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output) &&
- output->WriteVarint32(value.size()) &&
- output->WriteString(value);
+ WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+ output->WriteVarint32(value.size());
+ output->WriteString(value);
}
-inline bool WireFormat::WriteBytes(int field_number, const string& value,
+inline void WireFormat::WriteBytes(int field_number, const string& value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output) &&
- output->WriteVarint32(value.size()) &&
- output->WriteString(value);
+ WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+ output->WriteVarint32(value.size());
+ output->WriteString(value);
}
-inline bool WireFormat::WriteGroup(int field_number, const Message& value,
+inline void WireFormat::WriteGroup(int field_number, const Message& value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_START_GROUP, output) &&
- value.SerializeWithCachedSizes(output) &&
- WriteTag(field_number, WIRETYPE_END_GROUP, output);
+ WriteTag(field_number, WIRETYPE_START_GROUP, output);
+ value.SerializeWithCachedSizes(output);
+ WriteTag(field_number, WIRETYPE_END_GROUP, output);
}
-inline bool WireFormat::WriteMessage(int field_number, const Message& value,
+inline void WireFormat::WriteMessage(int field_number, const Message& value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output) &&
- output->WriteVarint32(value.GetCachedSize()) &&
- value.SerializeWithCachedSizes(output);
+ WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+ output->WriteVarint32(value.GetCachedSize());
+ value.SerializeWithCachedSizes(output);
}
template<typename MessageType>
-inline bool WireFormat::WriteGroupNoVirtual(
+inline void WireFormat::WriteGroupNoVirtual(
int field_number, const MessageType& value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_START_GROUP, output) &&
- value.MessageType::SerializeWithCachedSizes(output) &&
- WriteTag(field_number, WIRETYPE_END_GROUP, output);
+ WriteTag(field_number, WIRETYPE_START_GROUP, output);
+ value.MessageType::SerializeWithCachedSizes(output);
+ WriteTag(field_number, WIRETYPE_END_GROUP, output);
}
template<typename MessageType>
-inline bool WireFormat::WriteMessageNoVirtual(
+inline void WireFormat::WriteMessageNoVirtual(
int field_number, const MessageType& value,
io::CodedOutputStream* output) {
- return WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output) &&
- output->WriteVarint32(value.MessageType::GetCachedSize()) &&
- value.MessageType::SerializeWithCachedSizes(output);
+ WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output);
+ output->WriteVarint32(value.MessageType::GetCachedSize());
+ value.MessageType::SerializeWithCachedSizes(output);
+}
+
+// ===================================================================
+
+inline uint8* WireFormat::WriteTagToArray(int field_number,
+ WireType type,
+ uint8* target) {
+ return io::CodedOutputStream::WriteTagToArray(MakeTag(field_number, type),
+ target);
+}
+
+inline uint8* WireFormat::WriteInt32NoTagToArray(int32 value, uint8* target) {
+ return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target);
+}
+inline uint8* WireFormat::WriteInt64NoTagToArray(int64 value, uint8* target) {
+ return io::CodedOutputStream::WriteVarint64ToArray(
+ static_cast<uint64>(value), target);
+}
+inline uint8* WireFormat::WriteUInt32NoTagToArray(uint32 value, uint8* target) {
+ return io::CodedOutputStream::WriteVarint32ToArray(value, target);
+}
+inline uint8* WireFormat::WriteUInt64NoTagToArray(uint64 value, uint8* target) {
+ return io::CodedOutputStream::WriteVarint64ToArray(value, target);
+}
+inline uint8* WireFormat::WriteSInt32NoTagToArray(int32 value, uint8* target) {
+ return io::CodedOutputStream::WriteVarint32ToArray(ZigZagEncode32(value),
+ target);
+}
+inline uint8* WireFormat::WriteSInt64NoTagToArray(int64 value, uint8* target) {
+ return io::CodedOutputStream::WriteVarint64ToArray(ZigZagEncode64(value),
+ target);
+}
+inline uint8* WireFormat::WriteFixed32NoTagToArray(uint32 value,
+ uint8* target) {
+ return io::CodedOutputStream::WriteLittleEndian32ToArray(value, target);
+}
+inline uint8* WireFormat::WriteFixed64NoTagToArray(uint64 value,
+ uint8* target) {
+ return io::CodedOutputStream::WriteLittleEndian64ToArray(value, target);
+}
+inline uint8* WireFormat::WriteSFixed32NoTagToArray(int32 value,
+ uint8* target) {
+ return io::CodedOutputStream::WriteLittleEndian32ToArray(
+ static_cast<uint32>(value), target);
+}
+inline uint8* WireFormat::WriteSFixed64NoTagToArray(int64 value,
+ uint8* target) {
+ return io::CodedOutputStream::WriteLittleEndian64ToArray(
+ static_cast<uint64>(value), target);
+}
+inline uint8* WireFormat::WriteFloatNoTagToArray(float value, uint8* target) {
+ return io::CodedOutputStream::WriteLittleEndian32ToArray(EncodeFloat(value),
+ target);
+}
+inline uint8* WireFormat::WriteDoubleNoTagToArray(double value,
+ uint8* target) {
+ return io::CodedOutputStream::WriteLittleEndian64ToArray(EncodeDouble(value),
+ target);
+}
+inline uint8* WireFormat::WriteBoolNoTagToArray(bool value,
+ uint8* target) {
+ return io::CodedOutputStream::WriteVarint32ToArray(value ? 1 : 0, target);
+}
+inline uint8* WireFormat::WriteEnumNoTagToArray(int value,
+ uint8* target) {
+ return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target);
+}
+
+inline uint8* WireFormat::WriteInt32ToArray(int field_number,
+ int32 value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+ return WriteInt32NoTagToArray(value, target);
+}
+inline uint8* WireFormat::WriteInt64ToArray(int field_number,
+ int64 value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+ return WriteInt64NoTagToArray(value, target);
+}
+inline uint8* WireFormat::WriteUInt32ToArray(int field_number,
+ uint32 value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+ return WriteUInt32NoTagToArray(value, target);
+}
+inline uint8* WireFormat::WriteUInt64ToArray(int field_number,
+ uint64 value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+ return WriteUInt64NoTagToArray(value, target);
+}
+inline uint8* WireFormat::WriteSInt32ToArray(int field_number,
+ int32 value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+ return WriteSInt32NoTagToArray(value, target);
+}
+inline uint8* WireFormat::WriteSInt64ToArray(int field_number,
+ int64 value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+ return WriteSInt64NoTagToArray(value, target);
+}
+inline uint8* WireFormat::WriteFixed32ToArray(int field_number,
+ uint32 value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
+ return WriteFixed32NoTagToArray(value, target);
+}
+inline uint8* WireFormat::WriteFixed64ToArray(int field_number,
+ uint64 value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
+ return WriteFixed64NoTagToArray(value, target);
+}
+inline uint8* WireFormat::WriteSFixed32ToArray(int field_number,
+ int32 value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
+ return WriteSFixed32NoTagToArray(value, target);
+}
+inline uint8* WireFormat::WriteSFixed64ToArray(int field_number,
+ int64 value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
+ return WriteSFixed64NoTagToArray(value, target);
+}
+inline uint8* WireFormat::WriteFloatToArray(int field_number,
+ float value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target);
+ return WriteFloatNoTagToArray(value, target);
+}
+inline uint8* WireFormat::WriteDoubleToArray(int field_number,
+ double value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target);
+ return WriteDoubleNoTagToArray(value, target);
+}
+inline uint8* WireFormat::WriteBoolToArray(int field_number,
+ bool value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+ return WriteBoolNoTagToArray(value, target);
+}
+inline uint8* WireFormat::WriteEnumToArray(int field_number,
+ int value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_VARINT, target);
+ return WriteEnumNoTagToArray(value, target);
+}
+
+inline uint8* WireFormat::WriteStringToArray(int field_number,
+ const string& value,
+ uint8* target) {
+ // String is for UTF-8 text only
+#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+ if (!IsStructurallyValidUTF8(value.data(), value.size())) {
+ GOOGLE_LOG(ERROR) << "Encountered string containing invalid UTF-8 data while "
+ "serializing protocol buffer. Strings must contain only UTF-8; "
+ "use the 'bytes' type for raw bytes.";
+ }
+#endif
+ // WARNING: In wire_format.cc, both strings and bytes are handled by
+ // WriteString() to avoid code duplication. If the implementations become
+ // different, you will need to update that usage.
+ target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
+ target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target);
+ return io::CodedOutputStream::WriteStringToArray(value, target);
+}
+inline uint8* WireFormat::WriteBytesToArray(int field_number,
+ const string& value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
+ target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target);
+ return io::CodedOutputStream::WriteStringToArray(value, target);
+}
+
+
+inline uint8* WireFormat::WriteGroupToArray(int field_number,
+ const Message& value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
+ target = value.SerializeWithCachedSizesToArray(target);
+ return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
+}
+inline uint8* WireFormat::WriteMessageToArray(int field_number,
+ const Message& value,
+ uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
+ target = io::CodedOutputStream::WriteVarint32ToArray(
+ value.GetCachedSize(), target);
+ return value.SerializeWithCachedSizesToArray(target);
+}
+
+template<typename MessageType>
+inline uint8* WireFormat::WriteGroupNoVirtualToArray(
+ int field_number, const MessageType& value, uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target);
+ target = value.MessageType::SerializeWithCachedSizesToArray(target);
+ return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target);
+}
+template<typename MessageType>
+inline uint8* WireFormat::WriteMessageNoVirtualToArray(
+ int field_number, const MessageType& value, uint8* target) {
+ target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
+ target = io::CodedOutputStream::WriteVarint32ToArray(
+ value.MessageType::GetCachedSize(), target);
+ return value.MessageType::SerializeWithCachedSizesToArray(target);
}
// ===================================================================
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index 5a7c6c23..1f00a93d 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -44,6 +44,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util-inl.h>
namespace google {
namespace protobuf {
@@ -179,6 +180,7 @@ TEST(WireFormatTest, Serialize) {
io::StringOutputStream raw_output(&generated_data);
io::CodedOutputStream output(&raw_output);
message.SerializeWithCachedSizes(&output);
+ ASSERT_FALSE(output.HadError());
}
// Serialize using WireFormat.
@@ -186,6 +188,7 @@ TEST(WireFormatTest, Serialize) {
io::StringOutputStream raw_output(&dynamic_data);
io::CodedOutputStream output(&raw_output);
WireFormat::SerializeWithCachedSizes(message, size, &output);
+ ASSERT_FALSE(output.HadError());
}
// Should be the same.
@@ -207,6 +210,7 @@ TEST(WireFormatTest, SerializeExtensions) {
io::StringOutputStream raw_output(&generated_data);
io::CodedOutputStream output(&raw_output);
message.SerializeWithCachedSizes(&output);
+ ASSERT_FALSE(output.HadError());
}
// Serialize using WireFormat.
@@ -214,6 +218,7 @@ TEST(WireFormatTest, SerializeExtensions) {
io::StringOutputStream raw_output(&dynamic_data);
io::CodedOutputStream output(&raw_output);
WireFormat::SerializeWithCachedSizes(message, size, &output);
+ ASSERT_FALSE(output.HadError());
}
// Should be the same.
@@ -235,6 +240,7 @@ TEST(WireFormatTest, SerializeFieldsAndExtensions) {
io::StringOutputStream raw_output(&generated_data);
io::CodedOutputStream output(&raw_output);
message.SerializeWithCachedSizes(&output);
+ ASSERT_FALSE(output.HadError());
}
// Serialize using WireFormat.
@@ -242,6 +248,7 @@ TEST(WireFormatTest, SerializeFieldsAndExtensions) {
io::StringOutputStream raw_output(&dynamic_data);
io::CodedOutputStream output(&raw_output);
WireFormat::SerializeWithCachedSizes(message, size, &output);
+ ASSERT_FALSE(output.HadError());
}
// Should be the same.
@@ -287,8 +294,8 @@ TEST(WireFormatTest, SerializeMessageSet) {
unittest::TestMessageSetExtension1::message_set_extension)->set_i(123);
message_set.MutableExtension(
unittest::TestMessageSetExtension2::message_set_extension)->set_str("foo");
- message_set.mutable_unknown_fields()->AddField(kUnknownTypeId)
- ->add_length_delimited("bar");
+ message_set.mutable_unknown_fields()->AddLengthDelimited(
+ kUnknownTypeId, "bar");
string data;
ASSERT_TRUE(message_set.SerializeToString(&data));
@@ -319,6 +326,43 @@ TEST(WireFormatTest, SerializeMessageSet) {
EXPECT_EQ("bar", raw.item(2).message());
}
+TEST(WireFormatTest, SerializeMessageSetToStreamAndArrayAreEqual) {
+ // Serialize a MessageSet to a stream and to a flat array and check that the
+ // results are equal.
+ // Set up a TestMessageSet with two known messages and an unknown one, as
+ // above.
+
+ unittest::TestMessageSet message_set;
+ message_set.MutableExtension(
+ unittest::TestMessageSetExtension1::message_set_extension)->set_i(123);
+ message_set.MutableExtension(
+ unittest::TestMessageSetExtension2::message_set_extension)->set_str("foo");
+ message_set.mutable_unknown_fields()->AddLengthDelimited(
+ kUnknownTypeId, "bar");
+
+ int size = message_set.ByteSize();
+ string flat_data;
+ string stream_data;
+ flat_data.resize(size);
+ stream_data.resize(size);
+ // Serialize to flat array
+ {
+ uint8* target = reinterpret_cast<uint8*>(string_as_array(&flat_data));
+ uint8* end = message_set.SerializeWithCachedSizesToArray(target);
+ EXPECT_EQ(size, end - target);
+ }
+
+ // Serialize to buffer
+ {
+ io::ArrayOutputStream array_stream(string_as_array(&stream_data), size, 1);
+ io::CodedOutputStream output_stream(&array_stream);
+ message_set.SerializeWithCachedSizes(&output_stream);
+ ASSERT_FALSE(output_stream.HadError());
+ }
+
+ EXPECT_TRUE(flat_data == stream_data);
+}
+
TEST(WireFormatTest, ParseMessageSet) {
// Set up a RawMessageSet with two known messages and an unknown one.
unittest::RawMessageSet raw;
@@ -360,8 +404,9 @@ TEST(WireFormatTest, ParseMessageSet) {
unittest::TestMessageSetExtension2::message_set_extension).str());
ASSERT_EQ(1, message_set.unknown_fields().field_count());
- ASSERT_EQ(1, message_set.unknown_fields().field(0).length_delimited_size());
- EXPECT_EQ("bar", message_set.unknown_fields().field(0).length_delimited(0));
+ ASSERT_EQ(UnknownField::TYPE_LENGTH_DELIMITED,
+ message_set.unknown_fields().field(0).type());
+ EXPECT_EQ("bar", message_set.unknown_fields().field(0).length_delimited());
}
TEST(WireFormatTest, RecursionLimit) {
@@ -390,11 +435,11 @@ TEST(WireFormatTest, RecursionLimit) {
TEST(WireFormatTest, UnknownFieldRecursionLimit) {
unittest::TestEmptyMessage message;
message.mutable_unknown_fields()
- ->AddField(1234)->add_group()
- ->AddField(1234)->add_group()
- ->AddField(1234)->add_group()
- ->AddField(1234)->add_group()
- ->AddField(1234)->add_varint(123);
+ ->AddGroup(1234)
+ ->AddGroup(1234)
+ ->AddGroup(1234)
+ ->AddGroup(1234)
+ ->AddVarint(1234, 123);
string data;
message.SerializeToString(&data);
@@ -500,8 +545,7 @@ class WireFormatInvalidInputTest : public testing::Test {
io::StringOutputStream raw_output(&result);
io::CodedOutputStream output(&raw_output);
- EXPECT_TRUE(WireFormat::WriteBytes(
- field->number(), string(bytes, size), &output));
+ WireFormat::WriteBytes(field->number(), string(bytes, size), &output);
}
return result;
@@ -522,12 +566,11 @@ class WireFormatInvalidInputTest : public testing::Test {
io::StringOutputStream raw_output(&result);
io::CodedOutputStream output(&raw_output);
- EXPECT_TRUE(output.WriteVarint32(WireFormat::MakeTag(field)));
- EXPECT_TRUE(output.WriteString(string(bytes, size)));
+ output.WriteVarint32(WireFormat::MakeTag(field));
+ output.WriteString(string(bytes, size));
if (include_end_tag) {
- EXPECT_TRUE(
- output.WriteVarint32(WireFormat::MakeTag(
- field->number(), WireFormat::WIRETYPE_END_GROUP)));
+ output.WriteVarint32(WireFormat::MakeTag(
+ field->number(), WireFormat::WIRETYPE_END_GROUP));
}
}