Merge pull request #3988 from acozzette/down-integrate
Integrated internal changes from Google
This commit is contained in:
commit
9021f623e1
@ -204,6 +204,7 @@ java_EXTRA_DIST=
|
||||
java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java \
|
||||
java/core/src/main/java/com/google/protobuf/AbstractParser.java \
|
||||
java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java \
|
||||
java/core/src/main/java/com/google/protobuf/Android.java \
|
||||
java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java \
|
||||
java/core/src/main/java/com/google/protobuf/BlockingService.java \
|
||||
java/core/src/main/java/com/google/protobuf/BooleanArrayList.java \
|
||||
|
@ -4,6 +4,7 @@ set(libprotobuf_lite_files
|
||||
${protobuf_source_dir}/src/google/protobuf/extension_set.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/generated_message_table_driven_lite.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/generated_message_util.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/implicit_weak_message.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/io/coded_stream.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream.cc
|
||||
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
|
||||
@ -31,6 +32,7 @@ set(libprotobuf_lite_includes
|
||||
${protobuf_source_dir}/src/google/protobuf/arenastring.h
|
||||
${protobuf_source_dir}/src/google/protobuf/extension_set.h
|
||||
${protobuf_source_dir}/src/google/protobuf/generated_message_util.h
|
||||
${protobuf_source_dir}/src/google/protobuf/implicit_weak_message.h
|
||||
${protobuf_source_dir}/src/google/protobuf/io/coded_stream.h
|
||||
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream.h
|
||||
${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream_impl_lite.h
|
||||
|
@ -54,4 +54,3 @@ Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT32
|
||||
Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT64
|
||||
Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT32
|
||||
Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64
|
||||
|
||||
|
@ -44,4 +44,4 @@ Required.Proto3.JsonInput.StringFieldNotAString
|
||||
Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
|
||||
Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
|
||||
Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
|
||||
Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
|
||||
Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
|
||||
|
@ -154,17 +154,18 @@ namespace Google.Protobuf.WellKnownTypes {
|
||||
public const int TypeUrlFieldNumber = 1;
|
||||
private string typeUrl_ = "";
|
||||
/// <summary>
|
||||
/// A URL/resource name whose content describes the type of the
|
||||
/// serialized protocol buffer message.
|
||||
/// A URL/resource name that uniquely identifies the type of the serialized
|
||||
/// protocol buffer message. The last segment of the URL's path must represent
|
||||
/// the fully qualified name of the type (as in
|
||||
/// `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||
/// (e.g., leading "." is not accepted).
|
||||
///
|
||||
/// For URLs which use the scheme `http`, `https`, or no scheme, the
|
||||
/// following restrictions and interpretations apply:
|
||||
/// In practice, teams usually precompile into the binary all types that they
|
||||
/// expect it to use in the context of Any. However, for URLs which use the
|
||||
/// scheme `http`, `https`, or no scheme, one can optionally set up a type
|
||||
/// server that maps type URLs to message definitions as follows:
|
||||
///
|
||||
/// * If no scheme is provided, `https` is assumed.
|
||||
/// * The last segment of the URL's path must represent the fully
|
||||
/// qualified name of the type (as in `path/google.protobuf.Duration`).
|
||||
/// The name should be in a canonical form (e.g., leading "." is
|
||||
/// not accepted).
|
||||
/// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
/// value in binary format, or produce an error.
|
||||
/// * Applications are allowed to cache lookup results based on the
|
||||
@ -173,6 +174,10 @@ namespace Google.Protobuf.WellKnownTypes {
|
||||
/// on changes to types. (Use versioned type names to manage
|
||||
/// breaking changes.)
|
||||
///
|
||||
/// Note: this functionality is not currently available in the official
|
||||
/// protobuf release, and it is not used for type URLs beginning with
|
||||
/// type.googleapis.com.
|
||||
///
|
||||
/// Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
/// used with implementation specific semantics.
|
||||
/// </summary>
|
||||
|
@ -112,8 +112,8 @@ namespace Google.Protobuf.WellKnownTypes {
|
||||
/// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
|
||||
/// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
||||
/// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||
/// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--)
|
||||
/// to obtain a formatter capable of generating timestamps in this format.
|
||||
/// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
|
||||
/// ) to obtain a formatter capable of generating timestamps in this format.
|
||||
/// </summary>
|
||||
public sealed partial class Timestamp : pb::IMessage<Timestamp> {
|
||||
private static readonly pb::MessageParser<Timestamp> _parser = new pb::MessageParser<Timestamp>(() => new Timestamp());
|
||||
|
57
java/core/src/main/java/com/google/protobuf/Android.java
Normal file
57
java/core/src/main/java/com/google/protobuf/Android.java
Normal file
@ -0,0 +1,57 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
final class Android {
|
||||
|
||||
private static final Class<?> MEMORY_CLASS = getClassForName("libcore.io.Memory");
|
||||
private static final boolean IS_ROBOLECTRIC =
|
||||
getClassForName("org.robolectric.Robolectric") != null;
|
||||
|
||||
/** Returns {@code true} if running on an Android device. */
|
||||
static boolean isOnAndroidDevice() {
|
||||
return MEMORY_CLASS != null && !IS_ROBOLECTRIC;
|
||||
}
|
||||
|
||||
/** Returns the memory class or {@code null} if not on Android device. */
|
||||
static Class<?> getMemoryClass() {
|
||||
return MEMORY_CLASS;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> Class<T> getClassForName(String name) {
|
||||
try {
|
||||
return (Class<T>) Class.forName(name);
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -124,14 +124,8 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
|
||||
|
||||
private static final ByteArrayCopier byteArrayCopier;
|
||||
static {
|
||||
boolean isAndroid = true;
|
||||
try {
|
||||
Class.forName("android.content.Context");
|
||||
} catch (ClassNotFoundException e) {
|
||||
isAndroid = false;
|
||||
}
|
||||
|
||||
byteArrayCopier = isAndroid ? new SystemByteArrayCopier() : new ArraysByteArrayCopier();
|
||||
byteArrayCopier =
|
||||
Android.isOnAndroidDevice() ? new SystemByteArrayCopier() : new ArraysByteArrayCopier();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -102,6 +102,11 @@ final class FieldSet<FieldDescriptorType extends
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true);
|
||||
|
||||
/** Returns {@code true} if empty, {@code false} otherwise. */
|
||||
boolean isEmpty() {
|
||||
return fields.isEmpty();
|
||||
}
|
||||
|
||||
/** Make this FieldSet immutable from this point forward. */
|
||||
@SuppressWarnings("unchecked")
|
||||
public void makeImmutable() {
|
||||
|
@ -504,11 +504,8 @@ public abstract class GeneratedMessageLite<
|
||||
extends GeneratedMessageLite<MessageType, BuilderType>
|
||||
implements ExtendableMessageOrBuilder<MessageType, BuilderType> {
|
||||
|
||||
/**
|
||||
* Represents the set of extensions on this message. For use by generated
|
||||
* code only.
|
||||
*/
|
||||
protected FieldSet<ExtensionDescriptor> extensions = FieldSet.newFieldSet();
|
||||
/** Represents the set of extensions on this message. For use by generated code only. */
|
||||
protected FieldSet<ExtensionDescriptor> extensions = FieldSet.emptySet();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected final void mergeExtensionFields(final MessageType other) {
|
||||
@ -578,7 +575,11 @@ public abstract class GeneratedMessageLite<
|
||||
if (unknown) { // Unknown field or wrong wire type. Skip.
|
||||
return parseUnknownField(tag, input);
|
||||
}
|
||||
|
||||
|
||||
if (extensions.isImmutable()) {
|
||||
extensions = extensions.clone();
|
||||
}
|
||||
|
||||
if (packed) {
|
||||
int length = input.readRawVarint32();
|
||||
int limit = input.pushLimit(length);
|
||||
@ -942,12 +943,6 @@ public abstract class GeneratedMessageLite<
|
||||
implements ExtendableMessageOrBuilder<MessageType, BuilderType> {
|
||||
protected ExtendableBuilder(MessageType defaultInstance) {
|
||||
super(defaultInstance);
|
||||
|
||||
// TODO(dweis): This is kind of an unnecessary clone since we construct a
|
||||
// new instance in the parent constructor which makes the extensions
|
||||
// immutable. This extra allocation shouldn't matter in practice
|
||||
// though.
|
||||
instance.extensions = instance.extensions.clone();
|
||||
}
|
||||
|
||||
// For immutable message conversion.
|
||||
@ -966,6 +961,15 @@ public abstract class GeneratedMessageLite<
|
||||
instance.extensions = instance.extensions.clone();
|
||||
}
|
||||
|
||||
private FieldSet<ExtensionDescriptor> ensureExtensionsAreMutable() {
|
||||
FieldSet<ExtensionDescriptor> extensions = instance.extensions;
|
||||
if (extensions.isImmutable()) {
|
||||
extensions = extensions.clone();
|
||||
instance.extensions = extensions;
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final MessageType buildPartial() {
|
||||
if (isBuilt) {
|
||||
@ -1024,7 +1028,8 @@ public abstract class GeneratedMessageLite<
|
||||
|
||||
verifyExtensionContainingType(extensionLite);
|
||||
copyOnWrite();
|
||||
instance.extensions.setField(extensionLite.descriptor, extensionLite.toFieldSetType(value));
|
||||
ensureExtensionsAreMutable()
|
||||
.setField(extensionLite.descriptor, extensionLite.toFieldSetType(value));
|
||||
return (BuilderType) this;
|
||||
}
|
||||
|
||||
@ -1037,8 +1042,9 @@ public abstract class GeneratedMessageLite<
|
||||
|
||||
verifyExtensionContainingType(extensionLite);
|
||||
copyOnWrite();
|
||||
instance.extensions.setRepeatedField(
|
||||
extensionLite.descriptor, index, extensionLite.singularToFieldSetType(value));
|
||||
ensureExtensionsAreMutable()
|
||||
.setRepeatedField(
|
||||
extensionLite.descriptor, index, extensionLite.singularToFieldSetType(value));
|
||||
return (BuilderType) this;
|
||||
}
|
||||
|
||||
@ -1051,8 +1057,8 @@ public abstract class GeneratedMessageLite<
|
||||
|
||||
verifyExtensionContainingType(extensionLite);
|
||||
copyOnWrite();
|
||||
instance.extensions.addRepeatedField(
|
||||
extensionLite.descriptor, extensionLite.singularToFieldSetType(value));
|
||||
ensureExtensionsAreMutable()
|
||||
.addRepeatedField(extensionLite.descriptor, extensionLite.singularToFieldSetType(value));
|
||||
return (BuilderType) this;
|
||||
}
|
||||
|
||||
@ -1063,7 +1069,7 @@ public abstract class GeneratedMessageLite<
|
||||
|
||||
verifyExtensionContainingType(extensionLite);
|
||||
copyOnWrite();
|
||||
instance.extensions.clearField(extensionLite.descriptor);
|
||||
ensureExtensionsAreMutable().clearField(extensionLite.descriptor);
|
||||
return (BuilderType) this;
|
||||
}
|
||||
}
|
||||
|
@ -1223,6 +1223,22 @@ public final class TextFormat {
|
||||
PARSER.merge(input, builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a text-format message from {@code input}.
|
||||
*
|
||||
* @return the parsed message, guaranteed initialized
|
||||
*/
|
||||
public static <T extends Message> T parse(final CharSequence input,
|
||||
final Class<T> protoClass)
|
||||
throws ParseException {
|
||||
Message.Builder builder =
|
||||
Internal.getDefaultInstance(protoClass).newBuilderForType();
|
||||
merge(input, builder);
|
||||
@SuppressWarnings("unchecked")
|
||||
T output = (T) builder.build();
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a text-format message from {@code input} and merge the contents
|
||||
* into {@code builder}. Extensions will be recognized if they are
|
||||
@ -1248,6 +1264,25 @@ public final class TextFormat {
|
||||
PARSER.merge(input, extensionRegistry, builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a text-format message from {@code input}. Extensions will be
|
||||
* recognized if they are registered in {@code extensionRegistry}.
|
||||
*
|
||||
* @return the parsed message, guaranteed initialized
|
||||
*/
|
||||
public static <T extends Message> T parse(
|
||||
final CharSequence input,
|
||||
final ExtensionRegistry extensionRegistry,
|
||||
final Class<T> protoClass)
|
||||
throws ParseException {
|
||||
Message.Builder builder =
|
||||
Internal.getDefaultInstance(protoClass).newBuilderForType();
|
||||
merge(input, extensionRegistry, builder);
|
||||
@SuppressWarnings("unchecked")
|
||||
T output = (T) builder.build();
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parser for text-format proto2 instances. This class is thread-safe.
|
||||
|
@ -385,15 +385,6 @@ final class UnsafeUtil {
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> Class<T> getClassForName(String name) {
|
||||
try {
|
||||
return (Class<T>) Class.forName(name);
|
||||
} catch (Throwable e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Finds the address field within a direct {@link Buffer}. */
|
||||
private static Field bufferAddressField() {
|
||||
return field(Buffer.class, "address", long.class);
|
||||
|
@ -30,6 +30,9 @@
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import static com.google.protobuf.TestUtil.TEST_REQUIRED_INITIALIZED;
|
||||
import static com.google.protobuf.TestUtil.TEST_REQUIRED_UNINITIALIZED;
|
||||
|
||||
import com.google.protobuf.Descriptors.FieldDescriptor;
|
||||
import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
|
||||
import protobuf_unittest.UnittestProto;
|
||||
@ -346,11 +349,6 @@ public class AbstractMessageTest extends TestCase {
|
||||
// -----------------------------------------------------------------
|
||||
// Tests for isInitialized().
|
||||
|
||||
private static final TestRequired TEST_REQUIRED_UNINITIALIZED =
|
||||
TestRequired.getDefaultInstance();
|
||||
private static final TestRequired TEST_REQUIRED_INITIALIZED =
|
||||
TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
|
||||
|
||||
public void testIsInitialized() throws Exception {
|
||||
TestRequired.Builder builder = TestRequired.newBuilder();
|
||||
AbstractMessageWrapper.Builder abstractBuilder =
|
||||
@ -380,7 +378,7 @@ public class AbstractMessageTest extends TestCase {
|
||||
builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
|
||||
assertFalse(abstractBuilder.isInitialized());
|
||||
assertEquals(
|
||||
"optional_message.a, optional_message.b, optional_message.c",
|
||||
"optional_message.b, optional_message.c",
|
||||
abstractBuilder.getInitializationErrorString());
|
||||
|
||||
builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
|
||||
@ -390,7 +388,7 @@ public class AbstractMessageTest extends TestCase {
|
||||
builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
|
||||
assertFalse(abstractBuilder.isInitialized());
|
||||
assertEquals(
|
||||
"repeated_message[0].a, repeated_message[0].b, repeated_message[0].c",
|
||||
"repeated_message[0].b, repeated_message[0].c",
|
||||
abstractBuilder.getInitializationErrorString());
|
||||
|
||||
builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
|
||||
|
@ -231,6 +231,7 @@ import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
|
||||
import protobuf_unittest.UnittestProto.TestOneof2;
|
||||
import protobuf_unittest.UnittestProto.TestPackedExtensions;
|
||||
import protobuf_unittest.UnittestProto.TestPackedTypes;
|
||||
import protobuf_unittest.UnittestProto.TestRequired;
|
||||
import protobuf_unittest.UnittestProto.TestUnpackedTypes;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -252,6 +253,11 @@ import junit.framework.Assert;
|
||||
public final class TestUtil {
|
||||
private TestUtil() {}
|
||||
|
||||
public static final TestRequired TEST_REQUIRED_UNINITIALIZED =
|
||||
TestRequired.newBuilder().setA(1).buildPartial();
|
||||
public static final TestRequired TEST_REQUIRED_INITIALIZED =
|
||||
TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
|
||||
|
||||
/** Helper to convert a String to ByteString. */
|
||||
static ByteString toBytes(String str) {
|
||||
return ByteString.copyFrom(str.getBytes(Internal.UTF_8));
|
||||
|
@ -30,6 +30,9 @@
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import static com.google.protobuf.TestUtil.TEST_REQUIRED_INITIALIZED;
|
||||
import static com.google.protobuf.TestUtil.TEST_REQUIRED_UNINITIALIZED;
|
||||
|
||||
import com.google.protobuf.Descriptors.Descriptor;
|
||||
import com.google.protobuf.Descriptors.FieldDescriptor;
|
||||
import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy;
|
||||
@ -42,6 +45,7 @@ import protobuf_unittest.UnittestProto.TestAllTypes;
|
||||
import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
|
||||
import protobuf_unittest.UnittestProto.TestEmptyMessage;
|
||||
import protobuf_unittest.UnittestProto.TestOneof2;
|
||||
import protobuf_unittest.UnittestProto.TestRequired;
|
||||
import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
|
||||
import java.io.StringReader;
|
||||
import java.util.List;
|
||||
@ -326,19 +330,58 @@ public class TextFormatTest extends TestCase {
|
||||
|
||||
// =================================================================
|
||||
|
||||
public void testParse() throws Exception {
|
||||
public void testMerge() throws Exception {
|
||||
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
||||
TextFormat.merge(allFieldsSetText, builder);
|
||||
TestUtil.assertAllFieldsSet(builder.build());
|
||||
}
|
||||
|
||||
public void testParseReader() throws Exception {
|
||||
public void testParse() throws Exception {
|
||||
TestUtil.assertAllFieldsSet(
|
||||
TextFormat.parse(allFieldsSetText, TestAllTypes.class));
|
||||
}
|
||||
|
||||
public void testMergeInitialized() throws Exception {
|
||||
TestRequired.Builder builder = TestRequired.newBuilder();
|
||||
TextFormat.merge(TEST_REQUIRED_INITIALIZED.toString(), builder);
|
||||
assertEquals(TEST_REQUIRED_INITIALIZED.toString(),
|
||||
builder.buildPartial().toString());
|
||||
assertTrue(builder.isInitialized());
|
||||
}
|
||||
|
||||
public void testParseInitialized() throws Exception {
|
||||
TestRequired parsed =
|
||||
TextFormat.parse(TEST_REQUIRED_INITIALIZED.toString(),
|
||||
TestRequired.class);
|
||||
assertEquals(TEST_REQUIRED_INITIALIZED.toString(), parsed.toString());
|
||||
assertTrue(parsed.isInitialized());
|
||||
}
|
||||
|
||||
public void testMergeUninitialized() throws Exception {
|
||||
TestRequired.Builder builder = TestRequired.newBuilder();
|
||||
TextFormat.merge(TEST_REQUIRED_UNINITIALIZED.toString(), builder);
|
||||
assertEquals(TEST_REQUIRED_UNINITIALIZED.toString(),
|
||||
builder.buildPartial().toString());
|
||||
assertFalse(builder.isInitialized());
|
||||
}
|
||||
|
||||
public void testParseUninitialized() throws Exception {
|
||||
try {
|
||||
TextFormat.parse(TEST_REQUIRED_UNINITIALIZED.toString(),
|
||||
TestRequired.class);
|
||||
fail("Expected UninitializedMessageException.");
|
||||
} catch (UninitializedMessageException e) {
|
||||
assertEquals("Message missing required fields: b, c", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testMergeReader() throws Exception {
|
||||
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
||||
TextFormat.merge(new StringReader(allFieldsSetText), builder);
|
||||
TestUtil.assertAllFieldsSet(builder.build());
|
||||
}
|
||||
|
||||
public void testParseExtensions() throws Exception {
|
||||
public void testMergeExtensions() throws Exception {
|
||||
TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
|
||||
TextFormat.merge(allExtensionsSetText,
|
||||
TestUtil.getExtensionRegistry(),
|
||||
@ -346,7 +389,14 @@ public class TextFormatTest extends TestCase {
|
||||
TestUtil.assertAllExtensionsSet(builder.build());
|
||||
}
|
||||
|
||||
public void testParseCompatibility() throws Exception {
|
||||
public void testParseExtensions() throws Exception {
|
||||
TestUtil.assertAllExtensionsSet(
|
||||
TextFormat.parse(allExtensionsSetText,
|
||||
TestUtil.getExtensionRegistry(),
|
||||
TestAllExtensions.class));
|
||||
}
|
||||
|
||||
public void testMergeAndParseCompatibility() throws Exception {
|
||||
String original = "repeated_float: inf\n" +
|
||||
"repeated_float: -inf\n" +
|
||||
"repeated_float: nan\n" +
|
||||
@ -371,21 +421,29 @@ public class TextFormatTest extends TestCase {
|
||||
"repeated_double: Infinity\n" +
|
||||
"repeated_double: -Infinity\n" +
|
||||
"repeated_double: NaN\n";
|
||||
|
||||
// Test merge().
|
||||
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
||||
TextFormat.merge(original, builder);
|
||||
assertEquals(canonical, builder.build().toString());
|
||||
|
||||
// Test parse().
|
||||
assertEquals(canonical,
|
||||
TextFormat.parse(original, TestAllTypes.class).toString());
|
||||
}
|
||||
|
||||
public void testParseExotic() throws Exception {
|
||||
public void testMergeAndParseExotic() throws Exception {
|
||||
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
||||
TextFormat.merge(exoticText, builder);
|
||||
|
||||
// Too lazy to check things individually. Don't try to debug this
|
||||
// if testPrintExotic() is failing.
|
||||
assertEquals(canonicalExoticText, builder.build().toString());
|
||||
assertEquals(canonicalExoticText,
|
||||
TextFormat.parse(exoticText, TestAllTypes.class).toString());
|
||||
}
|
||||
|
||||
public void testParseMessageSet() throws Exception {
|
||||
public void testMergeMessageSet() throws Exception {
|
||||
ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
|
||||
extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
|
||||
extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
|
||||
@ -411,7 +469,7 @@ public class TextFormatTest extends TestCase {
|
||||
TestMessageSetExtension1.messageSetExtension).getI());
|
||||
}
|
||||
|
||||
public void testParseMessageSetWithOverwriteForbidden() throws Exception {
|
||||
public void testMergeMessageSetWithOverwriteForbidden() throws Exception {
|
||||
ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
|
||||
extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
|
||||
extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
|
||||
@ -438,20 +496,20 @@ public class TextFormatTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testParseNumericEnum() throws Exception {
|
||||
public void testMergeNumericEnum() throws Exception {
|
||||
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
||||
TextFormat.merge("optional_nested_enum: 2", builder);
|
||||
assertEquals(TestAllTypes.NestedEnum.BAR, builder.getOptionalNestedEnum());
|
||||
}
|
||||
|
||||
public void testParseAngleBrackets() throws Exception {
|
||||
public void testMergeAngleBrackets() throws Exception {
|
||||
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
||||
TextFormat.merge("OptionalGroup: < a: 1 >", builder);
|
||||
assertTrue(builder.hasOptionalGroup());
|
||||
assertEquals(1, builder.getOptionalGroup().getA());
|
||||
}
|
||||
|
||||
public void testParseComment() throws Exception {
|
||||
public void testMergeComment() throws Exception {
|
||||
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
||||
TextFormat.merge(
|
||||
"# this is a comment\n" +
|
||||
@ -463,6 +521,7 @@ public class TextFormatTest extends TestCase {
|
||||
}
|
||||
|
||||
private void assertParseError(String error, String text) {
|
||||
// Test merge().
|
||||
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
||||
try {
|
||||
TextFormat.merge(text, TestUtil.getExtensionRegistry(), builder);
|
||||
@ -470,6 +529,15 @@ public class TextFormatTest extends TestCase {
|
||||
} catch (TextFormat.ParseException e) {
|
||||
assertEquals(error, e.getMessage());
|
||||
}
|
||||
|
||||
// Test parse().
|
||||
try {
|
||||
TextFormat.parse(
|
||||
text, TestUtil.getExtensionRegistry(), TestAllTypes.class);
|
||||
fail("Expected parse exception.");
|
||||
} catch (TextFormat.ParseException e) {
|
||||
assertEquals(error, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -105,7 +105,7 @@ public class JsonFormat {
|
||||
public static Printer printer() {
|
||||
return new Printer(
|
||||
TypeRegistry.getEmptyTypeRegistry(), false, Collections.<FieldDescriptor>emptySet(),
|
||||
false, false);
|
||||
false, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,18 +125,21 @@ public class JsonFormat {
|
||||
private Set<FieldDescriptor> includingDefaultValueFields;
|
||||
private final boolean preservingProtoFieldNames;
|
||||
private final boolean omittingInsignificantWhitespace;
|
||||
private final boolean printingEnumsAsInts;
|
||||
|
||||
private Printer(
|
||||
TypeRegistry registry,
|
||||
boolean alwaysOutputDefaultValueFields,
|
||||
Set<FieldDescriptor> includingDefaultValueFields,
|
||||
boolean preservingProtoFieldNames,
|
||||
boolean omittingInsignificantWhitespace) {
|
||||
boolean omittingInsignificantWhitespace,
|
||||
boolean printingEnumsAsInts) {
|
||||
this.registry = registry;
|
||||
this.alwaysOutputDefaultValueFields = alwaysOutputDefaultValueFields;
|
||||
this.includingDefaultValueFields = includingDefaultValueFields;
|
||||
this.preservingProtoFieldNames = preservingProtoFieldNames;
|
||||
this.omittingInsignificantWhitespace = omittingInsignificantWhitespace;
|
||||
this.printingEnumsAsInts = printingEnumsAsInts;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -154,7 +157,8 @@ public class JsonFormat {
|
||||
alwaysOutputDefaultValueFields,
|
||||
includingDefaultValueFields,
|
||||
preservingProtoFieldNames,
|
||||
omittingInsignificantWhitespace);
|
||||
omittingInsignificantWhitespace,
|
||||
printingEnumsAsInts);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -170,7 +174,31 @@ public class JsonFormat {
|
||||
true,
|
||||
Collections.<FieldDescriptor>emptySet(),
|
||||
preservingProtoFieldNames,
|
||||
omittingInsignificantWhitespace);
|
||||
omittingInsignificantWhitespace,
|
||||
printingEnumsAsInts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Printer} that will print enum field values as integers instead of as
|
||||
* string.
|
||||
* The new Printer clones all other configurations from the current
|
||||
* {@link Printer}.
|
||||
*/
|
||||
public Printer printingEnumsAsInts() {
|
||||
checkUnsetPrintingEnumsAsInts();
|
||||
return new Printer(
|
||||
registry,
|
||||
alwaysOutputDefaultValueFields,
|
||||
Collections.<FieldDescriptor>emptySet(),
|
||||
preservingProtoFieldNames,
|
||||
omittingInsignificantWhitespace,
|
||||
true);
|
||||
}
|
||||
|
||||
private void checkUnsetPrintingEnumsAsInts() {
|
||||
if (printingEnumsAsInts) {
|
||||
throw new IllegalStateException("JsonFormat printingEnumsAsInts has already been set.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -191,7 +219,8 @@ public class JsonFormat {
|
||||
false,
|
||||
fieldsToAlwaysOutput,
|
||||
preservingProtoFieldNames,
|
||||
omittingInsignificantWhitespace);
|
||||
omittingInsignificantWhitespace,
|
||||
printingEnumsAsInts);
|
||||
}
|
||||
|
||||
private void checkUnsetIncludingDefaultValueFields() {
|
||||
@ -213,7 +242,8 @@ public class JsonFormat {
|
||||
alwaysOutputDefaultValueFields,
|
||||
includingDefaultValueFields,
|
||||
true,
|
||||
omittingInsignificantWhitespace);
|
||||
omittingInsignificantWhitespace,
|
||||
printingEnumsAsInts);
|
||||
}
|
||||
|
||||
|
||||
@ -240,7 +270,8 @@ public class JsonFormat {
|
||||
alwaysOutputDefaultValueFields,
|
||||
includingDefaultValueFields,
|
||||
preservingProtoFieldNames,
|
||||
true);
|
||||
true,
|
||||
printingEnumsAsInts);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -259,7 +290,8 @@ public class JsonFormat {
|
||||
includingDefaultValueFields,
|
||||
preservingProtoFieldNames,
|
||||
output,
|
||||
omittingInsignificantWhitespace)
|
||||
omittingInsignificantWhitespace,
|
||||
printingEnumsAsInts)
|
||||
.print(message);
|
||||
}
|
||||
|
||||
@ -416,7 +448,7 @@ public class JsonFormat {
|
||||
*/
|
||||
public Builder add(Iterable<Descriptor> messageTypes) {
|
||||
if (types == null) {
|
||||
throw new IllegalStateException("A TypeRegistry.Builer can only be used once.");
|
||||
throw new IllegalStateException("A TypeRegistry.Builder can only be used once.");
|
||||
}
|
||||
for (Descriptor type : messageTypes) {
|
||||
addFile(type.getFile());
|
||||
@ -570,6 +602,7 @@ public class JsonFormat {
|
||||
private final boolean alwaysOutputDefaultValueFields;
|
||||
private final Set<FieldDescriptor> includingDefaultValueFields;
|
||||
private final boolean preservingProtoFieldNames;
|
||||
private final boolean printingEnumsAsInts;
|
||||
private final TextGenerator generator;
|
||||
// We use Gson to help handle string escapes.
|
||||
private final Gson gson;
|
||||
@ -586,11 +619,13 @@ public class JsonFormat {
|
||||
Set<FieldDescriptor> includingDefaultValueFields,
|
||||
boolean preservingProtoFieldNames,
|
||||
Appendable jsonOutput,
|
||||
boolean omittingInsignificantWhitespace) {
|
||||
boolean omittingInsignificantWhitespace,
|
||||
boolean printingEnumsAsInts) {
|
||||
this.registry = registry;
|
||||
this.alwaysOutputDefaultValueFields = alwaysOutputDefaultValueFields;
|
||||
this.includingDefaultValueFields = includingDefaultValueFields;
|
||||
this.preservingProtoFieldNames = preservingProtoFieldNames;
|
||||
this.printingEnumsAsInts = printingEnumsAsInts;
|
||||
this.gson = GsonHolder.DEFAULT_GSON;
|
||||
// json format related properties, determined by printerType
|
||||
if (omittingInsignificantWhitespace) {
|
||||
@ -1069,7 +1104,7 @@ public class JsonFormat {
|
||||
generator.print("\"");
|
||||
}
|
||||
} else {
|
||||
if (((EnumValueDescriptor) value).getIndex() == -1) {
|
||||
if (printingEnumsAsInts || ((EnumValueDescriptor) value).getIndex() == -1) {
|
||||
generator.print(String.valueOf(((EnumValueDescriptor) value).getNumber()));
|
||||
} else {
|
||||
generator.print("\"" + ((EnumValueDescriptor) value).getName() + "\"");
|
||||
|
@ -74,6 +74,11 @@ public final class Timestamps {
|
||||
public static final Timestamp MAX_VALUE =
|
||||
Timestamp.newBuilder().setSeconds(TIMESTAMP_SECONDS_MAX).setNanos(999999999).build();
|
||||
|
||||
/**
|
||||
* A constant holding the {@link Timestamp} of epoch time, {@code 1970-01-01T00:00:00.000000000Z}.
|
||||
*/
|
||||
public static final Timestamp EPOCH = Timestamp.newBuilder().setSeconds(0).setNanos(0).build();
|
||||
|
||||
private static final ThreadLocal<SimpleDateFormat> timestampFormat =
|
||||
new ThreadLocal<SimpleDateFormat>() {
|
||||
@Override
|
||||
@ -358,10 +363,12 @@ public final class Timestamps {
|
||||
static Timestamp normalizedTimestamp(long seconds, int nanos) {
|
||||
if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
|
||||
seconds = checkedAdd(seconds, nanos / NANOS_PER_SECOND);
|
||||
nanos %= NANOS_PER_SECOND;
|
||||
nanos = (int) (nanos % NANOS_PER_SECOND);
|
||||
}
|
||||
if (nanos < 0) {
|
||||
nanos += NANOS_PER_SECOND; // no overflow since nanos is negative (and we're adding)
|
||||
nanos =
|
||||
(int)
|
||||
(nanos + NANOS_PER_SECOND); // no overflow since nanos is negative (and we're adding)
|
||||
seconds = checkedSubtract(seconds, 1);
|
||||
}
|
||||
Timestamp timestamp = Timestamp.newBuilder().setSeconds(seconds).setNanos(nanos).build();
|
||||
|
@ -1174,6 +1174,14 @@ public class JsonFormatTest extends TestCase {
|
||||
JsonFormat.parser().ignoringUnknownFields().merge(json, builder);
|
||||
}
|
||||
|
||||
public void testParserIntegerEnumValue() throws Exception {
|
||||
TestAllTypes.Builder actualBuilder = TestAllTypes.newBuilder();
|
||||
mergeFromJson("{\n" + " \"optionalNestedEnum\": 2\n" + "}", actualBuilder);
|
||||
|
||||
TestAllTypes expected = TestAllTypes.newBuilder().setOptionalNestedEnum(NestedEnum.BAZ).build();
|
||||
assertEquals(expected, actualBuilder.build());
|
||||
}
|
||||
|
||||
public void testCustomJsonName() throws Exception {
|
||||
TestCustomJsonName message = TestCustomJsonName.newBuilder().setValue(12345).build();
|
||||
assertEquals("{\n" + " \"@value\": 12345\n" + "}", JsonFormat.printer().print(message));
|
||||
@ -1441,6 +1449,13 @@ public class JsonFormatTest extends TestCase {
|
||||
assertEquals(54321, builder.getOptionalInt32());
|
||||
}
|
||||
|
||||
public void testPrintingEnumsAsInts() throws Exception {
|
||||
TestAllTypes message = TestAllTypes.newBuilder().setOptionalNestedEnum(NestedEnum.BAR).build();
|
||||
assertEquals(
|
||||
"{\n" + " \"optionalNestedEnum\": 1\n" + "}",
|
||||
JsonFormat.printer().printingEnumsAsInts().print(message));
|
||||
}
|
||||
|
||||
public void testOmittingInsignificantWhiteSpace() throws Exception {
|
||||
TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(12345).build();
|
||||
assertEquals(
|
||||
|
@ -221,7 +221,7 @@ jspb.arith.UInt64.prototype.mul = function(a) {
|
||||
* Divide a 64-bit number by a 32-bit number to produce a
|
||||
* 64-bit quotient and a 32-bit remainder.
|
||||
* @param {number} _divisor
|
||||
* @return {Array.<jspb.arith.UInt64>} array of [quotient, remainder],
|
||||
* @return {Array<jspb.arith.UInt64>} array of [quotient, remainder],
|
||||
* unless divisor is 0, in which case an empty array is returned.
|
||||
*/
|
||||
jspb.arith.UInt64.prototype.div = function(_divisor) {
|
||||
|
@ -58,7 +58,7 @@ goog.require('jspb.utils');
|
||||
* @param {?jspb.BinaryDecoder=} opt_decoder
|
||||
* @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=}
|
||||
* opt_next The decoder method to use for next().
|
||||
* @param {?Array.<number|boolean|string>=} opt_elements
|
||||
* @param {?Array<number|boolean|string>=} opt_elements
|
||||
* @constructor
|
||||
* @struct
|
||||
*/
|
||||
@ -92,7 +92,7 @@ jspb.BinaryIterator = function(opt_decoder, opt_next, opt_elements) {
|
||||
* @param {?jspb.BinaryDecoder=} opt_decoder
|
||||
* @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=}
|
||||
* opt_next The decoder method to use for next().
|
||||
* @param {?Array.<number|boolean|string>=} opt_elements
|
||||
* @param {?Array<number|boolean|string>=} opt_elements
|
||||
* @private
|
||||
*/
|
||||
jspb.BinaryIterator.prototype.init_ =
|
||||
@ -112,7 +112,7 @@ jspb.BinaryIterator.prototype.init_ =
|
||||
|
||||
/**
|
||||
* Global pool of BinaryIterator instances.
|
||||
* @private {!Array.<!jspb.BinaryIterator>}
|
||||
* @private {!Array<!jspb.BinaryIterator>}
|
||||
*/
|
||||
jspb.BinaryIterator.instanceCache_ = [];
|
||||
|
||||
@ -123,7 +123,7 @@ jspb.BinaryIterator.instanceCache_ = [];
|
||||
* @param {?jspb.BinaryDecoder=} opt_decoder
|
||||
* @param {?function(this:jspb.BinaryDecoder):(number|boolean|string)=}
|
||||
* opt_next The decoder method to use for next().
|
||||
* @param {?Array.<number|boolean|string>=} opt_elements
|
||||
* @param {?Array<number|boolean|string>=} opt_elements
|
||||
* @return {!jspb.BinaryIterator}
|
||||
*/
|
||||
jspb.BinaryIterator.alloc = function(opt_decoder, opt_next, opt_elements) {
|
||||
@ -274,7 +274,7 @@ jspb.BinaryDecoder = function(opt_bytes, opt_start, opt_length) {
|
||||
|
||||
/**
|
||||
* Global pool of BinaryDecoder instances.
|
||||
* @private {!Array.<!jspb.BinaryDecoder>}
|
||||
* @private {!Array<!jspb.BinaryDecoder>}
|
||||
*/
|
||||
jspb.BinaryDecoder.instanceCache_ = [];
|
||||
|
||||
|
@ -51,7 +51,7 @@ goog.require('jspb.utils');
|
||||
* @struct
|
||||
*/
|
||||
jspb.BinaryEncoder = function() {
|
||||
/** @private {!Array.<number>} */
|
||||
/** @private {!Array<number>} */
|
||||
this.buffer_ = [];
|
||||
};
|
||||
|
||||
@ -65,7 +65,7 @@ jspb.BinaryEncoder.prototype.length = function() {
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryEncoder.prototype.end = function() {
|
||||
var buffer = this.buffer_;
|
||||
|
@ -97,7 +97,7 @@ jspb.BinaryReader = function(opt_bytes, opt_start, opt_length) {
|
||||
|
||||
/**
|
||||
* User-defined reader callbacks.
|
||||
* @private {Object.<string, function(!jspb.BinaryReader):*>}
|
||||
* @private {Object<string, function(!jspb.BinaryReader):*>}
|
||||
*/
|
||||
this.readCallbacks_ = null;
|
||||
};
|
||||
@ -105,7 +105,7 @@ jspb.BinaryReader = function(opt_bytes, opt_start, opt_length) {
|
||||
|
||||
/**
|
||||
* Global pool of BinaryReader instances.
|
||||
* @private {!Array.<!jspb.BinaryReader>}
|
||||
* @private {!Array<!jspb.BinaryReader>}
|
||||
*/
|
||||
jspb.BinaryReader.instanceCache_ = [];
|
||||
|
||||
@ -992,7 +992,7 @@ jspb.BinaryReader.prototype.readPackedField_ = function(decodeMethod) {
|
||||
/**
|
||||
* Reads a packed int32 field, which consists of a length header and a list of
|
||||
* signed varints.
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedInt32 = function() {
|
||||
return this.readPackedField_(this.decoder_.readSignedVarint32);
|
||||
@ -1002,7 +1002,7 @@ jspb.BinaryReader.prototype.readPackedInt32 = function() {
|
||||
/**
|
||||
* Reads a packed int32 field, which consists of a length header and a list of
|
||||
* signed varints. Returns a list of strings.
|
||||
* @return {!Array.<string>}
|
||||
* @return {!Array<string>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedInt32String = function() {
|
||||
return this.readPackedField_(this.decoder_.readSignedVarint32String);
|
||||
@ -1012,7 +1012,7 @@ jspb.BinaryReader.prototype.readPackedInt32String = function() {
|
||||
/**
|
||||
* Reads a packed int64 field, which consists of a length header and a list of
|
||||
* signed varints.
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedInt64 = function() {
|
||||
return this.readPackedField_(this.decoder_.readSignedVarint64);
|
||||
@ -1022,7 +1022,7 @@ jspb.BinaryReader.prototype.readPackedInt64 = function() {
|
||||
/**
|
||||
* Reads a packed int64 field, which consists of a length header and a list of
|
||||
* signed varints. Returns a list of strings.
|
||||
* @return {!Array.<string>}
|
||||
* @return {!Array<string>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedInt64String = function() {
|
||||
return this.readPackedField_(this.decoder_.readSignedVarint64String);
|
||||
@ -1032,7 +1032,7 @@ jspb.BinaryReader.prototype.readPackedInt64String = function() {
|
||||
/**
|
||||
* Reads a packed uint32 field, which consists of a length header and a list of
|
||||
* unsigned varints.
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedUint32 = function() {
|
||||
return this.readPackedField_(this.decoder_.readUnsignedVarint32);
|
||||
@ -1042,7 +1042,7 @@ jspb.BinaryReader.prototype.readPackedUint32 = function() {
|
||||
/**
|
||||
* Reads a packed uint32 field, which consists of a length header and a list of
|
||||
* unsigned varints. Returns a list of strings.
|
||||
* @return {!Array.<string>}
|
||||
* @return {!Array<string>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedUint32String = function() {
|
||||
return this.readPackedField_(this.decoder_.readUnsignedVarint32String);
|
||||
@ -1052,7 +1052,7 @@ jspb.BinaryReader.prototype.readPackedUint32String = function() {
|
||||
/**
|
||||
* Reads a packed uint64 field, which consists of a length header and a list of
|
||||
* unsigned varints.
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedUint64 = function() {
|
||||
return this.readPackedField_(this.decoder_.readUnsignedVarint64);
|
||||
@ -1062,7 +1062,7 @@ jspb.BinaryReader.prototype.readPackedUint64 = function() {
|
||||
/**
|
||||
* Reads a packed uint64 field, which consists of a length header and a list of
|
||||
* unsigned varints. Returns a list of strings.
|
||||
* @return {!Array.<string>}
|
||||
* @return {!Array<string>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedUint64String = function() {
|
||||
return this.readPackedField_(this.decoder_.readUnsignedVarint64String);
|
||||
@ -1072,7 +1072,7 @@ jspb.BinaryReader.prototype.readPackedUint64String = function() {
|
||||
/**
|
||||
* Reads a packed sint32 field, which consists of a length header and a list of
|
||||
* zigzag varints.
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedSint32 = function() {
|
||||
return this.readPackedField_(this.decoder_.readZigzagVarint32);
|
||||
@ -1082,7 +1082,7 @@ jspb.BinaryReader.prototype.readPackedSint32 = function() {
|
||||
/**
|
||||
* Reads a packed sint64 field, which consists of a length header and a list of
|
||||
* zigzag varints.
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedSint64 = function() {
|
||||
return this.readPackedField_(this.decoder_.readZigzagVarint64);
|
||||
@ -1092,7 +1092,7 @@ jspb.BinaryReader.prototype.readPackedSint64 = function() {
|
||||
/**
|
||||
* Reads a packed sint64 field, which consists of a length header and a list of
|
||||
* zigzag varints. Returns a list of strings.
|
||||
* @return {!Array.<string>}
|
||||
* @return {!Array<string>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedSint64String = function() {
|
||||
return this.readPackedField_(this.decoder_.readZigzagVarint64String);
|
||||
@ -1102,7 +1102,7 @@ jspb.BinaryReader.prototype.readPackedSint64String = function() {
|
||||
/**
|
||||
* Reads a packed fixed32 field, which consists of a length header and a list
|
||||
* of unsigned 32-bit ints.
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedFixed32 = function() {
|
||||
return this.readPackedField_(this.decoder_.readUint32);
|
||||
@ -1112,7 +1112,7 @@ jspb.BinaryReader.prototype.readPackedFixed32 = function() {
|
||||
/**
|
||||
* Reads a packed fixed64 field, which consists of a length header and a list
|
||||
* of unsigned 64-bit ints.
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedFixed64 = function() {
|
||||
return this.readPackedField_(this.decoder_.readUint64);
|
||||
@ -1122,7 +1122,7 @@ jspb.BinaryReader.prototype.readPackedFixed64 = function() {
|
||||
/**
|
||||
* Reads a packed fixed64 field, which consists of a length header and a list
|
||||
* of unsigned 64-bit ints. Returns a list of strings.
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedFixed64String = function() {
|
||||
return this.readPackedField_(this.decoder_.readUint64String);
|
||||
@ -1132,7 +1132,7 @@ jspb.BinaryReader.prototype.readPackedFixed64String = function() {
|
||||
/**
|
||||
* Reads a packed sfixed32 field, which consists of a length header and a list
|
||||
* of 32-bit ints.
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedSfixed32 = function() {
|
||||
return this.readPackedField_(this.decoder_.readInt32);
|
||||
@ -1142,7 +1142,7 @@ jspb.BinaryReader.prototype.readPackedSfixed32 = function() {
|
||||
/**
|
||||
* Reads a packed sfixed64 field, which consists of a length header and a list
|
||||
* of 64-bit ints.
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedSfixed64 = function() {
|
||||
return this.readPackedField_(this.decoder_.readInt64);
|
||||
@ -1152,7 +1152,7 @@ jspb.BinaryReader.prototype.readPackedSfixed64 = function() {
|
||||
/**
|
||||
* Reads a packed sfixed64 field, which consists of a length header and a list
|
||||
* of 64-bit ints. Returns a list of strings.
|
||||
* @return {!Array.<string>}
|
||||
* @return {!Array<string>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedSfixed64String = function() {
|
||||
return this.readPackedField_(this.decoder_.readInt64String);
|
||||
@ -1162,7 +1162,7 @@ jspb.BinaryReader.prototype.readPackedSfixed64String = function() {
|
||||
/**
|
||||
* Reads a packed float field, which consists of a length header and a list of
|
||||
* floats.
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedFloat = function() {
|
||||
return this.readPackedField_(this.decoder_.readFloat);
|
||||
@ -1172,7 +1172,7 @@ jspb.BinaryReader.prototype.readPackedFloat = function() {
|
||||
/**
|
||||
* Reads a packed double field, which consists of a length header and a list of
|
||||
* doubles.
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedDouble = function() {
|
||||
return this.readPackedField_(this.decoder_.readDouble);
|
||||
@ -1182,7 +1182,7 @@ jspb.BinaryReader.prototype.readPackedDouble = function() {
|
||||
/**
|
||||
* Reads a packed bool field, which consists of a length header and a list of
|
||||
* unsigned varints.
|
||||
* @return {!Array.<boolean>}
|
||||
* @return {!Array<boolean>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedBool = function() {
|
||||
return this.readPackedField_(this.decoder_.readBool);
|
||||
@ -1192,7 +1192,7 @@ jspb.BinaryReader.prototype.readPackedBool = function() {
|
||||
/**
|
||||
* Reads a packed enum field, which consists of a length header and a list of
|
||||
* unsigned varints.
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedEnum = function() {
|
||||
return this.readPackedField_(this.decoder_.readEnum);
|
||||
@ -1202,7 +1202,7 @@ jspb.BinaryReader.prototype.readPackedEnum = function() {
|
||||
/**
|
||||
* Reads a packed varint hash64 field, which consists of a length header and a
|
||||
* list of varint hash64s.
|
||||
* @return {!Array.<string>}
|
||||
* @return {!Array<string>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedVarintHash64 = function() {
|
||||
return this.readPackedField_(this.decoder_.readVarintHash64);
|
||||
@ -1212,7 +1212,7 @@ jspb.BinaryReader.prototype.readPackedVarintHash64 = function() {
|
||||
/**
|
||||
* Reads a packed fixed hash64 field, which consists of a length header and a
|
||||
* list of fixed hash64s.
|
||||
* @return {!Array.<string>}
|
||||
* @return {!Array<string>}
|
||||
*/
|
||||
jspb.BinaryReader.prototype.readPackedFixedHash64 = function() {
|
||||
return this.readPackedField_(this.decoder_.readFixedHash64);
|
||||
|
@ -431,7 +431,7 @@ jspb.utils.joinHash64 = function(bitsLow, bitsHigh) {
|
||||
|
||||
/**
|
||||
* Individual digits for number->string conversion.
|
||||
* @const {!Array.<string>}
|
||||
* @const {!Array<string>}
|
||||
*/
|
||||
jspb.utils.DIGITS = [
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
@ -554,10 +554,10 @@ jspb.utils.hash64ToDecimalString = function(hash, signed) {
|
||||
/**
|
||||
* Converts an array of 8-character hash strings into their decimal
|
||||
* representations.
|
||||
* @param {!Array.<string>} hashes The array of hash strings to convert.
|
||||
* @param {!Array<string>} hashes The array of hash strings to convert.
|
||||
* @param {boolean} signed True if we should treat the hash string as encoding
|
||||
* a signed integer.
|
||||
* @return {!Array.<string>}
|
||||
* @return {!Array<string>}
|
||||
*/
|
||||
jspb.utils.hash64ArrayToDecimalStrings = function(hashes, signed) {
|
||||
var result = new Array(hashes.length);
|
||||
@ -972,7 +972,7 @@ jspb.utils.byteSourceToUint8Array = function(data) {
|
||||
}
|
||||
|
||||
if (data.constructor === Array) {
|
||||
data = /** @type {!Array.<number>} */(data);
|
||||
data = /** @type {!Array<number>} */(data);
|
||||
return /** @type {!Uint8Array} */(new Uint8Array(data));
|
||||
}
|
||||
|
||||
|
@ -657,7 +657,7 @@ describe('binaryUtilsTest', function() {
|
||||
// Converting Uint8Arrays into Uint8Arrays should be a no-op.
|
||||
assertEquals(sourceBytes, convert(sourceBytes));
|
||||
|
||||
// Converting Array.<numbers> into Uint8Arrays should work.
|
||||
// Converting Array<numbers> into Uint8Arrays should work.
|
||||
check(convert(sourceData));
|
||||
|
||||
// Converting ArrayBuffers into Uint8Arrays should work.
|
||||
|
@ -102,7 +102,7 @@ jspb.BinaryWriter = function() {
|
||||
* A stack of bookmarks containing the parent blocks for each message started
|
||||
* via beginSubMessage(), needed as bookkeeping for endSubMessage().
|
||||
* TODO(aappleby): Deprecated, users should be calling writeMessage().
|
||||
* @private {!Array.<!Array.<number>>}
|
||||
* @private {!Array<!Array<number>>}
|
||||
*/
|
||||
this.bookmarks_ = [];
|
||||
};
|
||||
@ -126,7 +126,7 @@ jspb.BinaryWriter.prototype.appendUint8Array_ = function(arr) {
|
||||
* Begins a new message by writing the field header and returning a bookmark
|
||||
* which we will use to patch in the message length to in endDelimited_ below.
|
||||
* @param {number} field
|
||||
* @return {!Array.<number>}
|
||||
* @return {!Array<number>}
|
||||
* @private
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.beginDelimited_ = function(field) {
|
||||
@ -143,7 +143,7 @@ jspb.BinaryWriter.prototype.beginDelimited_ = function(field) {
|
||||
* Ends a message by encoding the _change_ in length of the buffer to the
|
||||
* parent block and adds the number of bytes needed to encode that length to
|
||||
* the total byte length.
|
||||
* @param {!Array.<number>} bookmark
|
||||
* @param {!Array<number>} bookmark
|
||||
* @private
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.endDelimited_ = function(bookmark) {
|
||||
@ -855,7 +855,7 @@ jspb.BinaryWriter.prototype.writeVarintHash64 = function(field, value) {
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a repeated 32-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedInt32 = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -869,7 +869,7 @@ jspb.BinaryWriter.prototype.writeRepeatedInt32 = function(field, value) {
|
||||
* Writes an array of numbers formatted as strings to the buffer as a repeated
|
||||
* 32-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of ints to write.
|
||||
* @param {?Array<string>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedInt32String = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -882,7 +882,7 @@ jspb.BinaryWriter.prototype.writeRepeatedInt32String = function(field, value) {
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a repeated 64-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedInt64 = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -896,7 +896,7 @@ jspb.BinaryWriter.prototype.writeRepeatedInt64 = function(field, value) {
|
||||
* Writes an array of numbers formatted as strings to the buffer as a repeated
|
||||
* 64-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of ints to write.
|
||||
* @param {?Array<string>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedInt64String = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -910,7 +910,7 @@ jspb.BinaryWriter.prototype.writeRepeatedInt64String = function(field, value) {
|
||||
* Writes an array numbers to the buffer as a repeated unsigned 32-bit int
|
||||
* field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedUint32 = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -924,7 +924,7 @@ jspb.BinaryWriter.prototype.writeRepeatedUint32 = function(field, value) {
|
||||
* Writes an array of numbers formatted as strings to the buffer as a repeated
|
||||
* unsigned 32-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of ints to write.
|
||||
* @param {?Array<string>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedUint32String = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -938,7 +938,7 @@ jspb.BinaryWriter.prototype.writeRepeatedUint32String = function(field, value) {
|
||||
* Writes an array numbers to the buffer as a repeated unsigned 64-bit int
|
||||
* field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedUint64 = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -952,7 +952,7 @@ jspb.BinaryWriter.prototype.writeRepeatedUint64 = function(field, value) {
|
||||
* Writes an array of numbers formatted as strings to the buffer as a repeated
|
||||
* unsigned 64-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of ints to write.
|
||||
* @param {?Array<string>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedUint64String = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -965,7 +965,7 @@ jspb.BinaryWriter.prototype.writeRepeatedUint64String = function(field, value) {
|
||||
/**
|
||||
* Writes an array numbers to the buffer as a repeated signed 32-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedSint32 = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -978,7 +978,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSint32 = function(field, value) {
|
||||
/**
|
||||
* Writes an array numbers to the buffer as a repeated signed 64-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedSint64 = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -991,7 +991,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSint64 = function(field, value) {
|
||||
/**
|
||||
* Writes an array numbers to the buffer as a repeated signed 64-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of ints to write.
|
||||
* @param {?Array<string>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedSint64String = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -1005,7 +1005,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSint64String = function(field, value) {
|
||||
* Writes an array of numbers to the buffer as a repeated fixed32 field. This
|
||||
* works for both signed and unsigned fixed32s.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedFixed32 = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -1019,7 +1019,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFixed32 = function(field, value) {
|
||||
* Writes an array of numbers to the buffer as a repeated fixed64 field. This
|
||||
* works for both signed and unsigned fixed64s.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedFixed64 = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -1033,7 +1033,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFixed64 = function(field, value) {
|
||||
* Writes an array of numbers to the buffer as a repeated fixed64 field. This
|
||||
* works for both signed and unsigned fixed64s.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of decimal strings to write.
|
||||
* @param {?Array<string>} value The array of decimal strings to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedFixed64String = function(
|
||||
field, value) {
|
||||
@ -1047,7 +1047,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFixed64String = function(
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a repeated sfixed32 field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedSfixed32 = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -1060,7 +1060,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSfixed32 = function(field, value) {
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a repeated sfixed64 field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedSfixed64 = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -1074,7 +1074,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSfixed64 = function(field, value) {
|
||||
* Writes an array of decimal strings to the buffer as a repeated sfixed64
|
||||
* field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of decimal strings to write.
|
||||
* @param {?Array<string>} value The array of decimal strings to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedSfixed64String = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -1087,7 +1087,7 @@ jspb.BinaryWriter.prototype.writeRepeatedSfixed64String = function(field, value)
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a repeated float field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedFloat = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -1100,7 +1100,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFloat = function(field, value) {
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a repeated double field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedDouble = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -1113,7 +1113,7 @@ jspb.BinaryWriter.prototype.writeRepeatedDouble = function(field, value) {
|
||||
/**
|
||||
* Writes an array of booleans to the buffer as a repeated bool field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<boolean>} value The array of ints to write.
|
||||
* @param {?Array<boolean>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedBool = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -1126,7 +1126,7 @@ jspb.BinaryWriter.prototype.writeRepeatedBool = function(field, value) {
|
||||
/**
|
||||
* Writes an array of enums to the buffer as a repeated enum field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedEnum = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -1139,7 +1139,7 @@ jspb.BinaryWriter.prototype.writeRepeatedEnum = function(field, value) {
|
||||
/**
|
||||
* Writes an array of strings to the buffer as a repeated string field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of strings to write.
|
||||
* @param {?Array<string>} value The array of strings to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedString = function(field, value) {
|
||||
if (value == null) return;
|
||||
@ -1152,7 +1152,7 @@ jspb.BinaryWriter.prototype.writeRepeatedString = function(field, value) {
|
||||
/**
|
||||
* Writes an array of arbitrary byte fields to the buffer.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<!jspb.ByteSource>} value The arrays of arrays of bytes to
|
||||
* @param {?Array<!jspb.ByteSource>} value The arrays of arrays of bytes to
|
||||
* write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedBytes = function(field, value) {
|
||||
@ -1167,7 +1167,7 @@ jspb.BinaryWriter.prototype.writeRepeatedBytes = function(field, value) {
|
||||
* Writes an array of messages to the buffer.
|
||||
* @template MessageType
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<MessageType>} value The array of messages to
|
||||
* @param {?Array<MessageType>} value The array of messages to
|
||||
* write.
|
||||
* @param {function(MessageType, !jspb.BinaryWriter)} writerCallback
|
||||
* Will be invoked with the value to write and the writer to write it with.
|
||||
@ -1187,7 +1187,7 @@ jspb.BinaryWriter.prototype.writeRepeatedMessage = function(
|
||||
* Writes an array of group messages to the buffer.
|
||||
* @template MessageType
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<MessageType>} value The array of messages to
|
||||
* @param {?Array<MessageType>} value The array of messages to
|
||||
* write.
|
||||
* @param {function(MessageType, !jspb.BinaryWriter)} writerCallback
|
||||
* Will be invoked with the value to write and the writer to write it with.
|
||||
@ -1207,7 +1207,7 @@ jspb.BinaryWriter.prototype.writeRepeatedGroup = function(
|
||||
* Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to
|
||||
* the buffer.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of hashes to write.
|
||||
* @param {?Array<string>} value The array of hashes to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedFixedHash64 =
|
||||
function(field, value) {
|
||||
@ -1222,7 +1222,7 @@ jspb.BinaryWriter.prototype.writeRepeatedFixedHash64 =
|
||||
* Writes a repeated 64-bit hash string field (8 characters @ 8 bits of data
|
||||
* each) to the buffer.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of hashes to write.
|
||||
* @param {?Array<string>} value The array of hashes to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 =
|
||||
function(field, value) {
|
||||
@ -1236,7 +1236,7 @@ jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 =
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a packed 32-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedInt32 = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1252,7 +1252,7 @@ jspb.BinaryWriter.prototype.writePackedInt32 = function(field, value) {
|
||||
* Writes an array of numbers represented as strings to the buffer as a packed
|
||||
* 32-bit int field.
|
||||
* @param {number} field
|
||||
* @param {?Array.<string>} value
|
||||
* @param {?Array<string>} value
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedInt32String = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1267,7 +1267,7 @@ jspb.BinaryWriter.prototype.writePackedInt32String = function(field, value) {
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a packed 64-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedInt64 = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1283,7 +1283,7 @@ jspb.BinaryWriter.prototype.writePackedInt64 = function(field, value) {
|
||||
* Writes an array of numbers represented as strings to the buffer as a packed
|
||||
* 64-bit int field.
|
||||
* @param {number} field
|
||||
* @param {?Array.<string>} value
|
||||
* @param {?Array<string>} value
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedInt64String = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1299,7 +1299,7 @@ jspb.BinaryWriter.prototype.writePackedInt64String = function(field, value) {
|
||||
/**
|
||||
* Writes an array numbers to the buffer as a packed unsigned 32-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedUint32 = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1315,7 +1315,7 @@ jspb.BinaryWriter.prototype.writePackedUint32 = function(field, value) {
|
||||
* Writes an array of numbers represented as strings to the buffer as a packed
|
||||
* unsigned 32-bit int field.
|
||||
* @param {number} field
|
||||
* @param {?Array.<string>} value
|
||||
* @param {?Array<string>} value
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedUint32String =
|
||||
function(field, value) {
|
||||
@ -1331,7 +1331,7 @@ jspb.BinaryWriter.prototype.writePackedUint32String =
|
||||
/**
|
||||
* Writes an array numbers to the buffer as a packed unsigned 64-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedUint64 = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1347,7 +1347,7 @@ jspb.BinaryWriter.prototype.writePackedUint64 = function(field, value) {
|
||||
* Writes an array of numbers represented as strings to the buffer as a packed
|
||||
* unsigned 64-bit int field.
|
||||
* @param {number} field
|
||||
* @param {?Array.<string>} value
|
||||
* @param {?Array<string>} value
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedUint64String =
|
||||
function(field, value) {
|
||||
@ -1364,7 +1364,7 @@ jspb.BinaryWriter.prototype.writePackedUint64String =
|
||||
/**
|
||||
* Writes an array numbers to the buffer as a packed signed 32-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedSint32 = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1379,7 +1379,7 @@ jspb.BinaryWriter.prototype.writePackedSint32 = function(field, value) {
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a packed signed 64-bit int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedSint64 = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1395,7 +1395,7 @@ jspb.BinaryWriter.prototype.writePackedSint64 = function(field, value) {
|
||||
* Writes an array of decimal strings to the buffer as a packed signed 64-bit
|
||||
* int field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of decimal strings to write.
|
||||
* @param {?Array<string>} value The array of decimal strings to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedSint64String = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1411,7 +1411,7 @@ jspb.BinaryWriter.prototype.writePackedSint64String = function(field, value) {
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a packed fixed32 field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedFixed32 = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1426,7 +1426,7 @@ jspb.BinaryWriter.prototype.writePackedFixed32 = function(field, value) {
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a packed fixed64 field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedFixed64 = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1442,7 +1442,7 @@ jspb.BinaryWriter.prototype.writePackedFixed64 = function(field, value) {
|
||||
* Writes an array of numbers represented as strings to the buffer as a packed
|
||||
* fixed64 field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of strings to write.
|
||||
* @param {?Array<string>} value The array of strings to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedFixed64String = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1458,7 +1458,7 @@ jspb.BinaryWriter.prototype.writePackedFixed64String = function(field, value) {
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a packed sfixed32 field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedSfixed32 = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1473,7 +1473,7 @@ jspb.BinaryWriter.prototype.writePackedSfixed32 = function(field, value) {
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a packed sfixed64 field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedSfixed64 = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1488,7 +1488,7 @@ jspb.BinaryWriter.prototype.writePackedSfixed64 = function(field, value) {
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a packed sfixed64 field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of decimal strings to write.
|
||||
* @param {?Array<string>} value The array of decimal strings to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedSfixed64String = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1503,7 +1503,7 @@ jspb.BinaryWriter.prototype.writePackedSfixed64String = function(field, value) {
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a packed float field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedFloat = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1518,7 +1518,7 @@ jspb.BinaryWriter.prototype.writePackedFloat = function(field, value) {
|
||||
/**
|
||||
* Writes an array of numbers to the buffer as a packed double field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedDouble = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1533,7 +1533,7 @@ jspb.BinaryWriter.prototype.writePackedDouble = function(field, value) {
|
||||
/**
|
||||
* Writes an array of booleans to the buffer as a packed bool field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<boolean>} value The array of ints to write.
|
||||
* @param {?Array<boolean>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedBool = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1548,7 +1548,7 @@ jspb.BinaryWriter.prototype.writePackedBool = function(field, value) {
|
||||
/**
|
||||
* Writes an array of enums to the buffer as a packed enum field.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<number>} value The array of ints to write.
|
||||
* @param {?Array<number>} value The array of ints to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedEnum = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1564,7 +1564,7 @@ jspb.BinaryWriter.prototype.writePackedEnum = function(field, value) {
|
||||
* Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to
|
||||
* the buffer.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of hashes to write.
|
||||
* @param {?Array<string>} value The array of hashes to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedFixedHash64 = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
@ -1580,7 +1580,7 @@ jspb.BinaryWriter.prototype.writePackedFixedHash64 = function(field, value) {
|
||||
* Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to
|
||||
* the buffer.
|
||||
* @param {number} field The field number.
|
||||
* @param {?Array.<string>} value The array of hashes to write.
|
||||
* @param {?Array<string>} value The array of hashes to write.
|
||||
*/
|
||||
jspb.BinaryWriter.prototype.writePackedVarintHash64 = function(field, value) {
|
||||
if (value == null || !value.length) return;
|
||||
|
@ -12,6 +12,7 @@
|
||||
goog.provide('jspb.ExportTestDeps');
|
||||
|
||||
goog.require('goog.crypt.base64');
|
||||
goog.require('goog.testing.PropertyReplacer');
|
||||
goog.require('jspb.arith.Int64');
|
||||
goog.require('jspb.arith.UInt64');
|
||||
goog.require('jspb.BinaryEncoder');
|
||||
|
@ -74,15 +74,22 @@ jspb.debug.dump = function(message) {
|
||||
*/
|
||||
jspb.debug.dump_ = function(thing) {
|
||||
var type = goog.typeOf(thing);
|
||||
var message = thing; // Copy because we don't want type inference on thing.
|
||||
if (type == 'number' || type == 'string' || type == 'boolean' ||
|
||||
type == 'null' || type == 'undefined') {
|
||||
return thing;
|
||||
}
|
||||
if (typeof Uint8Array !== 'undefined') {
|
||||
// Will fail on IE9, where Uint8Array doesn't exist.
|
||||
if (message instanceof Uint8Array) {
|
||||
return thing;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == 'array') {
|
||||
goog.asserts.assertArray(thing);
|
||||
return goog.array.map(thing, jspb.debug.dump_);
|
||||
}
|
||||
var message = thing; // Copy because we don't want type inference on thing.
|
||||
goog.asserts.assert(message instanceof jspb.Message,
|
||||
'Only messages expected: ' + thing);
|
||||
var ctor = message.constructor;
|
||||
|
@ -41,6 +41,8 @@ goog.require('proto.jspb.test.IsExtension');
|
||||
goog.require('proto.jspb.test.Simple1');
|
||||
|
||||
|
||||
// CommonJS-LoadFromFile: testbinary_pb
|
||||
goog.require('proto.jspb.test.TestAllTypes');
|
||||
|
||||
describe('debugTest', function() {
|
||||
it('testSimple1', function() {
|
||||
@ -74,6 +76,15 @@ describe('debugTest', function() {
|
||||
}, jspb.debug.dump(message));
|
||||
});
|
||||
|
||||
it('testBytes', function() {
|
||||
if (COMPILED || typeof Uint8Array == 'undefined') {
|
||||
return;
|
||||
}
|
||||
var message = new proto.jspb.test.TestAllTypes();
|
||||
var bytes = new Uint8Array(4);
|
||||
message.setOptionalBytes(bytes);
|
||||
assertEquals(jspb.debug.dump(message)['optionalBytes'], bytes);
|
||||
});
|
||||
|
||||
it('testExtensions', function() {
|
||||
if (COMPILED) {
|
||||
|
@ -205,6 +205,16 @@ goog.define('jspb.Message.GENERATE_TO_STRING', true);
|
||||
goog.define('jspb.Message.ASSUME_LOCAL_ARRAYS', false);
|
||||
|
||||
|
||||
// TODO(jakubvrana): Turn this off by default.
|
||||
/**
|
||||
* @define {boolean} Disabling the serialization of empty trailing fields
|
||||
* reduces the size of serialized protos. The price is an extra iteration of
|
||||
* the proto before serialization. This is enabled by default to be
|
||||
* backwards compatible. Projects are advised to turn this flag always off.
|
||||
*/
|
||||
goog.define('jspb.Message.SERIALIZE_EMPTY_TRAILING_FIELDS', true);
|
||||
|
||||
|
||||
/**
|
||||
* @define {boolean} Turning on this flag does NOT change the behavior of JSPB
|
||||
* and only affects private internal state. It may, however, break some
|
||||
@ -212,8 +222,8 @@ goog.define('jspb.Message.ASSUME_LOCAL_ARRAYS', false);
|
||||
* mutates its internal state.
|
||||
* Projects are advised to turn this flag always on.
|
||||
*/
|
||||
goog.define('jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS', COMPILED);
|
||||
// TODO(b/19419436) Turn this on by default.
|
||||
goog.define('jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS', true);
|
||||
// TODO(b/19419436): Delete this flag.
|
||||
|
||||
|
||||
/**
|
||||
@ -277,6 +287,13 @@ jspb.Message.prototype.messageId_;
|
||||
jspb.Message.prototype.convertedFloatingPointFields_;
|
||||
|
||||
|
||||
/**
|
||||
* Repeated fields numbers.
|
||||
* @protected {?Array<number>|undefined}
|
||||
*/
|
||||
jspb.Message.prototype.repeatedFields;
|
||||
|
||||
|
||||
/**
|
||||
* The xid of this proto type (The same for all instances of a proto). Provides
|
||||
* a way to identify a proto by stable obfuscated name.
|
||||
@ -323,6 +340,18 @@ jspb.Message.getIndex_ = function(msg, fieldNumber) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the tag number based on the index in msg.array.
|
||||
* @param {!jspb.Message} msg Message for which we're calculating an index.
|
||||
* @param {number} index The tag number.
|
||||
* @return {number} The field number.
|
||||
* @private
|
||||
*/
|
||||
jspb.Message.getFieldNumber_ = function(msg, index) {
|
||||
return index - msg.arrayIndexOffset_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes a JsPb Message.
|
||||
* @param {!jspb.Message} msg The JsPb proto to modify.
|
||||
@ -353,6 +382,13 @@ jspb.Message.initialize = function(
|
||||
jspb.Message.initPivotAndExtensionObject_(msg, suggestedPivot);
|
||||
msg.convertedFloatingPointFields_ = {};
|
||||
|
||||
if (!jspb.Message.SERIALIZE_EMPTY_TRAILING_FIELDS) {
|
||||
// TODO(jakubvrana): This is same for all instances, move to prototype.
|
||||
// TODO(jakubvrana): There are indexOf calls on this in serializtion,
|
||||
// consider switching to a set.
|
||||
msg.repeatedFields = repeatedFields;
|
||||
}
|
||||
|
||||
if (repeatedFields) {
|
||||
for (var i = 0; i < repeatedFields.length; i++) {
|
||||
var fieldNumber = repeatedFields[i];
|
||||
@ -376,8 +412,9 @@ jspb.Message.initialize = function(
|
||||
if (opt_oneofFields && opt_oneofFields.length) {
|
||||
// Compute the oneof case for each union. This ensures only one value is
|
||||
// set in the union.
|
||||
goog.array.forEach(
|
||||
opt_oneofFields, goog.partial(jspb.Message.computeOneofCase, msg));
|
||||
for (var i = 0; i < opt_oneofFields.length; i++) {
|
||||
jspb.Message.computeOneofCase(msg, opt_oneofFields[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -428,7 +465,7 @@ jspb.Message.initPivotAndExtensionObject_ = function(msg, suggestedPivot) {
|
||||
// in Safari on iOS 8. See the description of CL/86511464 for details.
|
||||
if (obj && typeof obj == 'object' && !jspb.Message.isArray_(obj) &&
|
||||
!(jspb.Message.SUPPORTS_UINT8ARRAY_ && obj instanceof Uint8Array)) {
|
||||
msg.pivot_ = foundIndex - msg.arrayIndexOffset_;
|
||||
msg.pivot_ = jspb.Message.getFieldNumber_(msg, foundIndex);
|
||||
msg.extensionObject_ = obj;
|
||||
return;
|
||||
}
|
||||
@ -1043,14 +1080,15 @@ jspb.Message.computeOneofCase = function(msg, oneof) {
|
||||
var oneofField;
|
||||
var oneofValue;
|
||||
|
||||
goog.array.forEach(oneof, function(fieldNumber) {
|
||||
for (var i = 0; i < oneof.length; i++) {
|
||||
var fieldNumber = oneof[i];
|
||||
var value = jspb.Message.getField(msg, fieldNumber);
|
||||
if (goog.isDefAndNotNull(value)) {
|
||||
if (value != null) {
|
||||
oneofField = fieldNumber;
|
||||
oneofValue = value;
|
||||
jspb.Message.setField(msg, fieldNumber, undefined);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (oneofField) {
|
||||
// NB: We know the value is unique, so we can call jspb.Message.setField
|
||||
@ -1241,7 +1279,7 @@ jspb.Message.addToRepeatedWrapperField = function(
|
||||
* dead code removal.
|
||||
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
|
||||
* for transitional soy proto support: http://goto/soy-param-migration
|
||||
* @return {!Object.<string, Object>} A map of proto or Soy objects.
|
||||
* @return {!Object<string, Object>} A map of proto or Soy objects.
|
||||
* @template T
|
||||
*/
|
||||
jspb.Message.toMap = function(
|
||||
@ -1318,7 +1356,7 @@ jspb.Message.prototype.toString = function() {
|
||||
|
||||
/**
|
||||
* Gets the value of the extension field from the extended object.
|
||||
* @param {jspb.ExtensionFieldInfo.<T>} fieldInfo Specifies the field to get.
|
||||
* @param {jspb.ExtensionFieldInfo<T>} fieldInfo Specifies the field to get.
|
||||
* @return {T} The value of the field.
|
||||
* @template T
|
||||
*/
|
||||
@ -1705,7 +1743,11 @@ jspb.Message.registry_ = {};
|
||||
* non-MessageSet. We special case MessageSet so that we do not need
|
||||
* to goog.require MessageSet from classes that extends MessageSet.
|
||||
*
|
||||
* @type {!Object.<number, jspb.ExtensionFieldInfo>}
|
||||
* @type {!Object<number, jspb.ExtensionFieldInfo>}
|
||||
*/
|
||||
jspb.Message.messageSetExtensions = {};
|
||||
|
||||
/**
|
||||
* @type {!Object<number, jspb.ExtensionFieldBinaryInfo>}
|
||||
*/
|
||||
jspb.Message.messageSetExtensionsBinary = {};
|
||||
|
@ -34,6 +34,7 @@ goog.setTestOnly();
|
||||
|
||||
goog.require('goog.json');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.testing.PropertyReplacer');
|
||||
goog.require('goog.testing.asserts');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
@ -85,6 +86,16 @@ goog.require('proto.jspb.test.TestExtensionsMessage');
|
||||
|
||||
|
||||
describe('Message test suite', function() {
|
||||
var stubs = new goog.testing.PropertyReplacer();
|
||||
|
||||
beforeEach(function() {
|
||||
stubs.set(jspb.Message, 'SERIALIZE_EMPTY_TRAILING_FIELDS', false);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
stubs.reset();
|
||||
});
|
||||
|
||||
it('testEmptyProto', function() {
|
||||
var empty1 = new proto.jspb.test.Empty([]);
|
||||
var empty2 = new proto.jspb.test.Empty([]);
|
||||
|
@ -135,17 +135,18 @@ typedef GPB_ENUM(GPBAny_FieldNumber) {
|
||||
@interface GPBAny : GPBMessage
|
||||
|
||||
/**
|
||||
* A URL/resource name whose content describes the type of the
|
||||
* serialized protocol buffer message.
|
||||
* A URL/resource name that uniquely identifies the type of the serialized
|
||||
* protocol buffer message. The last segment of the URL's path must represent
|
||||
* the fully qualified name of the type (as in
|
||||
* `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||
* (e.g., leading "." is not accepted).
|
||||
*
|
||||
* For URLs which use the scheme `http`, `https`, or no scheme, the
|
||||
* following restrictions and interpretations apply:
|
||||
* In practice, teams usually precompile into the binary all types that they
|
||||
* expect it to use in the context of Any. However, for URLs which use the
|
||||
* scheme `http`, `https`, or no scheme, one can optionally set up a type
|
||||
* server that maps type URLs to message definitions as follows:
|
||||
*
|
||||
* * If no scheme is provided, `https` is assumed.
|
||||
* * The last segment of the URL's path must represent the fully
|
||||
* qualified name of the type (as in `path/google.protobuf.Duration`).
|
||||
* The name should be in a canonical form (e.g., leading "." is
|
||||
* not accepted).
|
||||
* * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
* value in binary format, or produce an error.
|
||||
* * Applications are allowed to cache lookup results based on the
|
||||
@ -154,6 +155,10 @@ typedef GPB_ENUM(GPBAny_FieldNumber) {
|
||||
* on changes to types. (Use versioned type names to manage
|
||||
* breaking changes.)
|
||||
*
|
||||
* Note: this functionality is not currently available in the official
|
||||
* protobuf release, and it is not used for type URLs beginning with
|
||||
* type.googleapis.com.
|
||||
*
|
||||
* Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
* used with implementation specific semantics.
|
||||
**/
|
||||
|
@ -126,8 +126,8 @@ typedef GPB_ENUM(GPBTimestamp_FieldNumber) {
|
||||
* to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
|
||||
* with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
||||
* can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||
* http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--)
|
||||
* to obtain a formatter capable of generating timestamps in this format.
|
||||
* http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
|
||||
* ) to obtain a formatter capable of generating timestamps in this format.
|
||||
**/
|
||||
@interface GPBTimestamp : GPBMessage
|
||||
|
||||
|
@ -41,8 +41,8 @@ from google.protobuf.internal import api_implementation
|
||||
_USE_C_DESCRIPTORS = False
|
||||
if api_implementation.Type() == 'cpp':
|
||||
# Used by MakeDescriptor in cpp mode
|
||||
import binascii
|
||||
import os
|
||||
import uuid
|
||||
from google.protobuf.pyext import _message
|
||||
_USE_C_DESCRIPTORS = getattr(_message, '_USE_C_DESCRIPTORS', False)
|
||||
|
||||
@ -952,7 +952,7 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True,
|
||||
# imported ones. We need to specify a file name so the descriptor pool
|
||||
# accepts our FileDescriptorProto, but it is not important what that file
|
||||
# name is actually set to.
|
||||
proto_name = str(uuid.uuid4())
|
||||
proto_name = binascii.hexlify(os.urandom(16)).decode('ascii')
|
||||
|
||||
if package:
|
||||
file_descriptor_proto.name = os.path.join(package.replace('.', '/'),
|
||||
|
@ -32,6 +32,8 @@
|
||||
|
||||
__author__ = 'matthewtoia@google.com (Matt Toia)'
|
||||
|
||||
import warnings
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
pass
|
||||
@ -64,21 +66,20 @@ class DescriptorDatabase(object):
|
||||
elif self._file_desc_protos_by_file[proto_name] != file_desc_proto:
|
||||
raise DescriptorDatabaseConflictingDefinitionError(
|
||||
'%s already added, but with different descriptor.' % proto_name)
|
||||
else:
|
||||
return
|
||||
|
||||
# Add all the top-level descriptors to the index.
|
||||
package = file_desc_proto.package
|
||||
for message in file_desc_proto.message_type:
|
||||
self._file_desc_protos_by_symbol.update(
|
||||
(name, file_desc_proto) for name in _ExtractSymbols(message, package))
|
||||
for name in _ExtractSymbols(message, package):
|
||||
self._AddSymbol(name, file_desc_proto)
|
||||
for enum in file_desc_proto.enum_type:
|
||||
self._file_desc_protos_by_symbol[
|
||||
'.'.join((package, enum.name))] = file_desc_proto
|
||||
self._AddSymbol(('.'.join((package, enum.name))), file_desc_proto)
|
||||
for extension in file_desc_proto.extension:
|
||||
self._file_desc_protos_by_symbol[
|
||||
'.'.join((package, extension.name))] = file_desc_proto
|
||||
self._AddSymbol(('.'.join((package, extension.name))), file_desc_proto)
|
||||
for service in file_desc_proto.service:
|
||||
self._file_desc_protos_by_symbol[
|
||||
'.'.join((package, service.name))] = file_desc_proto
|
||||
self._AddSymbol(('.'.join((package, service.name))), file_desc_proto)
|
||||
|
||||
def FindFileByName(self, name):
|
||||
"""Finds the file descriptor proto by file name.
|
||||
@ -132,6 +133,15 @@ class DescriptorDatabase(object):
|
||||
top_level, _, _ = symbol.rpartition('.')
|
||||
return self._file_desc_protos_by_symbol[top_level]
|
||||
|
||||
def _AddSymbol(self, name, file_desc_proto):
|
||||
if name in self._file_desc_protos_by_symbol:
|
||||
warn_msg = ('Conflict register for file "' + file_desc_proto.name +
|
||||
'": ' + name +
|
||||
' is already defined in file "' +
|
||||
self._file_desc_protos_by_symbol[name].name + '"')
|
||||
warnings.warn(warn_msg, RuntimeWarning)
|
||||
self._file_desc_protos_by_symbol[name] = file_desc_proto
|
||||
|
||||
|
||||
def _ExtractSymbols(desc_proto, package):
|
||||
"""Pulls out all the symbols from a descriptor proto.
|
||||
|
@ -58,6 +58,7 @@ directly instead of this class.
|
||||
__author__ = 'matthewtoia@google.com (Matt Toia)'
|
||||
|
||||
import collections
|
||||
import warnings
|
||||
|
||||
from google.protobuf import descriptor
|
||||
from google.protobuf import descriptor_database
|
||||
@ -136,6 +137,29 @@ class DescriptorPool(object):
|
||||
self._extensions_by_name = collections.defaultdict(dict)
|
||||
self._extensions_by_number = collections.defaultdict(dict)
|
||||
|
||||
def _CheckConflictRegister(self, desc):
|
||||
"""Check if the descriptor name conflicts with another of the same name.
|
||||
|
||||
Args:
|
||||
desc: Descriptor of a message, enum, service or extension.
|
||||
"""
|
||||
desc_name = desc.full_name
|
||||
for register, descriptor_type in [
|
||||
(self._descriptors, descriptor.Descriptor),
|
||||
(self._enum_descriptors, descriptor.EnumDescriptor),
|
||||
(self._service_descriptors, descriptor.ServiceDescriptor),
|
||||
(self._toplevel_extensions, descriptor.FieldDescriptor)]:
|
||||
if desc_name in register:
|
||||
file_name = register[desc_name].file.name
|
||||
if not isinstance(desc, descriptor_type) or (
|
||||
file_name != desc.file.name):
|
||||
warn_msg = ('Conflict register for file "' + desc.file.name +
|
||||
'": ' + desc_name +
|
||||
' is already defined in file "' +
|
||||
file_name + '"')
|
||||
warnings.warn(warn_msg, RuntimeWarning)
|
||||
return
|
||||
|
||||
def Add(self, file_desc_proto):
|
||||
"""Adds the FileDescriptorProto and its types to this pool.
|
||||
|
||||
@ -172,6 +196,8 @@ class DescriptorPool(object):
|
||||
if not isinstance(desc, descriptor.Descriptor):
|
||||
raise TypeError('Expected instance of descriptor.Descriptor.')
|
||||
|
||||
self._CheckConflictRegister(desc)
|
||||
|
||||
self._descriptors[desc.full_name] = desc
|
||||
self._AddFileDescriptor(desc.file)
|
||||
|
||||
@ -187,6 +213,7 @@ class DescriptorPool(object):
|
||||
if not isinstance(enum_desc, descriptor.EnumDescriptor):
|
||||
raise TypeError('Expected instance of descriptor.EnumDescriptor.')
|
||||
|
||||
self._CheckConflictRegister(enum_desc)
|
||||
self._enum_descriptors[enum_desc.full_name] = enum_desc
|
||||
self._AddFileDescriptor(enum_desc.file)
|
||||
|
||||
@ -200,6 +227,7 @@ class DescriptorPool(object):
|
||||
if not isinstance(service_desc, descriptor.ServiceDescriptor):
|
||||
raise TypeError('Expected instance of descriptor.ServiceDescriptor.')
|
||||
|
||||
self._CheckConflictRegister(service_desc)
|
||||
self._service_descriptors[service_desc.full_name] = service_desc
|
||||
|
||||
def AddExtensionDescriptor(self, extension):
|
||||
@ -219,6 +247,7 @@ class DescriptorPool(object):
|
||||
raise TypeError('Expected an extension descriptor.')
|
||||
|
||||
if extension.extension_scope is None:
|
||||
self._CheckConflictRegister(extension)
|
||||
self._toplevel_extensions[extension.full_name] = extension
|
||||
|
||||
try:
|
||||
@ -689,6 +718,7 @@ class DescriptorPool(object):
|
||||
fields[field_index].containing_oneof = oneofs[oneof_index]
|
||||
|
||||
scope[_PrefixWithDot(desc_name)] = desc
|
||||
self._CheckConflictRegister(desc)
|
||||
self._descriptors[desc_name] = desc
|
||||
return desc
|
||||
|
||||
@ -727,6 +757,7 @@ class DescriptorPool(object):
|
||||
containing_type=containing_type,
|
||||
options=_OptionsOrNone(enum_proto))
|
||||
scope['.%s' % enum_name] = desc
|
||||
self._CheckConflictRegister(desc)
|
||||
self._enum_descriptors[enum_name] = desc
|
||||
return desc
|
||||
|
||||
@ -923,6 +954,7 @@ class DescriptorPool(object):
|
||||
methods=methods,
|
||||
options=_OptionsOrNone(service_proto),
|
||||
file=file_desc)
|
||||
self._CheckConflictRegister(desc)
|
||||
self._service_descriptors[service_name] = desc
|
||||
return desc
|
||||
|
||||
|
@ -38,6 +38,7 @@ try:
|
||||
import unittest2 as unittest #PY26
|
||||
except ImportError:
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
from google.protobuf import unittest_pb2
|
||||
from google.protobuf import descriptor_pb2
|
||||
@ -98,6 +99,26 @@ class DescriptorDatabaseTest(unittest.TestCase):
|
||||
db.FindFileContainingSymbol,
|
||||
'protobuf_unittest.NoneMessage')
|
||||
|
||||
def testConflictRegister(self):
|
||||
db = descriptor_database.DescriptorDatabase()
|
||||
unittest_fd = descriptor_pb2.FileDescriptorProto.FromString(
|
||||
unittest_pb2.DESCRIPTOR.serialized_pb)
|
||||
db.Add(unittest_fd)
|
||||
conflict_fd = descriptor_pb2.FileDescriptorProto.FromString(
|
||||
unittest_pb2.DESCRIPTOR.serialized_pb)
|
||||
conflict_fd.name = 'other_file'
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
# Cause all warnings to always be triggered.
|
||||
warnings.simplefilter('always')
|
||||
db.Add(conflict_fd)
|
||||
self.assertTrue(len(w))
|
||||
self.assertIs(w[0].category, RuntimeWarning)
|
||||
self.assertIn('Conflict register for file "other_file": ',
|
||||
str(w[0].message))
|
||||
self.assertIn('already defined in file '
|
||||
'"google/protobuf/unittest.proto"',
|
||||
str(w[0].message))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -34,8 +34,10 @@
|
||||
|
||||
__author__ = 'matthewtoia@google.com (Matt Toia)'
|
||||
|
||||
import copy
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
try:
|
||||
import unittest2 as unittest #PY26
|
||||
@ -119,6 +121,14 @@ class DescriptorPoolTestBase(object):
|
||||
self.assertEqual('google/protobuf/unittest.proto',
|
||||
file_desc5.name)
|
||||
|
||||
# Tests the generated pool.
|
||||
assert descriptor_pool.Default().FindFileContainingSymbol(
|
||||
'google.protobuf.python.internal.Factory2Message.one_more_field')
|
||||
assert descriptor_pool.Default().FindFileContainingSymbol(
|
||||
'google.protobuf.python.internal.another_field')
|
||||
assert descriptor_pool.Default().FindFileContainingSymbol(
|
||||
'protobuf_unittest.TestService')
|
||||
|
||||
def testFindFileContainingSymbolFailure(self):
|
||||
with self.assertRaises(KeyError):
|
||||
self.pool.FindFileContainingSymbol('Does not exist')
|
||||
@ -492,6 +502,52 @@ class DescriptorPoolTestBase(object):
|
||||
TEST1_FILE.CheckFile(self, self.pool)
|
||||
TEST2_FILE.CheckFile(self, self.pool)
|
||||
|
||||
def testConflictRegister(self):
|
||||
if isinstance(self, SecondaryDescriptorFromDescriptorDB):
|
||||
if api_implementation.Type() == 'cpp':
|
||||
# Cpp extension cannot call Add on a DescriptorPool
|
||||
# that uses a DescriptorDatabase.
|
||||
# TODO(jieluo): Fix python and cpp extension diff.
|
||||
return
|
||||
unittest_fd = descriptor_pb2.FileDescriptorProto.FromString(
|
||||
unittest_pb2.DESCRIPTOR.serialized_pb)
|
||||
conflict_fd = copy.deepcopy(unittest_fd)
|
||||
conflict_fd.name = 'other_file'
|
||||
if api_implementation.Type() == 'cpp':
|
||||
try:
|
||||
self.pool.Add(unittest_fd)
|
||||
self.pool.Add(conflict_fd)
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
# Cause all warnings to always be triggered.
|
||||
warnings.simplefilter('always')
|
||||
pool = copy.deepcopy(self.pool)
|
||||
# No warnings to add the same descriptors.
|
||||
file_descriptor = unittest_pb2.DESCRIPTOR
|
||||
pool.AddDescriptor(
|
||||
file_descriptor.message_types_by_name['TestAllTypes'])
|
||||
pool.AddEnumDescriptor(
|
||||
file_descriptor.enum_types_by_name['ForeignEnum'])
|
||||
pool.AddServiceDescriptor(
|
||||
file_descriptor.services_by_name['TestService'])
|
||||
pool.AddExtensionDescriptor(
|
||||
file_descriptor.extensions_by_name['optional_int32_extension'])
|
||||
self.assertEqual(len(w), 0)
|
||||
# Check warnings for conflict descriptors with the same name.
|
||||
pool.Add(unittest_fd)
|
||||
pool.Add(conflict_fd)
|
||||
pool.FindFileByName(unittest_fd.name)
|
||||
pool.FindFileByName(conflict_fd.name)
|
||||
self.assertTrue(len(w))
|
||||
self.assertIs(w[0].category, RuntimeWarning)
|
||||
self.assertIn('Conflict register for file "other_file": ',
|
||||
str(w[0].message))
|
||||
self.assertIn('already defined in file '
|
||||
'"google/protobuf/unittest.proto"',
|
||||
str(w[0].message))
|
||||
|
||||
|
||||
class DefaultDescriptorPoolTest(DescriptorPoolTestBase, unittest.TestCase):
|
||||
|
||||
|
@ -418,7 +418,8 @@ def _VarintBytes(value):
|
||||
def TagBytes(field_number, wire_type):
|
||||
"""Encode the given tag and return the bytes. Only called at startup."""
|
||||
|
||||
return six.binary_type( _VarintBytes(wire_format.PackTag(field_number, wire_type)) )
|
||||
return six.binary_type(
|
||||
_VarintBytes(wire_format.PackTag(field_number, wire_type)))
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# As with sizers (see above), we have a number of common encoder
|
||||
|
@ -828,6 +828,10 @@ class Proto2Tests(TextFormatBase):
|
||||
' }\n'
|
||||
' }\n'
|
||||
' [unknown_extension]: 5\n'
|
||||
' [unknown_extension_with_number_field] {\n'
|
||||
' 1: "some_field"\n'
|
||||
' 2: -0.451\n'
|
||||
' }\n'
|
||||
'}\n')
|
||||
text_format.Parse(text, message, allow_unknown_extension=True)
|
||||
golden = 'message_set {\n}\n'
|
||||
@ -894,7 +898,6 @@ class Proto2Tests(TextFormatBase):
|
||||
message = unittest_mset_pb2.TestMessageSetContainer()
|
||||
malformed = ('message_set {\n'
|
||||
' unknown_field: true\n'
|
||||
' \n' # Missing '>' here.
|
||||
'}\n')
|
||||
six.assertRaisesRegex(self,
|
||||
text_format.ParseError,
|
||||
@ -906,7 +909,7 @@ class Proto2Tests(TextFormatBase):
|
||||
message,
|
||||
allow_unknown_extension=True)
|
||||
|
||||
# Parse known extension correcty.
|
||||
# Parse known extension correctly.
|
||||
message = unittest_mset_pb2.TestMessageSetContainer()
|
||||
text = ('message_set {\n'
|
||||
' [protobuf_unittest.TestMessageSetExtension1] {\n'
|
||||
|
@ -957,55 +957,55 @@ static int Count(PyContainer* self) {
|
||||
return GetDescriptor(self)->field_count();
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByName(PyContainer* self, const string& name) {
|
||||
static const void* GetByName(PyContainer* self, const string& name) {
|
||||
return GetDescriptor(self)->FindFieldByName(name);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByCamelcaseName(PyContainer* self,
|
||||
static const void* GetByCamelcaseName(PyContainer* self,
|
||||
const string& name) {
|
||||
return GetDescriptor(self)->FindFieldByCamelcaseName(name);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByNumber(PyContainer* self, int number) {
|
||||
static const void* GetByNumber(PyContainer* self, int number) {
|
||||
return GetDescriptor(self)->FindFieldByNumber(number);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
return GetDescriptor(self)->field(index);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyFieldDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyFieldDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static const string& GetItemName(ItemDescriptor item) {
|
||||
return item->name();
|
||||
static const string& GetItemName(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->name();
|
||||
}
|
||||
|
||||
static const string& GetItemCamelcaseName(ItemDescriptor item) {
|
||||
return item->camelcase_name();
|
||||
static const string& GetItemCamelcaseName(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->camelcase_name();
|
||||
}
|
||||
|
||||
static int GetItemNumber(ItemDescriptor item) {
|
||||
return item->number();
|
||||
static int GetItemNumber(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->number();
|
||||
}
|
||||
|
||||
static int GetItemIndex(ItemDescriptor item) {
|
||||
return item->index();
|
||||
static int GetItemIndex(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->index();
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"MessageFields",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)GetByName,
|
||||
(GetByCamelcaseNameMethod)GetByCamelcaseName,
|
||||
(GetByNumberMethod)GetByNumber,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)GetItemName,
|
||||
(GetItemCamelcaseNameMethod)GetItemCamelcaseName,
|
||||
(GetItemNumberMethod)GetItemNumber,
|
||||
(GetItemIndexMethod)GetItemIndex,
|
||||
Count,
|
||||
GetByIndex,
|
||||
GetByName,
|
||||
GetByCamelcaseName,
|
||||
GetByNumber,
|
||||
NewObjectFromItem,
|
||||
GetItemName,
|
||||
GetItemCamelcaseName,
|
||||
GetItemNumber,
|
||||
GetItemIndex,
|
||||
};
|
||||
|
||||
} // namespace fields
|
||||
@ -1035,38 +1035,38 @@ static int Count(PyContainer* self) {
|
||||
return GetDescriptor(self)->nested_type_count();
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByName(PyContainer* self, const string& name) {
|
||||
static const void* GetByName(PyContainer* self, const string& name) {
|
||||
return GetDescriptor(self)->FindNestedTypeByName(name);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
return GetDescriptor(self)->nested_type(index);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyMessageDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyMessageDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static const string& GetItemName(ItemDescriptor item) {
|
||||
return item->name();
|
||||
static const string& GetItemName(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->name();
|
||||
}
|
||||
|
||||
static int GetItemIndex(ItemDescriptor item) {
|
||||
return item->index();
|
||||
static int GetItemIndex(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->index();
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"MessageNestedTypes",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)GetByName,
|
||||
(GetByCamelcaseNameMethod)NULL,
|
||||
(GetByNumberMethod)NULL,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)GetItemName,
|
||||
(GetItemCamelcaseNameMethod)NULL,
|
||||
(GetItemNumberMethod)NULL,
|
||||
(GetItemIndexMethod)GetItemIndex,
|
||||
Count,
|
||||
GetByIndex,
|
||||
GetByName,
|
||||
NULL,
|
||||
NULL,
|
||||
NewObjectFromItem,
|
||||
GetItemName,
|
||||
NULL,
|
||||
NULL,
|
||||
GetItemIndex,
|
||||
};
|
||||
|
||||
} // namespace nested_types
|
||||
@ -1087,38 +1087,38 @@ static int Count(PyContainer* self) {
|
||||
return GetDescriptor(self)->enum_type_count();
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByName(PyContainer* self, const string& name) {
|
||||
static const void* GetByName(PyContainer* self, const string& name) {
|
||||
return GetDescriptor(self)->FindEnumTypeByName(name);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
return GetDescriptor(self)->enum_type(index);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyEnumDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyEnumDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static const string& GetItemName(ItemDescriptor item) {
|
||||
return item->name();
|
||||
static const string& GetItemName(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->name();
|
||||
}
|
||||
|
||||
static int GetItemIndex(ItemDescriptor item) {
|
||||
return item->index();
|
||||
static int GetItemIndex(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->index();
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"MessageNestedEnums",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)GetByName,
|
||||
(GetByCamelcaseNameMethod)NULL,
|
||||
(GetByNumberMethod)NULL,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)GetItemName,
|
||||
(GetItemCamelcaseNameMethod)NULL,
|
||||
(GetItemNumberMethod)NULL,
|
||||
(GetItemIndexMethod)GetItemIndex,
|
||||
Count,
|
||||
GetByIndex,
|
||||
GetByName,
|
||||
NULL,
|
||||
NULL,
|
||||
NewObjectFromItem,
|
||||
GetItemName,
|
||||
NULL,
|
||||
NULL,
|
||||
GetItemIndex,
|
||||
};
|
||||
|
||||
} // namespace enums
|
||||
@ -1150,11 +1150,11 @@ static int Count(PyContainer* self) {
|
||||
return count;
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByName(PyContainer* self, const string& name) {
|
||||
static const void* GetByName(PyContainer* self, const string& name) {
|
||||
return GetDescriptor(self)->FindEnumValueByName(name);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
// This is not optimal, but the number of enums *types* in a given message
|
||||
// is small. This function is only used when iterating over the mapping.
|
||||
const EnumDescriptor* enum_type = NULL;
|
||||
@ -1173,26 +1173,27 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
return enum_type->value(index);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyEnumValueDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyEnumValueDescriptor_FromDescriptor(
|
||||
static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static const string& GetItemName(ItemDescriptor item) {
|
||||
return item->name();
|
||||
static const string& GetItemName(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->name();
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"MessageEnumValues",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)GetByName,
|
||||
(GetByCamelcaseNameMethod)NULL,
|
||||
(GetByNumberMethod)NULL,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)GetItemName,
|
||||
(GetItemCamelcaseNameMethod)NULL,
|
||||
(GetItemNumberMethod)NULL,
|
||||
(GetItemIndexMethod)NULL,
|
||||
Count,
|
||||
GetByIndex,
|
||||
GetByName,
|
||||
NULL,
|
||||
NULL,
|
||||
NewObjectFromItem,
|
||||
GetItemName,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
} // namespace enumvalues
|
||||
@ -1209,38 +1210,38 @@ static int Count(PyContainer* self) {
|
||||
return GetDescriptor(self)->extension_count();
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByName(PyContainer* self, const string& name) {
|
||||
static const void* GetByName(PyContainer* self, const string& name) {
|
||||
return GetDescriptor(self)->FindExtensionByName(name);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
return GetDescriptor(self)->extension(index);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyFieldDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyFieldDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static const string& GetItemName(ItemDescriptor item) {
|
||||
return item->name();
|
||||
static const string& GetItemName(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->name();
|
||||
}
|
||||
|
||||
static int GetItemIndex(ItemDescriptor item) {
|
||||
return item->index();
|
||||
static int GetItemIndex(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->index();
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"MessageExtensions",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)GetByName,
|
||||
(GetByCamelcaseNameMethod)NULL,
|
||||
(GetByNumberMethod)NULL,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)GetItemName,
|
||||
(GetItemCamelcaseNameMethod)NULL,
|
||||
(GetItemNumberMethod)NULL,
|
||||
(GetItemIndexMethod)GetItemIndex,
|
||||
Count,
|
||||
GetByIndex,
|
||||
GetByName,
|
||||
NULL,
|
||||
NULL,
|
||||
NewObjectFromItem,
|
||||
GetItemName,
|
||||
NULL,
|
||||
NULL,
|
||||
GetItemIndex,
|
||||
};
|
||||
|
||||
} // namespace extensions
|
||||
@ -1261,38 +1262,38 @@ static int Count(PyContainer* self) {
|
||||
return GetDescriptor(self)->oneof_decl_count();
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByName(PyContainer* self, const string& name) {
|
||||
static const void* GetByName(PyContainer* self, const string& name) {
|
||||
return GetDescriptor(self)->FindOneofByName(name);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
return GetDescriptor(self)->oneof_decl(index);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyOneofDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyOneofDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static const string& GetItemName(ItemDescriptor item) {
|
||||
return item->name();
|
||||
static const string& GetItemName(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->name();
|
||||
}
|
||||
|
||||
static int GetItemIndex(ItemDescriptor item) {
|
||||
return item->index();
|
||||
static int GetItemIndex(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->index();
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"MessageOneofs",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)GetByName,
|
||||
(GetByCamelcaseNameMethod)NULL,
|
||||
(GetByNumberMethod)NULL,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)GetItemName,
|
||||
(GetItemCamelcaseNameMethod)NULL,
|
||||
(GetItemNumberMethod)NULL,
|
||||
(GetItemIndexMethod)GetItemIndex,
|
||||
Count,
|
||||
GetByIndex,
|
||||
GetByName,
|
||||
NULL,
|
||||
NULL,
|
||||
NewObjectFromItem,
|
||||
GetItemName,
|
||||
NULL,
|
||||
NULL,
|
||||
GetItemIndex,
|
||||
};
|
||||
|
||||
} // namespace oneofs
|
||||
@ -1323,46 +1324,47 @@ static int Count(PyContainer* self) {
|
||||
return GetDescriptor(self)->value_count();
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
return GetDescriptor(self)->value(index);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByName(PyContainer* self, const string& name) {
|
||||
static const void* GetByName(PyContainer* self, const string& name) {
|
||||
return GetDescriptor(self)->FindValueByName(name);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByNumber(PyContainer* self, int number) {
|
||||
static const void* GetByNumber(PyContainer* self, int number) {
|
||||
return GetDescriptor(self)->FindValueByNumber(number);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyEnumValueDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyEnumValueDescriptor_FromDescriptor(
|
||||
static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static const string& GetItemName(ItemDescriptor item) {
|
||||
return item->name();
|
||||
static const string& GetItemName(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->name();
|
||||
}
|
||||
|
||||
static int GetItemNumber(ItemDescriptor item) {
|
||||
return item->number();
|
||||
static int GetItemNumber(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->number();
|
||||
}
|
||||
|
||||
static int GetItemIndex(ItemDescriptor item) {
|
||||
return item->index();
|
||||
static int GetItemIndex(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->index();
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"EnumValues",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)GetByName,
|
||||
(GetByCamelcaseNameMethod)NULL,
|
||||
(GetByNumberMethod)GetByNumber,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)GetItemName,
|
||||
(GetItemCamelcaseNameMethod)NULL,
|
||||
(GetItemNumberMethod)GetItemNumber,
|
||||
(GetItemIndexMethod)GetItemIndex,
|
||||
Count,
|
||||
GetByIndex,
|
||||
GetByName,
|
||||
NULL,
|
||||
GetByNumber,
|
||||
NewObjectFromItem,
|
||||
GetItemName,
|
||||
NULL,
|
||||
GetItemNumber,
|
||||
GetItemIndex,
|
||||
};
|
||||
|
||||
} // namespace enumvalues
|
||||
@ -1397,30 +1399,30 @@ static int Count(PyContainer* self) {
|
||||
return GetDescriptor(self)->field_count();
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
return GetDescriptor(self)->field(index);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyFieldDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyFieldDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static int GetItemIndex(ItemDescriptor item) {
|
||||
return item->index_in_oneof();
|
||||
static int GetItemIndex(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->index_in_oneof();
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"OneofFields",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)NULL,
|
||||
(GetByCamelcaseNameMethod)NULL,
|
||||
(GetByNumberMethod)NULL,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)NULL,
|
||||
(GetItemCamelcaseNameMethod)NULL,
|
||||
(GetItemNumberMethod)NULL,
|
||||
(GetItemIndexMethod)GetItemIndex,
|
||||
Count,
|
||||
GetByIndex,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NewObjectFromItem,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
GetItemIndex,
|
||||
};
|
||||
|
||||
} // namespace fields
|
||||
@ -1447,38 +1449,38 @@ static int Count(PyContainer* self) {
|
||||
return GetDescriptor(self)->method_count();
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByName(PyContainer* self, const string& name) {
|
||||
static const void* GetByName(PyContainer* self, const string& name) {
|
||||
return GetDescriptor(self)->FindMethodByName(name);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
return GetDescriptor(self)->method(index);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyMethodDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyMethodDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static const string& GetItemName(ItemDescriptor item) {
|
||||
return item->name();
|
||||
static const string& GetItemName(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->name();
|
||||
}
|
||||
|
||||
static int GetItemIndex(ItemDescriptor item) {
|
||||
return item->index();
|
||||
static int GetItemIndex(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->index();
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"ServiceMethods",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)GetByName,
|
||||
(GetByCamelcaseNameMethod)NULL,
|
||||
(GetByNumberMethod)NULL,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)GetItemName,
|
||||
(GetItemCamelcaseNameMethod)NULL,
|
||||
(GetItemNumberMethod)NULL,
|
||||
(GetItemIndexMethod)GetItemIndex,
|
||||
Count,
|
||||
GetByIndex,
|
||||
GetByName,
|
||||
NULL,
|
||||
NULL,
|
||||
NewObjectFromItem,
|
||||
GetItemName,
|
||||
NULL,
|
||||
NULL,
|
||||
GetItemIndex,
|
||||
};
|
||||
|
||||
} // namespace methods
|
||||
@ -1509,38 +1511,38 @@ static int Count(PyContainer* self) {
|
||||
return GetDescriptor(self)->message_type_count();
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByName(PyContainer* self, const string& name) {
|
||||
static const void* GetByName(PyContainer* self, const string& name) {
|
||||
return GetDescriptor(self)->FindMessageTypeByName(name);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
return GetDescriptor(self)->message_type(index);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyMessageDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyMessageDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static const string& GetItemName(ItemDescriptor item) {
|
||||
return item->name();
|
||||
static const string& GetItemName(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->name();
|
||||
}
|
||||
|
||||
static int GetItemIndex(ItemDescriptor item) {
|
||||
return item->index();
|
||||
static int GetItemIndex(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->index();
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"FileMessages",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)GetByName,
|
||||
(GetByCamelcaseNameMethod)NULL,
|
||||
(GetByNumberMethod)NULL,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)GetItemName,
|
||||
(GetItemCamelcaseNameMethod)NULL,
|
||||
(GetItemNumberMethod)NULL,
|
||||
(GetItemIndexMethod)GetItemIndex,
|
||||
Count,
|
||||
GetByIndex,
|
||||
GetByName,
|
||||
NULL,
|
||||
NULL,
|
||||
NewObjectFromItem,
|
||||
GetItemName,
|
||||
NULL,
|
||||
NULL,
|
||||
GetItemIndex,
|
||||
};
|
||||
|
||||
} // namespace messages
|
||||
@ -1557,38 +1559,38 @@ static int Count(PyContainer* self) {
|
||||
return GetDescriptor(self)->enum_type_count();
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByName(PyContainer* self, const string& name) {
|
||||
static const void* GetByName(PyContainer* self, const string& name) {
|
||||
return GetDescriptor(self)->FindEnumTypeByName(name);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
return GetDescriptor(self)->enum_type(index);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyEnumDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyEnumDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static const string& GetItemName(ItemDescriptor item) {
|
||||
return item->name();
|
||||
static const string& GetItemName(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->name();
|
||||
}
|
||||
|
||||
static int GetItemIndex(ItemDescriptor item) {
|
||||
return item->index();
|
||||
static int GetItemIndex(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->index();
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"FileEnums",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)GetByName,
|
||||
(GetByCamelcaseNameMethod)NULL,
|
||||
(GetByNumberMethod)NULL,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)GetItemName,
|
||||
(GetItemCamelcaseNameMethod)NULL,
|
||||
(GetItemNumberMethod)NULL,
|
||||
(GetItemIndexMethod)GetItemIndex,
|
||||
Count,
|
||||
GetByIndex,
|
||||
GetByName,
|
||||
NULL,
|
||||
NULL,
|
||||
NewObjectFromItem,
|
||||
GetItemName,
|
||||
NULL,
|
||||
NULL,
|
||||
GetItemIndex,
|
||||
};
|
||||
|
||||
} // namespace enums
|
||||
@ -1605,38 +1607,38 @@ static int Count(PyContainer* self) {
|
||||
return GetDescriptor(self)->extension_count();
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByName(PyContainer* self, const string& name) {
|
||||
static const void* GetByName(PyContainer* self, const string& name) {
|
||||
return GetDescriptor(self)->FindExtensionByName(name);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
return GetDescriptor(self)->extension(index);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyFieldDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyFieldDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static const string& GetItemName(ItemDescriptor item) {
|
||||
return item->name();
|
||||
static const string& GetItemName(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->name();
|
||||
}
|
||||
|
||||
static int GetItemIndex(ItemDescriptor item) {
|
||||
return item->index();
|
||||
static int GetItemIndex(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->index();
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"FileExtensions",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)GetByName,
|
||||
(GetByCamelcaseNameMethod)NULL,
|
||||
(GetByNumberMethod)NULL,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)GetItemName,
|
||||
(GetItemCamelcaseNameMethod)NULL,
|
||||
(GetItemNumberMethod)NULL,
|
||||
(GetItemIndexMethod)GetItemIndex,
|
||||
Count,
|
||||
GetByIndex,
|
||||
GetByName,
|
||||
NULL,
|
||||
NULL,
|
||||
NewObjectFromItem,
|
||||
GetItemName,
|
||||
NULL,
|
||||
NULL,
|
||||
GetItemIndex,
|
||||
};
|
||||
|
||||
} // namespace extensions
|
||||
@ -1653,38 +1655,38 @@ static int Count(PyContainer* self) {
|
||||
return GetDescriptor(self)->service_count();
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByName(PyContainer* self, const string& name) {
|
||||
static const void* GetByName(PyContainer* self, const string& name) {
|
||||
return GetDescriptor(self)->FindServiceByName(name);
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
return GetDescriptor(self)->service(index);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyServiceDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyServiceDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static const string& GetItemName(ItemDescriptor item) {
|
||||
return item->name();
|
||||
static const string& GetItemName(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->name();
|
||||
}
|
||||
|
||||
static int GetItemIndex(ItemDescriptor item) {
|
||||
return item->index();
|
||||
static int GetItemIndex(const void* item) {
|
||||
return static_cast<ItemDescriptor>(item)->index();
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"FileServices",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)GetByName,
|
||||
(GetByCamelcaseNameMethod)NULL,
|
||||
(GetByNumberMethod)NULL,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)GetItemName,
|
||||
(GetItemCamelcaseNameMethod)NULL,
|
||||
(GetItemNumberMethod)NULL,
|
||||
(GetItemIndexMethod)GetItemIndex,
|
||||
Count,
|
||||
GetByIndex,
|
||||
GetByName,
|
||||
NULL,
|
||||
NULL,
|
||||
NewObjectFromItem,
|
||||
GetItemName,
|
||||
NULL,
|
||||
NULL,
|
||||
GetItemIndex,
|
||||
};
|
||||
|
||||
} // namespace services
|
||||
@ -1701,26 +1703,26 @@ static int Count(PyContainer* self) {
|
||||
return GetDescriptor(self)->dependency_count();
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
return GetDescriptor(self)->dependency(index);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyFileDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyFileDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"FileDependencies",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)NULL,
|
||||
(GetByCamelcaseNameMethod)NULL,
|
||||
(GetByNumberMethod)NULL,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)NULL,
|
||||
(GetItemCamelcaseNameMethod)NULL,
|
||||
(GetItemNumberMethod)NULL,
|
||||
(GetItemIndexMethod)NULL,
|
||||
Count,
|
||||
GetByIndex,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NewObjectFromItem,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
} // namespace dependencies
|
||||
@ -1737,26 +1739,26 @@ static int Count(PyContainer* self) {
|
||||
return GetDescriptor(self)->public_dependency_count();
|
||||
}
|
||||
|
||||
static ItemDescriptor GetByIndex(PyContainer* self, int index) {
|
||||
static const void* GetByIndex(PyContainer* self, int index) {
|
||||
return GetDescriptor(self)->public_dependency(index);
|
||||
}
|
||||
|
||||
static PyObject* NewObjectFromItem(ItemDescriptor item) {
|
||||
return PyFileDescriptor_FromDescriptor(item);
|
||||
static PyObject* NewObjectFromItem(const void* item) {
|
||||
return PyFileDescriptor_FromDescriptor(static_cast<ItemDescriptor>(item));
|
||||
}
|
||||
|
||||
static DescriptorContainerDef ContainerDef = {
|
||||
"FilePublicDependencies",
|
||||
(CountMethod)Count,
|
||||
(GetByIndexMethod)GetByIndex,
|
||||
(GetByNameMethod)NULL,
|
||||
(GetByCamelcaseNameMethod)NULL,
|
||||
(GetByNumberMethod)NULL,
|
||||
(NewObjectFromItemMethod)NewObjectFromItem,
|
||||
(GetItemNameMethod)NULL,
|
||||
(GetItemCamelcaseNameMethod)NULL,
|
||||
(GetItemNumberMethod)NULL,
|
||||
(GetItemIndexMethod)NULL,
|
||||
Count,
|
||||
GetByIndex,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NewObjectFromItem,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
} // namespace public_dependencies
|
||||
|
@ -605,18 +605,16 @@ void OutOfRangeError(PyObject* arg) {
|
||||
|
||||
template<class RangeType, class ValueType>
|
||||
bool VerifyIntegerCastAndRange(PyObject* arg, ValueType value) {
|
||||
if
|
||||
GOOGLE_PREDICT_FALSE(value == -1 && PyErr_Occurred()) {
|
||||
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
||||
// Replace it with the same ValueError as pure python protos instead of
|
||||
// the default one.
|
||||
PyErr_Clear();
|
||||
OutOfRangeError(arg);
|
||||
} // Otherwise propagate existing error.
|
||||
return false;
|
||||
if (GOOGLE_PREDICT_FALSE(value == -1 && PyErr_Occurred())) {
|
||||
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
||||
// Replace it with the same ValueError as pure python protos instead of
|
||||
// the default one.
|
||||
PyErr_Clear();
|
||||
OutOfRangeError(arg);
|
||||
} // Otherwise propagate existing error.
|
||||
return false;
|
||||
}
|
||||
if
|
||||
GOOGLE_PREDICT_FALSE(!IsValidNumericCast<RangeType>(value)) {
|
||||
if (GOOGLE_PREDICT_FALSE(!IsValidNumericCast<RangeType>(value))) {
|
||||
OutOfRangeError(arg);
|
||||
return false;
|
||||
}
|
||||
@ -628,26 +626,22 @@ bool CheckAndGetInteger(PyObject* arg, T* value) {
|
||||
// The fast path.
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
// For the typical case, offer a fast path.
|
||||
if
|
||||
GOOGLE_PREDICT_TRUE(PyInt_Check(arg)) {
|
||||
long int_result = PyInt_AsLong(arg);
|
||||
if
|
||||
GOOGLE_PREDICT_TRUE(IsValidNumericCast<T>(int_result)) {
|
||||
*value = static_cast<T>(int_result);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
OutOfRangeError(arg);
|
||||
return false;
|
||||
}
|
||||
if (GOOGLE_PREDICT_TRUE(PyInt_Check(arg))) {
|
||||
long int_result = PyInt_AsLong(arg);
|
||||
if (GOOGLE_PREDICT_TRUE(IsValidNumericCast<T>(int_result))) {
|
||||
*value = static_cast<T>(int_result);
|
||||
return true;
|
||||
} else {
|
||||
OutOfRangeError(arg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// This effectively defines an integer as "an object that can be cast as
|
||||
// an integer and can be used as an ordinal number".
|
||||
// This definition includes everything that implements numbers.Integral
|
||||
// and shouldn't cast the net too wide.
|
||||
if
|
||||
GOOGLE_PREDICT_FALSE(!PyIndex_Check(arg)) {
|
||||
if (GOOGLE_PREDICT_FALSE(!PyIndex_Check(arg))) {
|
||||
FormatTypeError(arg, "int, long");
|
||||
return false;
|
||||
}
|
||||
@ -664,10 +658,9 @@ bool CheckAndGetInteger(PyObject* arg, T* value) {
|
||||
// Unlike PyLong_AsLongLong, PyLong_AsUnsignedLongLong is very
|
||||
// picky about the exact type.
|
||||
PyObject* casted = PyNumber_Long(arg);
|
||||
if
|
||||
GOOGLE_PREDICT_FALSE(casted == NULL) {
|
||||
// Propagate existing error.
|
||||
return false;
|
||||
if (GOOGLE_PREDICT_FALSE(casted == NULL)) {
|
||||
// Propagate existing error.
|
||||
return false;
|
||||
}
|
||||
ulong_result = PyLong_AsUnsignedLongLong(casted);
|
||||
Py_DECREF(casted);
|
||||
@ -690,10 +683,9 @@ bool CheckAndGetInteger(PyObject* arg, T* value) {
|
||||
// Valid subclasses of numbers.Integral should have a __long__() method
|
||||
// so fall back to that.
|
||||
PyObject* casted = PyNumber_Long(arg);
|
||||
if
|
||||
GOOGLE_PREDICT_FALSE(casted == NULL) {
|
||||
// Propagate existing error.
|
||||
return false;
|
||||
if (GOOGLE_PREDICT_FALSE(casted == NULL)) {
|
||||
// Propagate existing error.
|
||||
return false;
|
||||
}
|
||||
long_result = PyLong_AsLongLong(casted);
|
||||
Py_DECREF(casted);
|
||||
@ -717,10 +709,9 @@ template bool CheckAndGetInteger<uint64>(PyObject*, uint64*);
|
||||
|
||||
bool CheckAndGetDouble(PyObject* arg, double* value) {
|
||||
*value = PyFloat_AsDouble(arg);
|
||||
if
|
||||
GOOGLE_PREDICT_FALSE(*value == -1 && PyErr_Occurred()) {
|
||||
FormatTypeError(arg, "int, long, float");
|
||||
return false;
|
||||
if (GOOGLE_PREDICT_FALSE(*value == -1 && PyErr_Occurred())) {
|
||||
FormatTypeError(arg, "int, long, float");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1187,7 +1178,7 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) {
|
||||
continue;
|
||||
}
|
||||
if (descriptor->is_map()) {
|
||||
ScopedPyObjectPtr map(GetAttr(self, name));
|
||||
ScopedPyObjectPtr map(GetAttr(reinterpret_cast<PyObject*>(self), name));
|
||||
const FieldDescriptor* value_descriptor =
|
||||
descriptor->message_type()->FindFieldByName("value");
|
||||
if (value_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
||||
@ -1215,7 +1206,8 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) {
|
||||
}
|
||||
}
|
||||
} else if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
|
||||
ScopedPyObjectPtr container(GetAttr(self, name));
|
||||
ScopedPyObjectPtr container(
|
||||
GetAttr(reinterpret_cast<PyObject*>(self), name));
|
||||
if (container == NULL) {
|
||||
return -1;
|
||||
}
|
||||
@ -1282,7 +1274,8 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) {
|
||||
}
|
||||
}
|
||||
} else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
||||
ScopedPyObjectPtr message(GetAttr(self, name));
|
||||
ScopedPyObjectPtr message(
|
||||
GetAttr(reinterpret_cast<PyObject*>(self), name));
|
||||
if (message == NULL) {
|
||||
return -1;
|
||||
}
|
||||
@ -1307,8 +1300,8 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (SetAttr(self, name, (new_val.get() == NULL) ? value : new_val.get()) <
|
||||
0) {
|
||||
if (SetAttr(reinterpret_cast<PyObject*>(self), name,
|
||||
(new_val.get() == NULL) ? value : new_val.get()) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -2211,7 +2204,8 @@ static PyObject* ListFields(CMessage* self) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject* field_value = GetAttr(self, py_field_name.get());
|
||||
PyObject* field_value =
|
||||
GetAttr(reinterpret_cast<PyObject*>(self), py_field_name.get());
|
||||
if (field_value == NULL) {
|
||||
PyErr_SetObject(PyExc_ValueError, py_field_name.get());
|
||||
return NULL;
|
||||
@ -2707,7 +2701,8 @@ static bool SetCompositeField(
|
||||
return PyDict_SetItem(self->composite_fields, name, value) == 0;
|
||||
}
|
||||
|
||||
PyObject* GetAttr(CMessage* self, PyObject* name) {
|
||||
PyObject* GetAttr(PyObject* pself, PyObject* name) {
|
||||
CMessage* self = reinterpret_cast<CMessage*>(pself);
|
||||
PyObject* value = self->composite_fields ?
|
||||
PyDict_GetItem(self->composite_fields, name) : NULL;
|
||||
if (value != NULL) {
|
||||
@ -2785,7 +2780,8 @@ PyObject* GetAttr(CMessage* self, PyObject* name) {
|
||||
return InternalGetScalar(self->message, field_descriptor);
|
||||
}
|
||||
|
||||
int SetAttr(CMessage* self, PyObject* name, PyObject* value) {
|
||||
int SetAttr(PyObject* pself, PyObject* name, PyObject* value) {
|
||||
CMessage* self = reinterpret_cast<CMessage*>(pself);
|
||||
if (self->composite_fields && PyDict_Contains(self->composite_fields, name)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Can't set composite field");
|
||||
return -1;
|
||||
@ -2837,8 +2833,8 @@ PyTypeObject CMessage_Type = {
|
||||
PyObject_HashNotImplemented, // tp_hash
|
||||
0, // tp_call
|
||||
(reprfunc)cmessage::ToStr, // tp_str
|
||||
(getattrofunc)cmessage::GetAttr, // tp_getattro
|
||||
(setattrofunc)cmessage::SetAttr, // tp_setattro
|
||||
cmessage::GetAttr, // tp_getattro
|
||||
cmessage::SetAttr, // tp_setattro
|
||||
0, // tp_as_buffer
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags
|
||||
"A ProtocolMessage", // tp_doc
|
||||
|
@ -240,15 +240,15 @@ PyObject* MergeFrom(CMessage* self, PyObject* arg);
|
||||
// has been registered with the same field number on this class.
|
||||
PyObject* RegisterExtension(PyObject* cls, PyObject* extension_handle);
|
||||
|
||||
// Retrieves an attribute named 'name' from CMessage 'self'. Returns
|
||||
// the attribute value on success, or NULL on failure.
|
||||
// Retrieves an attribute named 'name' from 'self', which is interpreted as a
|
||||
// CMessage. Returns the attribute value on success, or null on failure.
|
||||
//
|
||||
// Returns a new reference.
|
||||
PyObject* GetAttr(CMessage* self, PyObject* name);
|
||||
PyObject* GetAttr(PyObject* self, PyObject* name);
|
||||
|
||||
// Set the value of the attribute named 'name', for CMessage 'self',
|
||||
// to the value 'value'. Returns -1 on failure.
|
||||
int SetAttr(CMessage* self, PyObject* name, PyObject* value);
|
||||
// Set the value of the attribute named 'name', for 'self', which is interpreted
|
||||
// as a CMessage, to the value 'value'. Returns -1 on failure.
|
||||
int SetAttr(PyObject* self, PyObject* name, PyObject* value);
|
||||
|
||||
PyObject* FindInitializationErrors(CMessage* self);
|
||||
|
||||
|
@ -938,7 +938,7 @@ def _SkipField(tokenizer):
|
||||
tokenizer.ConsumeIdentifier()
|
||||
tokenizer.Consume(']')
|
||||
else:
|
||||
tokenizer.ConsumeIdentifier()
|
||||
tokenizer.ConsumeIdentifierOrNumber()
|
||||
|
||||
_SkipFieldContents(tokenizer)
|
||||
|
||||
|
@ -118,6 +118,7 @@ nobase_include_HEADERS = \
|
||||
google/protobuf/generated_message_table_driven.h \
|
||||
google/protobuf/generated_message_util.h \
|
||||
google/protobuf/has_bits.h \
|
||||
google/protobuf/implicit_weak_message.h \
|
||||
google/protobuf/map_entry.h \
|
||||
google/protobuf/map_entry_lite.h \
|
||||
google/protobuf/map_field.h \
|
||||
@ -222,6 +223,7 @@ libprotobuf_lite_la_SOURCES = \
|
||||
google/protobuf/generated_message_util.cc \
|
||||
google/protobuf/generated_message_table_driven_lite.h \
|
||||
google/protobuf/generated_message_table_driven_lite.cc \
|
||||
google/protobuf/implicit_weak_message.cc \
|
||||
google/protobuf/message_lite.cc \
|
||||
google/protobuf/repeated_field.cc \
|
||||
google/protobuf/wire_format_lite.cc \
|
||||
|
@ -196,13 +196,6 @@ const Any& Any::default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
Any* Any::New(::google::protobuf::Arena* arena) const {
|
||||
Any* n = new Any;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void Any::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.Any)
|
||||
@ -436,5 +429,12 @@ void Any::InternalSwap(Any* other) {
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Any* Arena::Create< ::google::protobuf::Any >(Arena* arena) {
|
||||
return Arena::CreateInternal< ::google::protobuf::Any >(arena);
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
@ -58,6 +58,11 @@ LIBPROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Any* Arena::Create< ::google::protobuf::Any>(Arena*);
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
@ -115,9 +120,13 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_in
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline Any* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
inline Any* New() const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<Any>(NULL);
|
||||
}
|
||||
|
||||
Any* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
Any* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<Any>(arena);
|
||||
}
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const Any& from);
|
||||
|
@ -120,17 +120,18 @@ option objc_class_prefix = "GPB";
|
||||
// }
|
||||
//
|
||||
message Any {
|
||||
// A URL/resource name whose content describes the type of the
|
||||
// serialized protocol buffer message.
|
||||
// A URL/resource name that uniquely identifies the type of the serialized
|
||||
// protocol buffer message. The last segment of the URL's path must represent
|
||||
// the fully qualified name of the type (as in
|
||||
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||
// (e.g., leading "." is not accepted).
|
||||
//
|
||||
// For URLs which use the scheme `http`, `https`, or no scheme, the
|
||||
// following restrictions and interpretations apply:
|
||||
// In practice, teams usually precompile into the binary all types that they
|
||||
// expect it to use in the context of Any. However, for URLs which use the
|
||||
// scheme `http`, `https`, or no scheme, one can optionally set up a type
|
||||
// server that maps type URLs to message definitions as follows:
|
||||
//
|
||||
// * If no scheme is provided, `https` is assumed.
|
||||
// * The last segment of the URL's path must represent the fully
|
||||
// qualified name of the type (as in `path/google.protobuf.Duration`).
|
||||
// The name should be in a canonical form (e.g., leading "." is
|
||||
// not accepted).
|
||||
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
// value in binary format, or produce an error.
|
||||
// * Applications are allowed to cache lookup results based on the
|
||||
@ -139,6 +140,10 @@ message Any {
|
||||
// on changes to types. (Use versioned type names to manage
|
||||
// breaking changes.)
|
||||
//
|
||||
// Note: this functionality is not currently available in the official
|
||||
// protobuf release, and it is not used for type URLs beginning with
|
||||
// type.googleapis.com.
|
||||
//
|
||||
// Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
// used with implementation specific semantics.
|
||||
//
|
||||
|
@ -311,13 +311,6 @@ const Api& Api::default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
Api* Api::New(::google::protobuf::Arena* arena) const {
|
||||
Api* n = new Api;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void Api::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.Api)
|
||||
@ -368,7 +361,8 @@ bool Api::MergePartialFromCodedStream(
|
||||
case 2: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(input, add_methods()));
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
|
||||
input, add_methods()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
@ -379,7 +373,8 @@ bool Api::MergePartialFromCodedStream(
|
||||
case 3: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(input, add_options()));
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
|
||||
input, add_options()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
@ -418,7 +413,8 @@ bool Api::MergePartialFromCodedStream(
|
||||
case 6: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(input, add_mixins()));
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
|
||||
input, add_mixins()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
@ -480,14 +476,18 @@ void Api::SerializeWithCachedSizes(
|
||||
for (unsigned int i = 0,
|
||||
n = static_cast<unsigned int>(this->methods_size()); i < n; i++) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
||||
2, this->methods(static_cast<int>(i)), output);
|
||||
2,
|
||||
this->methods(static_cast<int>(i)),
|
||||
output);
|
||||
}
|
||||
|
||||
// repeated .google.protobuf.Option options = 3;
|
||||
for (unsigned int i = 0,
|
||||
n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
||||
3, this->options(static_cast<int>(i)), output);
|
||||
3,
|
||||
this->options(static_cast<int>(i)),
|
||||
output);
|
||||
}
|
||||
|
||||
// string version = 4;
|
||||
@ -503,14 +503,16 @@ void Api::SerializeWithCachedSizes(
|
||||
// .google.protobuf.SourceContext source_context = 5;
|
||||
if (this->has_source_context()) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
||||
5, *this->source_context_, output);
|
||||
5, *source_context_, output);
|
||||
}
|
||||
|
||||
// repeated .google.protobuf.Mixin mixins = 6;
|
||||
for (unsigned int i = 0,
|
||||
n = static_cast<unsigned int>(this->mixins_size()); i < n; i++) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
||||
6, this->mixins(static_cast<int>(i)), output);
|
||||
6,
|
||||
this->mixins(static_cast<int>(i)),
|
||||
output);
|
||||
}
|
||||
|
||||
// .google.protobuf.Syntax syntax = 7;
|
||||
@ -575,7 +577,7 @@ void Api::SerializeWithCachedSizes(
|
||||
if (this->has_source_context()) {
|
||||
target = ::google::protobuf::internal::WireFormatLite::
|
||||
InternalWriteMessageToArray(
|
||||
5, *this->source_context_, deterministic, target);
|
||||
5, *source_context_, deterministic, target);
|
||||
}
|
||||
|
||||
// repeated .google.protobuf.Mixin mixins = 6;
|
||||
@ -660,7 +662,7 @@ size_t Api::ByteSizeLong() const {
|
||||
if (this->has_source_context()) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::MessageSize(
|
||||
*this->source_context_);
|
||||
*source_context_);
|
||||
}
|
||||
|
||||
// .google.protobuf.Syntax syntax = 7;
|
||||
@ -741,9 +743,9 @@ void Api::Swap(Api* other) {
|
||||
}
|
||||
void Api::InternalSwap(Api* other) {
|
||||
using std::swap;
|
||||
methods_.InternalSwap(&other->methods_);
|
||||
options_.InternalSwap(&other->options_);
|
||||
mixins_.InternalSwap(&other->mixins_);
|
||||
CastToBase(&methods_)->InternalSwap(CastToBase(&other->methods_));
|
||||
CastToBase(&options_)->InternalSwap(CastToBase(&other->options_));
|
||||
CastToBase(&mixins_)->InternalSwap(CastToBase(&other->mixins_));
|
||||
name_.Swap(&other->name_);
|
||||
version_.Swap(&other->version_);
|
||||
swap(source_context_, other->source_context_);
|
||||
@ -843,13 +845,6 @@ const Method& Method::default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
Method* Method::New(::google::protobuf::Arena* arena) const {
|
||||
Method* n = new Method;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void Method::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.Method)
|
||||
@ -957,7 +952,8 @@ bool Method::MergePartialFromCodedStream(
|
||||
case 6: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(input, add_options()));
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
|
||||
input, add_options()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
@ -1049,7 +1045,9 @@ void Method::SerializeWithCachedSizes(
|
||||
for (unsigned int i = 0,
|
||||
n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
||||
6, this->options(static_cast<int>(i)), output);
|
||||
6,
|
||||
this->options(static_cast<int>(i)),
|
||||
output);
|
||||
}
|
||||
|
||||
// .google.protobuf.Syntax syntax = 7;
|
||||
@ -1271,7 +1269,7 @@ void Method::Swap(Method* other) {
|
||||
}
|
||||
void Method::InternalSwap(Method* other) {
|
||||
using std::swap;
|
||||
options_.InternalSwap(&other->options_);
|
||||
CastToBase(&options_)->InternalSwap(CastToBase(&other->options_));
|
||||
name_.Swap(&other->name_);
|
||||
request_type_url_.Swap(&other->request_type_url_);
|
||||
response_type_url_.Swap(&other->response_type_url_);
|
||||
@ -1352,13 +1350,6 @@ const Mixin& Mixin::default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
Mixin* Mixin::New(::google::protobuf::Arena* arena) const {
|
||||
Mixin* n = new Mixin;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void Mixin::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.Mixin)
|
||||
@ -1604,5 +1595,18 @@ void Mixin::InternalSwap(Mixin* other) {
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Api* Arena::Create< ::google::protobuf::Api >(Arena* arena) {
|
||||
return Arena::CreateInternal< ::google::protobuf::Api >(arena);
|
||||
}
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Method* Arena::Create< ::google::protobuf::Method >(Arena* arena) {
|
||||
return Arena::CreateInternal< ::google::protobuf::Method >(arena);
|
||||
}
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Mixin* Arena::Create< ::google::protobuf::Mixin >(Arena* arena) {
|
||||
return Arena::CreateInternal< ::google::protobuf::Mixin >(arena);
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
@ -71,6 +71,13 @@ LIBPROTOBUF_EXPORT extern MixinDefaultTypeInternal _Mixin_default_instance_;
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Api* Arena::Create< ::google::protobuf::Api>(Arena*);
|
||||
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Method* Arena::Create< ::google::protobuf::Method>(Arena*);
|
||||
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Mixin* Arena::Create< ::google::protobuf::Mixin>(Arena*);
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
@ -118,9 +125,13 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_in
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline Api* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
inline Api* New() const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<Api>(NULL);
|
||||
}
|
||||
|
||||
Api* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
Api* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<Api>(arena);
|
||||
}
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const Api& from);
|
||||
@ -160,11 +171,11 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_in
|
||||
int methods_size() const;
|
||||
void clear_methods();
|
||||
static const int kMethodsFieldNumber = 2;
|
||||
const ::google::protobuf::Method& methods(int index) const;
|
||||
::google::protobuf::Method* mutable_methods(int index);
|
||||
::google::protobuf::Method* add_methods();
|
||||
::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >*
|
||||
mutable_methods();
|
||||
const ::google::protobuf::Method& methods(int index) const;
|
||||
::google::protobuf::Method* add_methods();
|
||||
const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >&
|
||||
methods() const;
|
||||
|
||||
@ -172,11 +183,11 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_in
|
||||
int options_size() const;
|
||||
void clear_options();
|
||||
static const int kOptionsFieldNumber = 3;
|
||||
const ::google::protobuf::Option& options(int index) const;
|
||||
::google::protobuf::Option* mutable_options(int index);
|
||||
::google::protobuf::Option* add_options();
|
||||
::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
|
||||
mutable_options();
|
||||
const ::google::protobuf::Option& options(int index) const;
|
||||
::google::protobuf::Option* add_options();
|
||||
const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
|
||||
options() const;
|
||||
|
||||
@ -184,11 +195,11 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_in
|
||||
int mixins_size() const;
|
||||
void clear_mixins();
|
||||
static const int kMixinsFieldNumber = 6;
|
||||
const ::google::protobuf::Mixin& mixins(int index) const;
|
||||
::google::protobuf::Mixin* mutable_mixins(int index);
|
||||
::google::protobuf::Mixin* add_mixins();
|
||||
::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >*
|
||||
mutable_mixins();
|
||||
const ::google::protobuf::Mixin& mixins(int index) const;
|
||||
::google::protobuf::Mixin* add_mixins();
|
||||
const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >&
|
||||
mixins() const;
|
||||
|
||||
@ -296,9 +307,13 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline Method* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
inline Method* New() const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<Method>(NULL);
|
||||
}
|
||||
|
||||
Method* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
Method* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<Method>(arena);
|
||||
}
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const Method& from);
|
||||
@ -338,11 +353,11 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc
|
||||
int options_size() const;
|
||||
void clear_options();
|
||||
static const int kOptionsFieldNumber = 6;
|
||||
const ::google::protobuf::Option& options(int index) const;
|
||||
::google::protobuf::Option* mutable_options(int index);
|
||||
::google::protobuf::Option* add_options();
|
||||
::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
|
||||
mutable_options();
|
||||
const ::google::protobuf::Option& options(int index) const;
|
||||
::google::protobuf::Option* add_options();
|
||||
const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
|
||||
options() const;
|
||||
|
||||
@ -467,9 +482,13 @@ class LIBPROTOBUF_EXPORT Mixin : public ::google::protobuf::Message /* @@protoc_
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline Mixin* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
inline Mixin* New() const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<Mixin>(NULL);
|
||||
}
|
||||
|
||||
Mixin* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
Mixin* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<Mixin>(arena);
|
||||
}
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const Mixin& from);
|
||||
@ -614,23 +633,23 @@ inline int Api::methods_size() const {
|
||||
inline void Api::clear_methods() {
|
||||
methods_.Clear();
|
||||
}
|
||||
inline const ::google::protobuf::Method& Api::methods(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Api.methods)
|
||||
return methods_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::Method* Api::mutable_methods(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Api.methods)
|
||||
return methods_.Mutable(index);
|
||||
}
|
||||
inline ::google::protobuf::Method* Api::add_methods() {
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.Api.methods)
|
||||
return methods_.Add();
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >*
|
||||
Api::mutable_methods() {
|
||||
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.methods)
|
||||
return &methods_;
|
||||
}
|
||||
inline const ::google::protobuf::Method& Api::methods(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Api.methods)
|
||||
return methods_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::Method* Api::add_methods() {
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.Api.methods)
|
||||
return methods_.Add();
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Method >&
|
||||
Api::methods() const {
|
||||
// @@protoc_insertion_point(field_list:google.protobuf.Api.methods)
|
||||
@ -641,23 +660,23 @@ Api::methods() const {
|
||||
inline int Api::options_size() const {
|
||||
return options_.size();
|
||||
}
|
||||
inline const ::google::protobuf::Option& Api::options(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Api.options)
|
||||
return options_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::Option* Api::mutable_options(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Api.options)
|
||||
return options_.Mutable(index);
|
||||
}
|
||||
inline ::google::protobuf::Option* Api::add_options() {
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.Api.options)
|
||||
return options_.Add();
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
|
||||
Api::mutable_options() {
|
||||
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.options)
|
||||
return &options_;
|
||||
}
|
||||
inline const ::google::protobuf::Option& Api::options(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Api.options)
|
||||
return options_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::Option* Api::add_options() {
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.Api.options)
|
||||
return options_.Add();
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
|
||||
Api::options() const {
|
||||
// @@protoc_insertion_point(field_list:google.protobuf.Api.options)
|
||||
@ -737,7 +756,8 @@ inline ::google::protobuf::SourceContext* Api::release_source_context() {
|
||||
inline ::google::protobuf::SourceContext* Api::mutable_source_context() {
|
||||
|
||||
if (source_context_ == NULL) {
|
||||
source_context_ = new ::google::protobuf::SourceContext;
|
||||
source_context_ = ::google::protobuf::Arena::Create< ::google::protobuf::SourceContext >(
|
||||
GetArenaNoVirtual());
|
||||
}
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Api.source_context)
|
||||
return source_context_;
|
||||
@ -768,23 +788,23 @@ inline int Api::mixins_size() const {
|
||||
inline void Api::clear_mixins() {
|
||||
mixins_.Clear();
|
||||
}
|
||||
inline const ::google::protobuf::Mixin& Api::mixins(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Api.mixins)
|
||||
return mixins_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::Mixin* Api::mutable_mixins(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Api.mixins)
|
||||
return mixins_.Mutable(index);
|
||||
}
|
||||
inline ::google::protobuf::Mixin* Api::add_mixins() {
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.Api.mixins)
|
||||
return mixins_.Add();
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >*
|
||||
Api::mutable_mixins() {
|
||||
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Api.mixins)
|
||||
return &mixins_;
|
||||
}
|
||||
inline const ::google::protobuf::Mixin& Api::mixins(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Api.mixins)
|
||||
return mixins_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::Mixin* Api::add_mixins() {
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.Api.mixins)
|
||||
return mixins_.Add();
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >&
|
||||
Api::mixins() const {
|
||||
// @@protoc_insertion_point(field_list:google.protobuf.Api.mixins)
|
||||
@ -1000,23 +1020,23 @@ inline void Method::set_response_streaming(bool value) {
|
||||
inline int Method::options_size() const {
|
||||
return options_.size();
|
||||
}
|
||||
inline const ::google::protobuf::Option& Method::options(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Method.options)
|
||||
return options_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::Option* Method::mutable_options(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.Method.options)
|
||||
return options_.Mutable(index);
|
||||
}
|
||||
inline ::google::protobuf::Option* Method::add_options() {
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.Method.options)
|
||||
return options_.Add();
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >*
|
||||
Method::mutable_options() {
|
||||
// @@protoc_insertion_point(field_mutable_list:google.protobuf.Method.options)
|
||||
return &options_;
|
||||
}
|
||||
inline const ::google::protobuf::Option& Method::options(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.Method.options)
|
||||
return options_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::Option* Method::add_options() {
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.Method.options)
|
||||
return options_.Add();
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
|
||||
Method::options() const {
|
||||
// @@protoc_insertion_point(field_list:google.protobuf.Method.options)
|
||||
|
@ -73,14 +73,15 @@ void ArenaImpl::Init() {
|
||||
// Thread which calls Init() owns the first block. This allows the
|
||||
// single-threaded case to allocate on the first block without having to
|
||||
// perform atomic operations.
|
||||
InitBlock(initial_block_, &thread_cache(), options_.initial_block_size);
|
||||
ThreadInfo* info = NewThreadInfo(initial_block_);
|
||||
info->next = NULL;
|
||||
new (initial_block_) Block(options_.initial_block_size, NULL);
|
||||
SerialArena* serial =
|
||||
SerialArena::New(initial_block_, &thread_cache(), this);
|
||||
serial->set_next(NULL);
|
||||
google::protobuf::internal::NoBarrier_Store(&threads_,
|
||||
reinterpret_cast<google::protobuf::internal::AtomicWord>(info));
|
||||
reinterpret_cast<google::protobuf::internal::AtomicWord>(serial));
|
||||
google::protobuf::internal::NoBarrier_Store(&space_allocated_,
|
||||
options_.initial_block_size);
|
||||
CacheBlock(initial_block_);
|
||||
CacheSerialArena(serial);
|
||||
} else {
|
||||
google::protobuf::internal::NoBarrier_Store(&space_allocated_, 0);
|
||||
}
|
||||
@ -103,145 +104,134 @@ uint64 ArenaImpl::Reset() {
|
||||
return space_allocated;
|
||||
}
|
||||
|
||||
ArenaImpl::Block* ArenaImpl::NewBlock(void* me, Block* my_last_block,
|
||||
size_t min_bytes) {
|
||||
ArenaImpl::Block* ArenaImpl::NewBlock(Block* last_block, size_t min_bytes) {
|
||||
size_t size;
|
||||
if (my_last_block != NULL) {
|
||||
if (last_block) {
|
||||
// Double the current block size, up to a limit.
|
||||
size = std::min(2 * my_last_block->size, options_.max_block_size);
|
||||
size = std::min(2 * last_block->size(), options_.max_block_size);
|
||||
} else {
|
||||
size = options_.start_block_size;
|
||||
}
|
||||
// Verify that min_bytes + kHeaderSize won't overflow.
|
||||
GOOGLE_CHECK_LE(min_bytes, std::numeric_limits<size_t>::max() - kHeaderSize);
|
||||
size = std::max(size, kHeaderSize + min_bytes);
|
||||
// Verify that min_bytes + kBlockHeaderSize won't overflow.
|
||||
GOOGLE_CHECK_LE(min_bytes, std::numeric_limits<size_t>::max() - kBlockHeaderSize);
|
||||
size = std::max(size, kBlockHeaderSize + min_bytes);
|
||||
|
||||
Block* b = reinterpret_cast<Block*>(options_.block_alloc(size));
|
||||
InitBlock(b, me, size);
|
||||
void* mem = options_.block_alloc(size);
|
||||
Block* b = new (mem) Block(size, last_block);
|
||||
google::protobuf::internal::NoBarrier_AtomicIncrement(&space_allocated_, size);
|
||||
return b;
|
||||
}
|
||||
|
||||
void ArenaImpl::InitBlock(Block* b, void *me, size_t size) {
|
||||
b->pos = kHeaderSize;
|
||||
b->size = size;
|
||||
b->owner = me;
|
||||
b->next = NULL;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
// Poison the rest of the block for ASAN. It was unpoisoned by the underlying
|
||||
// malloc but it's not yet usable until we return it as part of an allocation.
|
||||
ASAN_POISON_MEMORY_REGION(
|
||||
reinterpret_cast<char*>(b) + b->pos, b->size - b->pos);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
}
|
||||
ArenaImpl::Block::Block(size_t size, Block* next)
|
||||
: next_(next), pos_(kBlockHeaderSize), size_(size) {}
|
||||
|
||||
ArenaImpl::CleanupChunk* ArenaImpl::ExpandCleanupList(CleanupChunk* cleanup,
|
||||
Block* b) {
|
||||
size_t size = cleanup ? cleanup->size * 2 : kMinCleanupListElements;
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
void ArenaImpl::SerialArena::AddCleanupFallback(void* elem,
|
||||
void (*cleanup)(void*)) {
|
||||
size_t size = cleanup_ ? cleanup_->size * 2 : kMinCleanupListElements;
|
||||
size = std::min(size, kMaxCleanupListElements);
|
||||
size_t bytes = internal::AlignUpTo8(CleanupChunk::SizeOf(size));
|
||||
if (b->avail() < bytes) {
|
||||
b = GetBlock(bytes);
|
||||
}
|
||||
CleanupChunk* list =
|
||||
reinterpret_cast<CleanupChunk*>(AllocFromBlock(b, bytes));
|
||||
list->next = b->thread_info->cleanup;
|
||||
CleanupChunk* list = reinterpret_cast<CleanupChunk*>(AllocateAligned(bytes));
|
||||
list->next = cleanup_;
|
||||
list->size = size;
|
||||
list->len = 0;
|
||||
b->thread_info->cleanup = list;
|
||||
return list;
|
||||
}
|
||||
|
||||
inline GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
void ArenaImpl::AddCleanupInBlock(
|
||||
Block* b, void* elem, void (*func)(void*)) {
|
||||
CleanupChunk* cleanup = b->thread_info->cleanup;
|
||||
if (cleanup == NULL || cleanup->len == cleanup->size) {
|
||||
cleanup = ExpandCleanupList(cleanup, b);
|
||||
}
|
||||
cleanup_ = list;
|
||||
cleanup_ptr_ = &list->nodes[0];
|
||||
cleanup_limit_ = &list->nodes[size];
|
||||
|
||||
CleanupNode* node = &cleanup->nodes[cleanup->len++];
|
||||
|
||||
node->elem = elem;
|
||||
node->cleanup = func;
|
||||
}
|
||||
|
||||
void ArenaImpl::AddCleanup(void* elem, void (*cleanup)(void*)) {
|
||||
return AddCleanupInBlock(GetBlock(0), elem, cleanup);
|
||||
AddCleanup(elem, cleanup);
|
||||
}
|
||||
|
||||
void* ArenaImpl::AllocateAligned(size_t n) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
|
||||
return AllocFromBlock(GetBlock(n), n);
|
||||
SerialArena* arena;
|
||||
if (GOOGLE_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
return arena->AllocateAligned(n);
|
||||
} else {
|
||||
return AllocateAlignedFallback(n);
|
||||
}
|
||||
}
|
||||
|
||||
void* ArenaImpl::AllocateAlignedAndAddCleanup(size_t n,
|
||||
void (*cleanup)(void*)) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
SerialArena* arena;
|
||||
if (GOOGLE_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
return arena->AllocateAlignedAndAddCleanup(n, cleanup);
|
||||
} else {
|
||||
return AllocateAlignedAndAddCleanupFallback(n, cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
Block* b = GetBlock(n);
|
||||
void* mem = AllocFromBlock(b, n);
|
||||
AddCleanupInBlock(b, mem, cleanup);
|
||||
return mem;
|
||||
void ArenaImpl::AddCleanup(void* elem, void (*cleanup)(void*)) {
|
||||
SerialArena* arena;
|
||||
if (GOOGLE_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
arena->AddCleanup(elem, cleanup);
|
||||
} else {
|
||||
return AddCleanupFallback(elem, cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
void* ArenaImpl::AllocateAlignedFallback(size_t n) {
|
||||
return GetSerialArena()->AllocateAligned(n);
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
void* ArenaImpl::AllocateAlignedAndAddCleanupFallback(size_t n,
|
||||
void (*cleanup)(void*)) {
|
||||
return GetSerialArena()->AllocateAlignedAndAddCleanup(n, cleanup);
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
void ArenaImpl::AddCleanupFallback(void* elem, void (*cleanup)(void*)) {
|
||||
GetSerialArena()->AddCleanup(elem, cleanup);
|
||||
}
|
||||
|
||||
inline GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
ArenaImpl::Block* ArenaImpl::GetBlock(size_t n) {
|
||||
Block* my_block = NULL;
|
||||
|
||||
bool ArenaImpl::GetSerialArenaFast(ArenaImpl::SerialArena** arena) {
|
||||
// If this thread already owns a block in this arena then try to use that.
|
||||
// This fast path optimizes the case where multiple threads allocate from the
|
||||
// same arena.
|
||||
ThreadCache* tc = &thread_cache();
|
||||
if (tc->last_lifecycle_id_seen == lifecycle_id_) {
|
||||
my_block = tc->last_block_used_;
|
||||
if (my_block->avail() >= n) {
|
||||
return my_block;
|
||||
}
|
||||
if (GOOGLE_PREDICT_TRUE(tc->last_lifecycle_id_seen == lifecycle_id_)) {
|
||||
*arena = tc->last_serial_arena;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check whether we own the last accessed block on this arena.
|
||||
// This fast path optimizes the case where a single thread uses multiple
|
||||
// arenas.
|
||||
Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&hint_));
|
||||
if (b != NULL && b->owner == tc) {
|
||||
my_block = b;
|
||||
if (my_block->avail() >= n) {
|
||||
return my_block;
|
||||
}
|
||||
// Check whether we own the last accessed SerialArena on this arena. This
|
||||
// fast path optimizes the case where a single thread uses multiple arenas.
|
||||
SerialArena* serial =
|
||||
reinterpret_cast<SerialArena*>(google::protobuf::internal::Acquire_Load(&hint_));
|
||||
if (GOOGLE_PREDICT_TRUE(serial != NULL && serial->owner() == tc)) {
|
||||
*arena = serial;
|
||||
return true;
|
||||
}
|
||||
return GetBlockSlow(tc, my_block, n);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
void* ArenaImpl::AllocFromBlock(Block* b, size_t n) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(b->pos), b->pos); // Must be already aligned.
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
GOOGLE_DCHECK_GE(b->avail(), n);
|
||||
size_t p = b->pos;
|
||||
b->pos = p + n;
|
||||
ArenaImpl::SerialArena* ArenaImpl::GetSerialArena() {
|
||||
SerialArena* arena;
|
||||
if (GOOGLE_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
|
||||
return arena;
|
||||
} else {
|
||||
return GetSerialArenaFallback(&thread_cache());
|
||||
}
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
void* ArenaImpl::SerialArena::AllocateAlignedFallback(size_t n) {
|
||||
// Sync back to current's pos.
|
||||
head_->set_pos(head_->size() - (limit_ - ptr_));
|
||||
|
||||
head_ = arena_->NewBlock(head_, n);
|
||||
ptr_ = head_->Pointer(head_->pos());
|
||||
limit_ = head_->Pointer(head_->size());
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(reinterpret_cast<char*>(b) + p, n);
|
||||
ASAN_POISON_MEMORY_REGION(ptr_, limit_ - ptr_);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
return reinterpret_cast<char*>(b) + p;
|
||||
}
|
||||
|
||||
ArenaImpl::Block* ArenaImpl::GetBlockSlow(void* me, Block* my_full_block,
|
||||
size_t n) {
|
||||
ThreadInfo* info =
|
||||
my_full_block ? my_full_block->thread_info : GetThreadInfo(me, n);
|
||||
GOOGLE_DCHECK(info != NULL);
|
||||
Block* b = info->head;
|
||||
if (b->avail() < n) {
|
||||
Block* new_b = NewBlock(me, b, n);
|
||||
new_b->thread_info = info;
|
||||
new_b->next = b;
|
||||
info->head = new_b;
|
||||
b = new_b;
|
||||
}
|
||||
CacheBlock(b);
|
||||
return b;
|
||||
return AllocateAligned(n);
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::SpaceAllocated() const {
|
||||
@ -249,18 +239,24 @@ uint64 ArenaImpl::SpaceAllocated() const {
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::SpaceUsed() const {
|
||||
ThreadInfo* info =
|
||||
reinterpret_cast<ThreadInfo*>(google::protobuf::internal::Acquire_Load(&threads_));
|
||||
SerialArena* serial =
|
||||
reinterpret_cast<SerialArena*>(google::protobuf::internal::Acquire_Load(&threads_));
|
||||
uint64 space_used = 0;
|
||||
|
||||
for ( ; info; info = info->next) {
|
||||
// Remove the overhead of the ThreadInfo itself.
|
||||
space_used -= sizeof(ThreadInfo);
|
||||
for (Block* b = info->head; b; b = b->next) {
|
||||
space_used += (b->pos - kHeaderSize);
|
||||
}
|
||||
for ( ; serial; serial = serial->next()) {
|
||||
space_used += serial->SpaceUsed();
|
||||
}
|
||||
return space_used;
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::SerialArena::SpaceUsed() const {
|
||||
// Get current block's size from ptr_ (since we can't trust head_->pos().
|
||||
uint64 space_used = ptr_ - head_->Pointer(kBlockHeaderSize);
|
||||
// Get subsequent block size from b->pos().
|
||||
for (Block* b = head_->next(); b; b = b->next()) {
|
||||
space_used += (b->pos() - kBlockHeaderSize);
|
||||
}
|
||||
// Remove the overhead of the SerialArena itself.
|
||||
space_used -= kSerialArenaSize;
|
||||
return space_used;
|
||||
}
|
||||
|
||||
@ -268,30 +264,45 @@ uint64 ArenaImpl::FreeBlocks() {
|
||||
uint64 space_allocated = 0;
|
||||
// By omitting an Acquire barrier we ensure that any user code that doesn't
|
||||
// properly synchronize Reset() or the destructor will throw a TSAN warning.
|
||||
ThreadInfo* info =
|
||||
reinterpret_cast<ThreadInfo*>(google::protobuf::internal::NoBarrier_Load(&threads_));
|
||||
SerialArena* serial =
|
||||
reinterpret_cast<SerialArena*>(google::protobuf::internal::NoBarrier_Load(&threads_));
|
||||
|
||||
while (info) {
|
||||
while (serial) {
|
||||
// This is inside a block we are freeing, so we need to read it now.
|
||||
SerialArena* next = serial->next();
|
||||
space_allocated += ArenaImpl::SerialArena::Free(serial, initial_block_,
|
||||
options_.block_dealloc);
|
||||
// serial is dead now.
|
||||
serial = next;
|
||||
}
|
||||
|
||||
return space_allocated;
|
||||
}
|
||||
|
||||
uint64 ArenaImpl::SerialArena::Free(ArenaImpl::SerialArena* serial,
|
||||
Block* initial_block,
|
||||
void (*block_dealloc)(void*, size_t)) {
|
||||
uint64 space_allocated = 0;
|
||||
|
||||
// We have to be careful in this function, since we will be freeing the Block
|
||||
// that contains this SerialArena. Be careful about accessing |serial|.
|
||||
|
||||
for (Block* b = serial->head_; b; ) {
|
||||
// This is inside the block we are freeing, so we need to read it now.
|
||||
ThreadInfo* next_info = info->next;
|
||||
for (Block* b = info->head; b; ) {
|
||||
// This is inside the block we are freeing, so we need to read it now.
|
||||
Block* next_block = b->next;
|
||||
space_allocated += (b->size);
|
||||
Block* next_block = b->next();
|
||||
space_allocated += (b->size());
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
// This memory was provided by the underlying allocator as unpoisoned, so
|
||||
// return it in an unpoisoned state.
|
||||
ASAN_UNPOISON_MEMORY_REGION(reinterpret_cast<char*>(b), b->size);
|
||||
// This memory was provided by the underlying allocator as unpoisoned, so
|
||||
// return it in an unpoisoned state.
|
||||
ASAN_UNPOISON_MEMORY_REGION(b->Pointer(0), b->size());
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
if (b != initial_block_) {
|
||||
options_.block_dealloc(b, b->size);
|
||||
}
|
||||
|
||||
b = next_block;
|
||||
if (b != initial_block) {
|
||||
block_dealloc(b, b->size());
|
||||
}
|
||||
info = next_info;
|
||||
|
||||
b = next_block;
|
||||
}
|
||||
|
||||
return space_allocated;
|
||||
@ -300,63 +311,87 @@ uint64 ArenaImpl::FreeBlocks() {
|
||||
void ArenaImpl::CleanupList() {
|
||||
// By omitting an Acquire barrier we ensure that any user code that doesn't
|
||||
// properly synchronize Reset() or the destructor will throw a TSAN warning.
|
||||
ThreadInfo* info =
|
||||
reinterpret_cast<ThreadInfo*>(google::protobuf::internal::NoBarrier_Load(&threads_));
|
||||
SerialArena* serial =
|
||||
reinterpret_cast<SerialArena*>(google::protobuf::internal::NoBarrier_Load(&threads_));
|
||||
|
||||
for ( ; info; info = info->next) {
|
||||
CleanupChunk* list = info->cleanup;
|
||||
while (list) {
|
||||
size_t n = list->len;
|
||||
CleanupNode* node = &list->nodes[list->len - 1];
|
||||
for (size_t i = 0; i < n; i++, node--) {
|
||||
node->cleanup(node->elem);
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
for ( ; serial; serial = serial->next()) {
|
||||
serial->CleanupList();
|
||||
}
|
||||
}
|
||||
|
||||
ArenaImpl::ThreadInfo* ArenaImpl::NewThreadInfo(Block* b) {
|
||||
GOOGLE_DCHECK(FindThreadInfo(b->owner) == NULL);
|
||||
ThreadInfo* info =
|
||||
reinterpret_cast<ThreadInfo*>(AllocFromBlock(b, sizeof(ThreadInfo)));
|
||||
b->thread_info = info;
|
||||
info->owner = b->owner;
|
||||
info->head = b;
|
||||
info->cleanup = NULL;
|
||||
return info;
|
||||
void ArenaImpl::SerialArena::CleanupList() {
|
||||
if (cleanup_ != NULL) {
|
||||
CleanupListFallback();
|
||||
}
|
||||
}
|
||||
|
||||
ArenaImpl::ThreadInfo* ArenaImpl::FindThreadInfo(void* me) {
|
||||
ThreadInfo* info =
|
||||
reinterpret_cast<ThreadInfo*>(google::protobuf::internal::Acquire_Load(&threads_));
|
||||
for ( ; info; info = info->next) {
|
||||
if (info->owner == me) {
|
||||
return info;
|
||||
void ArenaImpl::SerialArena::CleanupListFallback() {
|
||||
// Cleanup newest chunk: ptrs give us length.
|
||||
size_t n = cleanup_ptr_ - &cleanup_->nodes[0];
|
||||
CleanupNode* node = cleanup_ptr_;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
--node;
|
||||
node->cleanup(node->elem);
|
||||
}
|
||||
|
||||
// Cleanup older chunks, which are known to be full.
|
||||
CleanupChunk* list = cleanup_->next;
|
||||
while (list) {
|
||||
size_t n = list->size;
|
||||
CleanupNode* node = &list->nodes[list->size];
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
--node;
|
||||
node->cleanup(node->elem);
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
ArenaImpl::SerialArena* ArenaImpl::SerialArena::New(Block* b, void* owner,
|
||||
ArenaImpl* arena) {
|
||||
GOOGLE_DCHECK_EQ(b->pos(), kBlockHeaderSize); // Should be a fresh block
|
||||
GOOGLE_DCHECK_LE(kBlockHeaderSize + kSerialArenaSize, b->size());
|
||||
SerialArena* serial =
|
||||
reinterpret_cast<SerialArena*>(b->Pointer(kBlockHeaderSize));
|
||||
b->set_pos(kBlockHeaderSize + kSerialArenaSize);
|
||||
serial->arena_ = arena;
|
||||
serial->owner_ = owner;
|
||||
serial->head_ = b;
|
||||
serial->ptr_ = b->Pointer(b->pos());
|
||||
serial->limit_ = b->Pointer(b->size());
|
||||
serial->cleanup_ = NULL;
|
||||
serial->cleanup_ptr_ = NULL;
|
||||
serial->cleanup_limit_ = NULL;
|
||||
return serial;
|
||||
}
|
||||
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE
|
||||
ArenaImpl::SerialArena* ArenaImpl::GetSerialArenaFallback(void* me) {
|
||||
// Look for this SerialArena in our linked list.
|
||||
SerialArena* serial =
|
||||
reinterpret_cast<SerialArena*>(google::protobuf::internal::Acquire_Load(&threads_));
|
||||
for ( ; serial; serial = serial->next()) {
|
||||
if (serial->owner() == me) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ArenaImpl::ThreadInfo* ArenaImpl::GetThreadInfo(void* me, size_t n) {
|
||||
ThreadInfo* info = FindThreadInfo(me);
|
||||
|
||||
if (!info) {
|
||||
// This thread doesn't have any ThreadInfo, which also means it doesn't have
|
||||
// any blocks yet. So we'll allocate its first block now.
|
||||
Block* b = NewBlock(me, NULL, sizeof(ThreadInfo) + n);
|
||||
info = NewThreadInfo(b);
|
||||
if (!serial) {
|
||||
// This thread doesn't have any SerialArena, which also means it doesn't
|
||||
// have any blocks yet. So we'll allocate its first block now.
|
||||
Block* b = NewBlock(NULL, kSerialArenaSize);
|
||||
serial = SerialArena::New(b, me, this);
|
||||
|
||||
google::protobuf::internal::AtomicWord head;
|
||||
do {
|
||||
head = google::protobuf::internal::NoBarrier_Load(&threads_);
|
||||
info->next = reinterpret_cast<ThreadInfo*>(head);
|
||||
serial->set_next(reinterpret_cast<SerialArena*>(head));
|
||||
} while (google::protobuf::internal::Release_CompareAndSwap(
|
||||
&threads_, head, reinterpret_cast<google::protobuf::internal::AtomicWord>(info)) != head);
|
||||
&threads_, head, reinterpret_cast<google::protobuf::internal::AtomicWord>(serial)) != head);
|
||||
}
|
||||
|
||||
return info;
|
||||
CacheSerialArena(serial);
|
||||
return serial;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -56,6 +56,21 @@ using type_info = ::type_info;
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
struct ArenaOptions;
|
||||
} // namespace protobuf
|
||||
|
||||
namespace quality_webanswers {
|
||||
|
||||
void TempPrivateWorkAround(::google::protobuf::ArenaOptions* arena_options);
|
||||
|
||||
} // namespace quality_webanswers
|
||||
|
||||
namespace protobuf {
|
||||
namespace arena_metrics {
|
||||
|
||||
void EnableArenaMetrics(::google::protobuf::ArenaOptions* options);
|
||||
|
||||
} // namespace arena_metrics
|
||||
|
||||
class Arena; // defined below
|
||||
class Message; // message.h
|
||||
@ -117,6 +132,20 @@ struct ArenaOptions {
|
||||
// from the arena. By default, it contains a ptr to a wrapper function that
|
||||
// calls free.
|
||||
void (*block_dealloc)(void*, size_t);
|
||||
|
||||
ArenaOptions()
|
||||
: start_block_size(kDefaultStartBlockSize),
|
||||
max_block_size(kDefaultMaxBlockSize),
|
||||
initial_block(NULL),
|
||||
initial_block_size(0),
|
||||
block_alloc(&::operator new),
|
||||
block_dealloc(&internal::arena_free),
|
||||
on_arena_init(NULL),
|
||||
on_arena_reset(NULL),
|
||||
on_arena_destruction(NULL),
|
||||
on_arena_allocation(NULL) {}
|
||||
|
||||
private:
|
||||
// Hooks for adding external functionality such as user-specific metrics
|
||||
// collection, specific debugging abilities, etc.
|
||||
// Init hook may return a pointer to a cookie to be stored in the arena.
|
||||
@ -138,23 +167,15 @@ struct ArenaOptions {
|
||||
void (*on_arena_allocation)(const std::type_info* allocated_type,
|
||||
uint64 alloc_size, void* cookie);
|
||||
|
||||
ArenaOptions()
|
||||
: start_block_size(kDefaultStartBlockSize),
|
||||
max_block_size(kDefaultMaxBlockSize),
|
||||
initial_block(NULL),
|
||||
initial_block_size(0),
|
||||
block_alloc(&::operator new),
|
||||
block_dealloc(&internal::arena_free),
|
||||
on_arena_init(NULL),
|
||||
on_arena_reset(NULL),
|
||||
on_arena_destruction(NULL),
|
||||
on_arena_allocation(NULL) {}
|
||||
|
||||
private:
|
||||
// Constants define default starting block size and max block size for
|
||||
// arena allocator behavior -- see descriptions above.
|
||||
static const size_t kDefaultStartBlockSize = 256;
|
||||
static const size_t kDefaultMaxBlockSize = 8192;
|
||||
|
||||
friend void ::google::protobuf::arena_metrics::EnableArenaMetrics(ArenaOptions*);
|
||||
friend void quality_webanswers::TempPrivateWorkAround(ArenaOptions*);
|
||||
friend class Arena;
|
||||
friend class ArenaOptionsTestFriend;
|
||||
};
|
||||
|
||||
// Support for non-RTTI environments. (The metrics hooks API uses type
|
||||
@ -229,14 +250,15 @@ class LIBPROTOBUF_EXPORT Arena {
|
||||
// WARNING: if you allocate multiple objects, it is difficult to guarantee
|
||||
// that a series of allocations will fit in the initial block, especially if
|
||||
// Arena changes its alignment guarantees in the future!
|
||||
static const size_t kBlockOverhead = internal::ArenaImpl::kHeaderSize;
|
||||
static const size_t kBlockOverhead = internal::ArenaImpl::kBlockHeaderSize +
|
||||
internal::ArenaImpl::kSerialArenaSize;
|
||||
|
||||
// Default constructor with sensible default options, tuned for average
|
||||
// use-cases.
|
||||
Arena() : impl_(ArenaOptions()) { Init(ArenaOptions()); }
|
||||
|
||||
~Arena() {
|
||||
if (on_arena_reset_ != NULL || on_arena_destruction_ != NULL) {
|
||||
if (hooks_cookie_) {
|
||||
CallDestructorHooks();
|
||||
}
|
||||
}
|
||||
@ -277,6 +299,7 @@ class LIBPROTOBUF_EXPORT Arena {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
static T* CreateMessage(::google::protobuf::Arena* arena) {
|
||||
#if LANG_CXX11
|
||||
@ -355,6 +378,7 @@ class LIBPROTOBUF_EXPORT Arena {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
static T* Create(::google::protobuf::Arena* arena) {
|
||||
if (arena == NULL) {
|
||||
@ -522,6 +546,7 @@ class LIBPROTOBUF_EXPORT Arena {
|
||||
//
|
||||
// Combines SpaceAllocated and SpaceUsed. Returns a pair of
|
||||
// <space_allocated, space_used>.
|
||||
PROTOBUF_RUNTIME_DEPRECATED("Please use SpaceAllocated() and SpaceUsed()")
|
||||
std::pair<uint64, uint64> SpaceAllocatedAndUsed() const {
|
||||
return std::make_pair(SpaceAllocated(), SpaceUsed());
|
||||
}
|
||||
@ -637,6 +662,29 @@ class LIBPROTOBUF_EXPORT Arena {
|
||||
struct is_arena_constructable : InternalHelper<T>::is_arena_constructable {};
|
||||
|
||||
private:
|
||||
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
static T* CreateMessageInternal(::google::protobuf::Arena* arena) {
|
||||
#if LANG_CXX11
|
||||
static_assert(
|
||||
InternalHelper<T>::is_arena_constructable::value,
|
||||
"CreateMessage can only construct types that are ArenaConstructable");
|
||||
#endif
|
||||
if (arena == NULL) {
|
||||
return new T;
|
||||
} else {
|
||||
return arena->CreateMessageInternal<T>();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
static T* CreateInternal(::google::protobuf::Arena* arena) {
|
||||
if (arena == NULL) {
|
||||
return new T();
|
||||
} else {
|
||||
return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value);
|
||||
}
|
||||
}
|
||||
|
||||
void CallDestructorHooks();
|
||||
void OnArenaAllocation(const std::type_info* allocated_type, size_t n) const;
|
||||
inline void AllocHook(const std::type_info* allocated_type, size_t n) const {
|
||||
@ -668,12 +716,12 @@ class LIBPROTOBUF_EXPORT Arena {
|
||||
// fields, since they are designed to work in all mode combinations.
|
||||
template <typename Msg> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
static Msg* CreateMaybeMessage(Arena* arena, google::protobuf::internal::true_type) {
|
||||
return CreateMessage<Msg>(arena);
|
||||
return CreateMessageInternal<Msg>(arena);
|
||||
}
|
||||
|
||||
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
static T* CreateMaybeMessage(Arena* arena, google::protobuf::internal::false_type) {
|
||||
return Create<T>(arena);
|
||||
return CreateInternal<T>(arena);
|
||||
}
|
||||
|
||||
template <typename T> GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
@ -907,7 +955,6 @@ class LIBPROTOBUF_EXPORT Arena {
|
||||
|
||||
internal::ArenaImpl impl_;
|
||||
|
||||
void* (*on_arena_init_)(Arena* arena);
|
||||
void (*on_arena_allocation_)(const std::type_info* allocated_type,
|
||||
uint64 alloc_size, void* cookie);
|
||||
void (*on_arena_reset_)(Arena* arena, void* cookie, uint64 space_used);
|
||||
|
@ -40,10 +40,13 @@
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
#include <google/protobuf/stubs/mutex.h>
|
||||
#include <google/protobuf/stubs/type_traits.h>
|
||||
|
||||
#include <google/protobuf/stubs/port.h>
|
||||
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#endif // ADDRESS_SANITIZER
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
@ -112,6 +115,10 @@ class LIBPROTOBUF_EXPORT ArenaImpl {
|
||||
void AddCleanup(void* elem, void (*cleanup)(void*));
|
||||
|
||||
private:
|
||||
void* AllocateAlignedFallback(size_t n);
|
||||
void* AllocateAlignedAndAddCleanupFallback(size_t n, void (*cleanup)(void*));
|
||||
void AddCleanupFallback(void* elem, void (*cleanup)(void*));
|
||||
|
||||
// Node contains the ptr of the object to be cleaned up and the associated
|
||||
// cleanup function ptr.
|
||||
struct CleanupNode {
|
||||
@ -124,34 +131,107 @@ class LIBPROTOBUF_EXPORT ArenaImpl {
|
||||
static size_t SizeOf(size_t i) {
|
||||
return sizeof(CleanupChunk) + (sizeof(CleanupNode) * (i - 1));
|
||||
}
|
||||
size_t len; // Number of elements currently present.
|
||||
size_t size; // Total elements in the list.
|
||||
CleanupChunk* next; // Next node in the list.
|
||||
CleanupNode nodes[1]; // True length is |size|.
|
||||
};
|
||||
|
||||
struct Block;
|
||||
class Block;
|
||||
|
||||
// Tracks per-thread info. ThreadInfos are kept in a linked list.
|
||||
struct ThreadInfo {
|
||||
void *owner; // &ThreadCache of this thread;
|
||||
Block* head; // Head of linked list of blocks.
|
||||
CleanupChunk* cleanup; // Head of cleanup list.
|
||||
ThreadInfo* next; // Next ThreadInfo in this linked list.
|
||||
// A thread-unsafe Arena that can only be used within its owning thread.
|
||||
class LIBPROTOBUF_EXPORT SerialArena {
|
||||
public:
|
||||
// The allocate/free methods here are a little strange, since SerialArena is
|
||||
// allocated inside a Block which it also manages. This is to avoid doing
|
||||
// an extra allocation for the SerialArena itself.
|
||||
|
||||
// Creates a new SerialArena inside Block* and returns it.
|
||||
static SerialArena* New(Block* b, void* owner, ArenaImpl* arena);
|
||||
|
||||
// Destroys this SerialArena, freeing all blocks with the given dealloc
|
||||
// function, except any block equal to |initial_block|.
|
||||
static uint64 Free(SerialArena* serial, Block* initial_block,
|
||||
void (*block_dealloc)(void*, size_t));
|
||||
|
||||
void CleanupList();
|
||||
uint64 SpaceUsed() const;
|
||||
|
||||
void* AllocateAligned(size_t n) {
|
||||
GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned.
|
||||
GOOGLE_DCHECK_GE(limit_, ptr_);
|
||||
if (GOOGLE_PREDICT_FALSE(static_cast<size_t>(limit_ - ptr_) < n)) {
|
||||
return AllocateAlignedFallback(n);
|
||||
}
|
||||
void* ret = ptr_;
|
||||
ptr_ += n;
|
||||
#ifdef ADDRESS_SANITIZER
|
||||
ASAN_UNPOISON_MEMORY_REGION(ret, n);
|
||||
#endif // ADDRESS_SANITIZER
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AddCleanup(void* elem, void (*cleanup)(void*)) {
|
||||
if (GOOGLE_PREDICT_FALSE(cleanup_ptr_ == cleanup_limit_)) {
|
||||
AddCleanupFallback(elem, cleanup);
|
||||
return;
|
||||
}
|
||||
cleanup_ptr_->elem = elem;
|
||||
cleanup_ptr_->cleanup = cleanup;
|
||||
cleanup_ptr_++;
|
||||
}
|
||||
|
||||
void* AllocateAlignedAndAddCleanup(size_t n, void (*cleanup)(void*)) {
|
||||
void* ret = AllocateAligned(n);
|
||||
AddCleanup(ret, cleanup);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void* owner() const { return owner_; }
|
||||
SerialArena* next() const { return next_; }
|
||||
void set_next(SerialArena* next) { next_ = next; }
|
||||
|
||||
private:
|
||||
void* AllocateAlignedFallback(size_t n);
|
||||
void AddCleanupFallback(void* elem, void (*cleanup)(void*));
|
||||
void CleanupListFallback();
|
||||
|
||||
ArenaImpl* arena_; // Containing arena.
|
||||
void* owner_; // &ThreadCache of this thread;
|
||||
Block* head_; // Head of linked list of blocks.
|
||||
CleanupChunk* cleanup_; // Head of cleanup list.
|
||||
SerialArena* next_; // Next SerialArena in this linked list.
|
||||
|
||||
// Next pointer to allocate from. Always 8-byte aligned. Points inside
|
||||
// head_ (and head_->pos will always be non-canonical). We keep these
|
||||
// here to reduce indirection.
|
||||
char* ptr_;
|
||||
char* limit_;
|
||||
|
||||
// Next CleanupList members to append to. These point inside cleanup_.
|
||||
CleanupNode* cleanup_ptr_;
|
||||
CleanupNode* cleanup_limit_;
|
||||
};
|
||||
|
||||
// Blocks are variable length malloc-ed objects. The following structure
|
||||
// describes the common header for all blocks.
|
||||
struct Block {
|
||||
void* owner; // &ThreadCache of thread that owns this block.
|
||||
ThreadInfo* thread_info; // ThreadInfo of thread that owns this block.
|
||||
Block* next; // Next block in arena (may have different owner)
|
||||
// ((char*) &block) + pos is next available byte. It is always
|
||||
// aligned at a multiple of 8 bytes.
|
||||
size_t pos;
|
||||
size_t size; // total size of the block.
|
||||
GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE
|
||||
size_t avail() const { return size - pos; }
|
||||
class LIBPROTOBUF_EXPORT Block {
|
||||
public:
|
||||
Block(size_t size, Block* next);
|
||||
|
||||
char* Pointer(size_t n) {
|
||||
GOOGLE_DCHECK(n <= size_);
|
||||
return reinterpret_cast<char*>(this) + n;
|
||||
}
|
||||
|
||||
Block* next() const { return next_; }
|
||||
size_t pos() const { return pos_; }
|
||||
size_t size() const { return size_; }
|
||||
void set_pos(size_t pos) { pos_ = pos; }
|
||||
|
||||
private:
|
||||
Block* next_; // Next block for this thread.
|
||||
size_t pos_;
|
||||
size_t size_;
|
||||
// data follows
|
||||
};
|
||||
|
||||
@ -160,13 +240,13 @@ class LIBPROTOBUF_EXPORT ArenaImpl {
|
||||
// If we are using the ThreadLocalStorage class to store the ThreadCache,
|
||||
// then the ThreadCache's default constructor has to be responsible for
|
||||
// initializing it.
|
||||
ThreadCache() : last_lifecycle_id_seen(-1), last_block_used_(NULL) {}
|
||||
ThreadCache() : last_lifecycle_id_seen(-1), last_serial_arena(NULL) {}
|
||||
#endif
|
||||
|
||||
// The ThreadCache is considered valid as long as this matches the
|
||||
// lifecycle_id of the arena being used.
|
||||
int64 last_lifecycle_id_seen;
|
||||
Block* last_block_used_;
|
||||
SerialArena* last_serial_arena;
|
||||
};
|
||||
static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
|
||||
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
|
||||
@ -188,38 +268,30 @@ class LIBPROTOBUF_EXPORT ArenaImpl {
|
||||
// Free all blocks and return the total space used which is the sums of sizes
|
||||
// of the all the allocated blocks.
|
||||
uint64 FreeBlocks();
|
||||
|
||||
void AddCleanupInBlock(Block* b, void* elem, void (*func)(void*));
|
||||
CleanupChunk* ExpandCleanupList(CleanupChunk* cleanup, Block* b);
|
||||
// Delete or Destruct all objects owned by the arena.
|
||||
void CleanupList();
|
||||
|
||||
inline void CacheBlock(Block* block) {
|
||||
thread_cache().last_block_used_ = block;
|
||||
inline void CacheSerialArena(SerialArena* serial) {
|
||||
thread_cache().last_serial_arena = serial;
|
||||
thread_cache().last_lifecycle_id_seen = lifecycle_id_;
|
||||
// TODO(haberman): evaluate whether we would gain efficiency by getting rid
|
||||
// of hint_. It's the only write we do to ArenaImpl in the allocation path,
|
||||
// which will dirty the cache line.
|
||||
google::protobuf::internal::Release_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(block));
|
||||
google::protobuf::internal::Release_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(serial));
|
||||
}
|
||||
|
||||
google::protobuf::internal::AtomicWord threads_; // Pointer to a linked list of ThreadInfo.
|
||||
google::protobuf::internal::AtomicWord threads_; // Pointer to a linked list of SerialArena.
|
||||
google::protobuf::internal::AtomicWord hint_; // Fast thread-local block access
|
||||
google::protobuf::internal::AtomicWord space_allocated_; // Sum of sizes of all allocated blocks.
|
||||
|
||||
Block *initial_block_; // If non-NULL, points to the block that came from
|
||||
// user data.
|
||||
|
||||
// Returns a block owned by this thread.
|
||||
Block* GetBlock(size_t n);
|
||||
Block* GetBlockSlow(void* me, Block* my_full_block, size_t n);
|
||||
Block* NewBlock(void* me, Block* my_last_block, size_t min_bytes);
|
||||
void InitBlock(Block* b, void *me, size_t size);
|
||||
static void* AllocFromBlock(Block* b, size_t n);
|
||||
ThreadInfo* NewThreadInfo(Block* b);
|
||||
ThreadInfo* FindThreadInfo(void* me);
|
||||
ThreadInfo* GetThreadInfo(void* me, size_t n);
|
||||
Block* NewBlock(Block* last_block, size_t min_bytes);
|
||||
|
||||
SerialArena* GetSerialArena();
|
||||
bool GetSerialArenaFast(SerialArena** arena);
|
||||
SerialArena* GetSerialArenaFallback(void* me);
|
||||
int64 lifecycle_id_; // Unique for each arena. Changes on Reset().
|
||||
|
||||
Options options_;
|
||||
@ -227,11 +299,15 @@ class LIBPROTOBUF_EXPORT ArenaImpl {
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArenaImpl);
|
||||
|
||||
public:
|
||||
// kHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8 to
|
||||
// protect the invariant that pos is always at a multiple of 8.
|
||||
static const size_t kHeaderSize = (sizeof(Block) + 7) & -8;
|
||||
// kBlockHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8
|
||||
// to protect the invariant that pos is always at a multiple of 8.
|
||||
static const size_t kBlockHeaderSize = (sizeof(Block) + 7) & -8;
|
||||
static const size_t kSerialArenaSize = (sizeof(SerialArena) + 7) & -8;
|
||||
#if LANG_CXX11
|
||||
static_assert(kHeaderSize % 8 == 0, "kHeaderSize must be a multiple of 8.");
|
||||
static_assert(kBlockHeaderSize % 8 == 0,
|
||||
"kBlockHeaderSize must be a multiple of 8.");
|
||||
static_assert(kSerialArenaSize % 8 == 0,
|
||||
"kSerialArenaSize must be a multiple of 8.");
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -67,7 +67,6 @@ using protobuf_unittest::TestOneof2;
|
||||
using protobuf_unittest::TestEmptyMessage;
|
||||
|
||||
namespace protobuf {
|
||||
namespace {
|
||||
|
||||
class Notifier {
|
||||
public:
|
||||
@ -270,7 +269,7 @@ TEST(ArenaTest, InitialBlockTooSmall) {
|
||||
// Construct a small (64 byte) initial block of memory to be used by the
|
||||
// arena allocator; then, allocate an object which will not fit in the
|
||||
// initial block.
|
||||
std::vector<char> arena_block(72);
|
||||
std::vector<char> arena_block(96);
|
||||
ArenaOptions options;
|
||||
options.initial_block = &arena_block[0];
|
||||
options.initial_block_size = arena_block.size();
|
||||
@ -1299,12 +1298,12 @@ TEST(ArenaTest, SpaceAllocated_and_Used) {
|
||||
options.initial_block_size = 0;
|
||||
Arena arena_3(options);
|
||||
EXPECT_EQ(0, arena_3.SpaceUsed());
|
||||
::google::protobuf::Arena::CreateArray<char>(&arena_3, 182);
|
||||
::google::protobuf::Arena::CreateArray<char>(&arena_3, 160);
|
||||
EXPECT_EQ(256, arena_3.SpaceAllocated());
|
||||
EXPECT_EQ(Align8(182), arena_3.SpaceUsed());
|
||||
EXPECT_EQ(Align8(160), arena_3.SpaceUsed());
|
||||
::google::protobuf::Arena::CreateArray<char>(&arena_3, 70);
|
||||
EXPECT_EQ(256 + 512, arena_3.SpaceAllocated());
|
||||
EXPECT_EQ(Align8(182) + Align8(70), arena_3.SpaceUsed());
|
||||
EXPECT_EQ(Align8(160) + Align8(70), arena_3.SpaceUsed());
|
||||
EXPECT_EQ(256 + 512, arena_3.Reset());
|
||||
}
|
||||
|
||||
@ -1347,6 +1346,13 @@ TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaAllocatedMessages) {
|
||||
EXPECT_EQ(NULL, Arena::GetArena(const_pointer_to_message));
|
||||
}
|
||||
|
||||
TEST(ArenaTest, AddCleanup) {
|
||||
::google::protobuf::Arena arena;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
arena.Own(new int);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ArenaTest, UnsafeSetAllocatedOnArena) {
|
||||
::google::protobuf::Arena arena;
|
||||
TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
|
||||
@ -1405,13 +1411,20 @@ uint32 ArenaHooksTestUtil::num_reset = 0;
|
||||
uint32 ArenaHooksTestUtil::num_destruct = 0;
|
||||
const int ArenaHooksTestUtil::kCookieValue;
|
||||
|
||||
class ArenaOptionsTestFriend {
|
||||
public:
|
||||
static void Set(::google::protobuf::ArenaOptions* options) {
|
||||
options->on_arena_init = ArenaHooksTestUtil::on_init;
|
||||
options->on_arena_allocation = ArenaHooksTestUtil::on_allocation;
|
||||
options->on_arena_reset = ArenaHooksTestUtil::on_reset;
|
||||
options->on_arena_destruction = ArenaHooksTestUtil::on_destruction;
|
||||
}
|
||||
};
|
||||
|
||||
// Test the hooks are correctly called and that the cookie is passed.
|
||||
TEST(ArenaTest, ArenaHooksSanity) {
|
||||
::google::protobuf::ArenaOptions options;
|
||||
options.on_arena_init = ArenaHooksTestUtil::on_init;
|
||||
options.on_arena_allocation = ArenaHooksTestUtil::on_allocation;
|
||||
options.on_arena_reset = ArenaHooksTestUtil::on_reset;
|
||||
options.on_arena_destruction = ArenaHooksTestUtil::on_destruction;
|
||||
ArenaOptionsTestFriend::Set(&options);
|
||||
|
||||
// Scope for defining the arena
|
||||
{
|
||||
@ -1433,6 +1446,5 @@ TEST(ArenaTest, ArenaHooksSanity) {
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
@ -51,6 +51,18 @@ namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
template <typename T>
|
||||
class TaggedPtr {
|
||||
public:
|
||||
void Set(T* p) { ptr_ = reinterpret_cast<uintptr_t>(p); }
|
||||
T* Get() const { return reinterpret_cast<T*>(ptr_); }
|
||||
|
||||
bool IsNull() { return ptr_ == 0; }
|
||||
|
||||
private:
|
||||
uintptr_t ptr_;
|
||||
};
|
||||
|
||||
struct LIBPROTOBUF_EXPORT ArenaStringPtr {
|
||||
inline void Set(const ::std::string* default_value,
|
||||
const ::std::string& value, ::google::protobuf::Arena* arena) {
|
||||
@ -294,6 +306,15 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
|
||||
return ptr_ == default_value;
|
||||
}
|
||||
|
||||
// Internal accessors!!!!
|
||||
void UnsafeSetTaggedPointer(TaggedPtr< ::std::string> value) {
|
||||
ptr_ = value.Get();
|
||||
}
|
||||
// Generated code only! An optimization, in certain cases the generated
|
||||
// code is certain we can obtain a string with no default checks and
|
||||
// tag tests.
|
||||
::std::string* UnsafeMutablePointer() { return ptr_; }
|
||||
|
||||
private:
|
||||
::std::string* ptr_;
|
||||
|
||||
|
@ -76,10 +76,9 @@ void AddFile(const string& filename, const string& data) {
|
||||
true));
|
||||
}
|
||||
|
||||
bool CaptureMetadata(const string& filename, const string& plugin_specific_args,
|
||||
const string& meta_file_suffix, CommandLineInterface* cli,
|
||||
FileDescriptorProto* file,
|
||||
std::vector<ExpectedOutput>* outputs) {
|
||||
bool RunProtoCompiler(const string& filename,
|
||||
const string& plugin_specific_args,
|
||||
CommandLineInterface* cli, FileDescriptorProto* file) {
|
||||
cli->SetInputsAreProtoPathRelative(true);
|
||||
|
||||
DescriptorCapturingGenerator capturing_generator(file);
|
||||
@ -92,24 +91,7 @@ bool CaptureMetadata(const string& filename, const string& plugin_specific_args,
|
||||
plugin_specific_args.c_str(), capture_out.c_str(),
|
||||
filename.c_str()};
|
||||
|
||||
if (cli->Run(5, argv) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outputs != NULL) {
|
||||
for (std::vector<ExpectedOutput>::iterator i = outputs->begin();
|
||||
i != outputs->end(); ++i) {
|
||||
GOOGLE_CHECK_OK(File::GetContents(TestTempDir() + "/" + i->file_path,
|
||||
&i->file_content, true));
|
||||
if (!DecodeMetadata(
|
||||
TestTempDir() + "/" + i->file_path + meta_file_suffix,
|
||||
&i->file_info)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return cli->Run(5, argv) == 0;
|
||||
}
|
||||
|
||||
bool DecodeMetadata(const string& path, GeneratedCodeInfo* info) {
|
||||
|
@ -59,25 +59,20 @@ struct ExpectedOutput {
|
||||
// directory.
|
||||
void AddFile(const string& filename, const string& data);
|
||||
|
||||
// Tries to capture a FileDescriptorProto, GeneratedCodeInfo, and output
|
||||
// code from the previously added file with name `filename`.
|
||||
// Runs proto compiler. Captures proto file structrue in FileDescriptorProto.
|
||||
// Files will be generated in TestTempDir() folder. Callers of this
|
||||
// function must read generated files themselves.
|
||||
//
|
||||
// filename: source .proto file used to generate code.
|
||||
// plugin_specific_args: command line arguments specific to current generator.
|
||||
// For Java, this value might be "--java_out=annotate_code:test_temp_dir"
|
||||
// meta_file_suffix: suffix of meta files that contain annotations. For Java
|
||||
// it is ".pb.meta" because for file Foo.java meta file is Foo.java.pb.meta
|
||||
// cli: instance of command line interface to run generator. See Java's
|
||||
// annotation_unittest.cc for an example of how to initialize it.
|
||||
// file: output parameter, will be set to the descriptor of the proto file
|
||||
// specified in filename.
|
||||
// outputs: output parameter. If not NULL, each ExpectedOutput in the vector
|
||||
// should have its file_path set; CaptureMetadata will fill the rest of
|
||||
// the fields appropriately.
|
||||
bool CaptureMetadata(const string& filename, const string& plugin_specific_args,
|
||||
const string& meta_file_suffix, CommandLineInterface* cli,
|
||||
FileDescriptorProto* file,
|
||||
std::vector<ExpectedOutput>* outputs);
|
||||
bool RunProtoCompiler(const string& filename,
|
||||
const string& plugin_specific_args,
|
||||
CommandLineInterface* cli, FileDescriptorProto* file);
|
||||
|
||||
bool DecodeMetadata(const string& path, GeneratedCodeInfo* info);
|
||||
|
||||
|
@ -195,7 +195,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
"inline $type$ $classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" return static_cast< $type$ >($oneof_prefix$$name$_);\n"
|
||||
" return static_cast< $type$ >($field_member$);\n"
|
||||
" }\n"
|
||||
" return static_cast< $type$ >($default$);\n"
|
||||
"}\n"
|
||||
@ -209,14 +209,14 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_ = value;\n"
|
||||
" $field_member$ = value;\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n");
|
||||
printer->Print(variables_, "$field_member$ = $default$;\n");
|
||||
}
|
||||
|
||||
void EnumOneofFieldGenerator::
|
||||
|
@ -67,12 +67,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||
(*variables)["classname"] = ClassName(FieldScope(descriptor), false);
|
||||
(*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
|
||||
|
||||
// non_null_ptr_to_name is usable only if has_$name$ is true. It yields a
|
||||
// pointer that will not be NULL. Subclasses of FieldGenerator may set
|
||||
// (*variables)["non_null_ptr_to_name"] differently.
|
||||
(*variables)["non_null_ptr_to_name"] =
|
||||
StrCat("&this->", FieldName(descriptor), "()");
|
||||
(*variables)["field_member"] = FieldName(descriptor) + "_";
|
||||
|
||||
(*variables)["tag_size"] = SimpleItoa(
|
||||
WireFormat::TagSize(descriptor->number(), descriptor->type()));
|
||||
@ -81,8 +76,6 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
(*variables)["deprecated_attr"] = descriptor->options().deprecated()
|
||||
? "GOOGLE_PROTOBUF_DEPRECATED_ATTR " : "";
|
||||
|
||||
(*variables)["cppget"] = "Get";
|
||||
|
||||
if (HasFieldPresence(descriptor->file())) {
|
||||
(*variables)["set_hasbit"] =
|
||||
"set_has_" + FieldName(descriptor) + "();";
|
||||
@ -93,10 +86,6 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
(*variables)["clear_hasbit"] = "";
|
||||
}
|
||||
|
||||
// By default, empty string, so that generic code used for both oneofs and
|
||||
// singular fields can be written.
|
||||
(*variables)["oneof_prefix"] = "";
|
||||
|
||||
// These variables are placeholders to pick out the beginning and ends of
|
||||
// identifiers for annotations (when doing so with existing variables would
|
||||
// be ambiguous or impossible). They should never be set to anything but the
|
||||
@ -108,10 +97,8 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
|
||||
std::map<string, string>* variables) {
|
||||
const string prefix = descriptor->containing_oneof()->name() + "_.";
|
||||
(*variables)["oneof_prefix"] = prefix;
|
||||
(*variables)["oneof_name"] = descriptor->containing_oneof()->name();
|
||||
(*variables)["non_null_ptr_to_name"] =
|
||||
StrCat(prefix, (*variables)["name"], "_");
|
||||
(*variables)["field_member"] = StrCat(prefix, (*variables)["name"], "_");
|
||||
}
|
||||
|
||||
FieldGenerator::~FieldGenerator() {}
|
||||
|
@ -184,6 +184,10 @@ class FieldGenerator {
|
||||
// message's MergeFromCodedStream() method.
|
||||
virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
|
||||
|
||||
// Returns true if this field's "MergeFromCodedStream" code needs the arena
|
||||
// to be defined as a variable.
|
||||
virtual bool MergeFromCodedStreamNeedsArena() const { return false; }
|
||||
|
||||
// Generate lines to decode this field from a packed value, which will be
|
||||
// placed inside the message's MergeFromCodedStream() method.
|
||||
virtual void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer)
|
||||
|
@ -397,7 +397,7 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) {
|
||||
|
||||
// Define default instances
|
||||
GenerateSourceDefaultInstance(idx, printer);
|
||||
if (UsingImplicitWeakFields(file_, options_)) {
|
||||
if (options_.lite_implicit_weak_fields) {
|
||||
printer->Print("void $classname$_ReferenceStrong() {}\n", "classname",
|
||||
message_generators_[idx]->classname_);
|
||||
}
|
||||
@ -416,6 +416,13 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) {
|
||||
GenerateInitForSCC(GetSCC(message_generators_[idx]->descriptor_), printer);
|
||||
}
|
||||
|
||||
|
||||
printer->Print(
|
||||
"namespace google {\nnamespace protobuf {\n");
|
||||
message_generators_[idx]->GenerateSourceInProto2Namespace(printer);
|
||||
printer->Print(
|
||||
"} // namespace protobuf\n} // namespace google\n");
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"// @@protoc_insertion_point(global_scope)\n");
|
||||
@ -467,7 +474,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
|
||||
// Define default instances
|
||||
for (int i = 0; i < message_generators_.size(); i++) {
|
||||
GenerateSourceDefaultInstance(i, printer);
|
||||
if (UsingImplicitWeakFields(file_, options_)) {
|
||||
if (options_.lite_implicit_weak_fields) {
|
||||
printer->Print("void $classname$_ReferenceStrong() {}\n", "classname",
|
||||
message_generators_[i]->classname_);
|
||||
}
|
||||
@ -525,6 +532,15 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
|
||||
"\n"
|
||||
"// @@protoc_insertion_point(namespace_scope)\n");
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"namespace google {\nnamespace protobuf {\n");
|
||||
for (int i = 0; i < message_generators_.size(); i++) {
|
||||
message_generators_[i]->GenerateSourceInProto2Namespace(printer);
|
||||
}
|
||||
printer->Print(
|
||||
"} // namespace protobuf\n} // namespace google\n");
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"// @@protoc_insertion_point(global_scope)\n");
|
||||
@ -553,7 +569,42 @@ class FileGenerator::ForwardDeclarations {
|
||||
std::map<string, const Descriptor*>& classes() { return classes_; }
|
||||
std::map<string, const EnumDescriptor*>& enums() { return enums_; }
|
||||
|
||||
void Print(io::Printer* printer, const Options& options) const {
|
||||
void PrintForwardDeclarations(io::Printer* printer,
|
||||
const Options& options) const {
|
||||
PrintNestedDeclarations(printer, options);
|
||||
PrintTopLevelDeclarations(printer, options);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
void PrintNestedDeclarations(io::Printer* printer,
|
||||
const Options& options) const {
|
||||
PrintDeclarationsInsideNamespace(printer, options);
|
||||
for (std::map<string, ForwardDeclarations *>::const_iterator
|
||||
it = namespaces_.begin(),
|
||||
end = namespaces_.end();
|
||||
it != end; ++it) {
|
||||
printer->Print("namespace $nsname$ {\n",
|
||||
"nsname", it->first);
|
||||
it->second->PrintNestedDeclarations(printer, options);
|
||||
printer->Print("} // namespace $nsname$\n",
|
||||
"nsname", it->first);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintTopLevelDeclarations(io::Printer* printer,
|
||||
const Options& options) const {
|
||||
PrintDeclarationsOutsideNamespace(printer, options);
|
||||
for (std::map<string, ForwardDeclarations *>::const_iterator
|
||||
it = namespaces_.begin(),
|
||||
end = namespaces_.end();
|
||||
it != end; ++it) {
|
||||
it->second->PrintTopLevelDeclarations(printer, options);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintDeclarationsInsideNamespace(io::Printer* printer,
|
||||
const Options& options) const {
|
||||
for (std::map<string, const EnumDescriptor *>::const_iterator
|
||||
it = enums_.begin(),
|
||||
end = enums_.end();
|
||||
@ -584,20 +635,36 @@ class FileGenerator::ForwardDeclarations {
|
||||
"classname", it->first);
|
||||
}
|
||||
}
|
||||
for (std::map<string, ForwardDeclarations *>::const_iterator
|
||||
it = namespaces_.begin(),
|
||||
end = namespaces_.end();
|
||||
it != end; ++it) {
|
||||
printer->Print("namespace $nsname$ {\n",
|
||||
"nsname", it->first);
|
||||
it->second->Print(printer, options);
|
||||
printer->Print("} // namespace $nsname$\n",
|
||||
"nsname", it->first);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintDeclarationsOutsideNamespace(io::Printer* printer,
|
||||
const Options& options) const {
|
||||
if (classes_.size() == 0) return;
|
||||
|
||||
printer->Print(
|
||||
"namespace google {\nnamespace protobuf {\n");
|
||||
for (std::map<string, const Descriptor*>::const_iterator
|
||||
it = classes_.begin(),
|
||||
end = classes_.end();
|
||||
it != end; ++it) {
|
||||
const Descriptor* d = it->second;
|
||||
string extra_class_qualifier;
|
||||
// "class" is to disambiguate in case there is also a function with this
|
||||
// name. There is code out there that does this!
|
||||
printer->Print(
|
||||
"template<> "
|
||||
"$dllexport_decl$"
|
||||
"$class$$classname$* Arena::$func$< $class$$classname$>(Arena*);\n",
|
||||
"classname", QualifiedClassName(d),
|
||||
"func", MessageCreateFunction(d),
|
||||
"class", extra_class_qualifier,
|
||||
"dllexport_decl",
|
||||
options.dllexport_decl.empty() ? "" : options.dllexport_decl + " ");
|
||||
}
|
||||
printer->Print(
|
||||
"} // namespace protobuf\n} // namespace google\n");
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<string, ForwardDeclarations*> namespaces_;
|
||||
std::map<string, const Descriptor*> classes_;
|
||||
std::map<string, const EnumDescriptor*> enums_;
|
||||
@ -1053,7 +1120,7 @@ void FileGenerator::GenerateInitializationCode(io::Printer* printer) {
|
||||
void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
|
||||
ForwardDeclarations decls;
|
||||
FillForwardDeclarations(&decls);
|
||||
decls.Print(printer, options_);
|
||||
decls.PrintForwardDeclarations(printer, options_);
|
||||
}
|
||||
|
||||
void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) {
|
||||
|
@ -41,12 +41,12 @@
|
||||
#endif
|
||||
#include <utility>
|
||||
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_file.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
@ -85,7 +85,6 @@ bool CppGenerator::Generate(const FileDescriptor* file,
|
||||
// __declspec(dllimport) depending on what is being compiled.
|
||||
//
|
||||
Options file_options;
|
||||
bool split_source = false;
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
if (options[i].first == "dllexport_decl") {
|
||||
file_options.dllexport_decl = options[i].second;
|
||||
@ -101,18 +100,28 @@ bool CppGenerator::Generate(const FileDescriptor* file,
|
||||
file_options.enforce_lite = true;
|
||||
} else if (options[i].first == "lite_implicit_weak_fields") {
|
||||
file_options.lite_implicit_weak_fields = true;
|
||||
if (!options[i].second.empty()) {
|
||||
file_options.num_cc_files = strto32(options[i].second.c_str(),
|
||||
NULL, 10);
|
||||
}
|
||||
} else if (options[i].first == "table_driven_parsing") {
|
||||
file_options.table_driven_parsing = true;
|
||||
} else if (options[i].first == "table_driven_serialization") {
|
||||
file_options.table_driven_serialization = true;
|
||||
} else if (options[i].first == "split_source") {
|
||||
split_source = true;
|
||||
} else {
|
||||
*error = "Unknown generator option: " + options[i].first;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The safe_boundary_check option controls behavior for Google-internal
|
||||
// protobuf APIs.
|
||||
if (file_options.safe_boundary_check) {
|
||||
*error =
|
||||
"The safe_boundary_check option is not supported outside of Google.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
|
||||
@ -159,8 +168,8 @@ bool CppGenerator::Generate(const FileDescriptor* file,
|
||||
}
|
||||
}
|
||||
|
||||
// Generate cc file.
|
||||
if (split_source) {
|
||||
// Generate cc file(s).
|
||||
if (UsingImplicitWeakFields(file, file_options)) {
|
||||
{
|
||||
// This is the global .cc file, containing enum/services/tables/reflection
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
@ -168,12 +177,26 @@ bool CppGenerator::Generate(const FileDescriptor* file,
|
||||
io::Printer printer(output.get(), '$');
|
||||
file_generator.GenerateGlobalSource(&printer);
|
||||
}
|
||||
for (int i = 0; i < file_generator.NumMessages(); i++) {
|
||||
|
||||
int num_cc_files = file_generator.NumMessages();
|
||||
|
||||
// If we're using implicit weak fields then we allow the user to optionally
|
||||
// specify how many files to generate, not counting the global pb.cc file.
|
||||
// If we have more files than messages, then some files will be generated as
|
||||
// empty placeholders.
|
||||
if (file_options.num_cc_files > 0) {
|
||||
GOOGLE_CHECK_LE(file_generator.NumMessages(), file_options.num_cc_files)
|
||||
<< "There must be at least as many numbered .cc files as messages.";
|
||||
num_cc_files = file_options.num_cc_files;
|
||||
}
|
||||
for (int i = 0; i < num_cc_files; i++) {
|
||||
// TODO(gerbens) Agree on naming scheme.
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
generator_context->Open(basename + "." + SimpleItoa(i) + ".cc"));
|
||||
io::Printer printer(output.get(), '$');
|
||||
file_generator.GenerateSourceForMessage(i, &printer);
|
||||
if (i < file_generator.NumMessages()) {
|
||||
file_generator.GenerateSourceForMessage(i, &printer);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
|
||||
|
@ -752,7 +752,7 @@ bool UsingImplicitWeakFields(const FileDescriptor* file,
|
||||
bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options) {
|
||||
return UsingImplicitWeakFields(field->file(), options) &&
|
||||
field->type() == FieldDescriptor::TYPE_MESSAGE &&
|
||||
!field->is_required() && !field->is_repeated() && !field->is_map() &&
|
||||
!field->is_required() && !field->is_map() &&
|
||||
field->containing_oneof() == NULL;
|
||||
}
|
||||
|
||||
|
@ -310,6 +310,10 @@ inline bool IsCrossFileMessage(const FieldDescriptor* field) {
|
||||
field->message_type()->file() != field->file();
|
||||
}
|
||||
|
||||
inline string MessageCreateFunction(const Descriptor* d) {
|
||||
return SupportsArenas(d) ? "CreateMessage" : "Create";
|
||||
}
|
||||
|
||||
bool IsAnyMessage(const FileDescriptor* descriptor);
|
||||
bool IsAnyMessage(const Descriptor* descriptor);
|
||||
|
||||
|
@ -325,6 +325,109 @@ bool IsCrossFileMaybeMap(const FieldDescriptor* field) {
|
||||
return IsCrossFileMessage(field);
|
||||
}
|
||||
|
||||
bool IsRequired(const std::vector<const FieldDescriptor*>& v) {
|
||||
return v.front()->is_required();
|
||||
}
|
||||
|
||||
// Allows chunking repeated fields together and non-repeated fields if the
|
||||
// fields share the same has_byte index.
|
||||
// TODO(seongkim): use lambda with capture instead of functor.
|
||||
class MatchRepeatedAndHasByte {
|
||||
public:
|
||||
MatchRepeatedAndHasByte(const std::vector<int>* has_bit_indices,
|
||||
bool has_field_presence)
|
||||
: has_bit_indices_(*has_bit_indices),
|
||||
has_field_presence_(has_field_presence) {}
|
||||
|
||||
// Returns true if the following conditions are met:
|
||||
// --both fields are repeated fields
|
||||
// --both fields are non-repeated fields with either has_field_presence is
|
||||
// false or have the same has_byte index.
|
||||
bool operator()(const FieldDescriptor* a, const FieldDescriptor* b) const {
|
||||
return a->is_repeated() == b->is_repeated() &&
|
||||
(!has_field_presence_ || a->is_repeated() ||
|
||||
has_bit_indices_[a->index()] / 8 ==
|
||||
has_bit_indices_[b->index()] / 8);
|
||||
}
|
||||
|
||||
private:
|
||||
const std::vector<int>& has_bit_indices_;
|
||||
const bool has_field_presence_;
|
||||
};
|
||||
|
||||
// Allows chunking required fields separately after chunking with
|
||||
// MatchRepeatedAndHasByte.
|
||||
class MatchRepeatedAndHasByteAndRequired : public MatchRepeatedAndHasByte {
|
||||
public:
|
||||
MatchRepeatedAndHasByteAndRequired(const std::vector<int>* has_bit_indices,
|
||||
bool has_field_presence)
|
||||
: MatchRepeatedAndHasByte(has_bit_indices, has_field_presence) {}
|
||||
|
||||
bool operator()(const FieldDescriptor* a, const FieldDescriptor* b) const {
|
||||
return MatchRepeatedAndHasByte::operator()(a, b) &&
|
||||
a->is_required() == b->is_required();
|
||||
}
|
||||
};
|
||||
|
||||
// Allows chunking zero-initializable fields separately after chunking with
|
||||
// MatchRepeatedAndHasByte.
|
||||
class MatchRepeatedAndHasByteAndZeroInits : public MatchRepeatedAndHasByte {
|
||||
public:
|
||||
MatchRepeatedAndHasByteAndZeroInits(const std::vector<int>* has_bit_indices,
|
||||
bool has_field_presence)
|
||||
: MatchRepeatedAndHasByte(has_bit_indices, has_field_presence) {}
|
||||
|
||||
bool operator()(const FieldDescriptor* a, const FieldDescriptor* b) const {
|
||||
return MatchRepeatedAndHasByte::operator()(a, b) &&
|
||||
CanInitializeByZeroing(a) == CanInitializeByZeroing(b);
|
||||
}
|
||||
};
|
||||
|
||||
// Collects neighboring fields based on a given criteria (equivalent predicate).
|
||||
template <typename Predicate>
|
||||
std::vector<std::vector<const FieldDescriptor*> > CollectFields(
|
||||
const std::vector<const FieldDescriptor*>& fields,
|
||||
const Predicate& equivalent) {
|
||||
std::vector<std::vector<const FieldDescriptor*> > chunks;
|
||||
if (fields.empty()) {
|
||||
return chunks;
|
||||
}
|
||||
|
||||
const FieldDescriptor* last_field = fields.front();
|
||||
std::vector<const FieldDescriptor*> chunk;
|
||||
for (int i = 0; i < fields.size(); i++) {
|
||||
if (!equivalent(last_field, fields[i]) && !chunk.empty()) {
|
||||
chunks.push_back(chunk);
|
||||
chunk.clear();
|
||||
}
|
||||
chunk.push_back(fields[i]);
|
||||
last_field = fields[i];
|
||||
}
|
||||
if (!chunk.empty()) {
|
||||
chunks.push_back(chunk);
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
|
||||
// Returns a bit mask based on has_bit index of "fields" that are typically on
|
||||
// the same chunk. It is used in a group presence check where _has_bits_ is
|
||||
// masked to tell if any thing in "fields" is present.
|
||||
uint32 GenChunkMask(const std::vector<const FieldDescriptor*>& fields,
|
||||
const std::vector<int>& has_bit_indices) {
|
||||
GOOGLE_CHECK(!fields.empty());
|
||||
int first_index_offset = has_bit_indices[fields.front()->index()] / 32;
|
||||
uint32 chunk_mask = 0;
|
||||
for (int i = 0; i < fields.size(); i++) {
|
||||
const FieldDescriptor* field = fields[i];
|
||||
// "index" defines where in the _has_bits_ the field appears.
|
||||
int index = has_bit_indices[field->index()];
|
||||
GOOGLE_CHECK_EQ(first_index_offset, index / 32);
|
||||
chunk_mask |= static_cast<uint32>(1) << (index % 32);
|
||||
}
|
||||
GOOGLE_CHECK_NE(0, chunk_mask);
|
||||
return chunk_mask;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// ===================================================================
|
||||
@ -993,6 +1096,7 @@ GenerateClassDefinition(io::Printer* printer) {
|
||||
|
||||
vars["new_final"] = " PROTOBUF_FINAL";
|
||||
|
||||
vars["create_func"] = MessageCreateFunction(descriptor_);
|
||||
printer->Print(vars,
|
||||
"void Swap($classname$* other);\n"
|
||||
"friend void swap($classname$& a, $classname$& b) {\n"
|
||||
@ -1001,9 +1105,13 @@ GenerateClassDefinition(io::Printer* printer) {
|
||||
"\n"
|
||||
"// implements Message ----------------------------------------------\n"
|
||||
"\n"
|
||||
"inline $classname$* New() const$new_final$ { return New(NULL); }\n"
|
||||
"inline $classname$* New() const$new_final$ {\n"
|
||||
" return ::google::protobuf::Arena::$create_func$<$classname$>(NULL);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"$classname$* New(::google::protobuf::Arena* arena) const$new_final$;\n");
|
||||
"$classname$* New(::google::protobuf::Arena* arena) const$new_final$ {\n"
|
||||
" return ::google::protobuf::Arena::$create_func$<$classname$>(arena);\n"
|
||||
"}\n");
|
||||
|
||||
// For instances that derive from Message (rather than MessageLite), some
|
||||
// methods are virtual and should be marked as final.
|
||||
@ -2452,112 +2560,125 @@ GenerateStructors(io::Printer* printer) {
|
||||
}
|
||||
|
||||
// Generate the copy constructor.
|
||||
printer->Print(
|
||||
"$classname$::$classname$(const $classname$& from)\n"
|
||||
" : $superclass$()",
|
||||
"classname", classname_,
|
||||
"superclass", superclass,
|
||||
"full_name", descriptor_->full_name());
|
||||
printer->Indent();
|
||||
printer->Indent();
|
||||
printer->Indent();
|
||||
if (UsingImplicitWeakFields(descriptor_->file(), options_)) {
|
||||
// If we are in lite mode and using implicit weak fields, we generate a
|
||||
// one-liner copy constructor that delegates to MergeFrom. This saves some
|
||||
// code size and also cuts down on the complexity of implicit weak fields.
|
||||
// We might eventually want to do this for all lite protos.
|
||||
printer->Print(
|
||||
"$classname$::$classname$(const $classname$& from)\n"
|
||||
" : $classname$() {\n"
|
||||
" MergeFrom(from);\n"
|
||||
"}\n",
|
||||
"classname", classname_);
|
||||
} else {
|
||||
printer->Print(
|
||||
"$classname$::$classname$(const $classname$& from)\n"
|
||||
" : $superclass$()",
|
||||
"classname", classname_,
|
||||
"superclass", superclass,
|
||||
"full_name", descriptor_->full_name());
|
||||
printer->Indent();
|
||||
printer->Indent();
|
||||
printer->Indent();
|
||||
|
||||
printer->Print(
|
||||
",\n_internal_metadata_(NULL)");
|
||||
printer->Print(
|
||||
",\n_internal_metadata_(NULL)");
|
||||
|
||||
if (HasFieldPresence(descriptor_->file())) {
|
||||
printer->Print(",\n_has_bits_(from._has_bits_)");
|
||||
}
|
||||
|
||||
bool need_to_emit_cached_size = true;
|
||||
const string cached_size_decl = ",\n_cached_size_(0)";
|
||||
// We reproduce the logic used for laying out _cached_sized_ in the class
|
||||
// definition, as to initialize it in-order.
|
||||
if (HasFieldPresence(descriptor_->file()) &&
|
||||
(HasBitsSize() % 8) != 0) {
|
||||
printer->Print(cached_size_decl.c_str());
|
||||
need_to_emit_cached_size = false;
|
||||
}
|
||||
|
||||
std::vector<bool> processed(optimized_order_.size(), false);
|
||||
for (int i = 0; i < optimized_order_.size(); ++i) {
|
||||
const FieldDescriptor* field = optimized_order_[i];
|
||||
|
||||
if (!(field->is_repeated() && !(field->is_map()))
|
||||
) {
|
||||
continue;
|
||||
if (HasFieldPresence(descriptor_->file())) {
|
||||
printer->Print(",\n_has_bits_(from._has_bits_)");
|
||||
}
|
||||
|
||||
processed[i] = true;
|
||||
printer->Print(",\n$name$_(from.$name$_)",
|
||||
"name", FieldName(field));
|
||||
}
|
||||
bool need_to_emit_cached_size = true;
|
||||
const string cached_size_decl = ",\n_cached_size_(0)";
|
||||
// We reproduce the logic used for laying out _cached_sized_ in the class
|
||||
// definition, as to initialize it in-order.
|
||||
if (HasFieldPresence(descriptor_->file()) &&
|
||||
(HasBitsSize() % 8) != 0) {
|
||||
printer->Print(cached_size_decl.c_str());
|
||||
need_to_emit_cached_size = false;
|
||||
}
|
||||
|
||||
if (need_to_emit_cached_size) {
|
||||
printer->Print(cached_size_decl.c_str());
|
||||
need_to_emit_cached_size = false;
|
||||
}
|
||||
std::vector<bool> processed(optimized_order_.size(), false);
|
||||
for (int i = 0; i < optimized_order_.size(); ++i) {
|
||||
const FieldDescriptor* field = optimized_order_[i];
|
||||
|
||||
if (IsAnyMessage(descriptor_)) {
|
||||
printer->Print(",\n_any_metadata_(&type_url_, &value_)");
|
||||
}
|
||||
if (num_weak_fields_ > 0) {
|
||||
printer->Print(",\n_weak_field_map_(from._weak_field_map_)");
|
||||
}
|
||||
if (!(field->is_repeated() && !(field->is_map()))
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Outdent();
|
||||
printer->Print(" {\n");
|
||||
processed[i] = true;
|
||||
printer->Print(",\n$name$_(from.$name$_)",
|
||||
"name", FieldName(field));
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"_internal_metadata_.MergeFrom(from._internal_metadata_);\n");
|
||||
if (need_to_emit_cached_size) {
|
||||
printer->Print(cached_size_decl.c_str());
|
||||
need_to_emit_cached_size = false;
|
||||
}
|
||||
|
||||
if (descriptor_->extension_range_count() > 0) {
|
||||
printer->Print("_extensions_.MergeFrom(from._extensions_);\n");
|
||||
}
|
||||
if (IsAnyMessage(descriptor_)) {
|
||||
printer->Print(",\n_any_metadata_(&type_url_, &value_)");
|
||||
}
|
||||
if (num_weak_fields_ > 0) {
|
||||
printer->Print(",\n_weak_field_map_(from._weak_field_map_)");
|
||||
}
|
||||
|
||||
GenerateConstructorBody(printer, processed, true);
|
||||
printer->Outdent();
|
||||
printer->Outdent();
|
||||
printer->Print(" {\n");
|
||||
|
||||
// Copy oneof fields. Oneof field requires oneof case check.
|
||||
for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
|
||||
printer->Print(
|
||||
"clear_has_$oneofname$();\n"
|
||||
"switch (from.$oneofname$_case()) {\n",
|
||||
"oneofname", descriptor_->oneof_decl(i)->name());
|
||||
printer->Indent();
|
||||
for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
|
||||
const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
|
||||
"_internal_metadata_.MergeFrom(from._internal_metadata_);\n");
|
||||
|
||||
if (descriptor_->extension_range_count() > 0) {
|
||||
printer->Print("_extensions_.MergeFrom(from._extensions_);\n");
|
||||
}
|
||||
|
||||
GenerateConstructorBody(printer, processed, true);
|
||||
|
||||
// Copy oneof fields. Oneof field requires oneof case check.
|
||||
for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
|
||||
printer->Print(
|
||||
"case k$field_name$: {\n",
|
||||
"field_name", UnderscoresToCamelCase(field->name(), true));
|
||||
"clear_has_$oneofname$();\n"
|
||||
"switch (from.$oneofname$_case()) {\n",
|
||||
"oneofname", descriptor_->oneof_decl(i)->name());
|
||||
printer->Indent();
|
||||
field_generators_.get(field).GenerateMergingCode(printer);
|
||||
for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
|
||||
const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
|
||||
printer->Print(
|
||||
"case k$field_name$: {\n",
|
||||
"field_name", UnderscoresToCamelCase(field->name(), true));
|
||||
printer->Indent();
|
||||
field_generators_.get(field).GenerateMergingCode(printer);
|
||||
printer->Print(
|
||||
"break;\n");
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n");
|
||||
}
|
||||
printer->Print(
|
||||
"break;\n");
|
||||
"case $cap_oneof_name$_NOT_SET: {\n"
|
||||
" break;\n"
|
||||
"}\n",
|
||||
"oneof_index",
|
||||
SimpleItoa(descriptor_->oneof_decl(i)->index()),
|
||||
"cap_oneof_name",
|
||||
ToUpper(descriptor_->oneof_decl(i)->name()));
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n");
|
||||
}
|
||||
printer->Print(
|
||||
"case $cap_oneof_name$_NOT_SET: {\n"
|
||||
" break;\n"
|
||||
"}\n",
|
||||
"oneof_index",
|
||||
SimpleItoa(descriptor_->oneof_decl(i)->index()),
|
||||
"cap_oneof_name",
|
||||
ToUpper(descriptor_->oneof_decl(i)->name()));
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n");
|
||||
" // @@protoc_insertion_point(copy_constructor:$full_name$)\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"full_name", descriptor_->full_name());
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
" // @@protoc_insertion_point(copy_constructor:$full_name$)\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"full_name", descriptor_->full_name());
|
||||
|
||||
// Generate the shared constructor code.
|
||||
GenerateSharedConstructorCode(printer);
|
||||
|
||||
@ -2610,24 +2731,17 @@ GenerateStructors(io::Printer* printer) {
|
||||
"}\n\n",
|
||||
"classname", classname_, "scc_name", scc_name_, "file_namespace",
|
||||
FileLevelNamespace(descriptor_));
|
||||
}
|
||||
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(
|
||||
"$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n"
|
||||
" return ::google::protobuf::Arena::CreateMessage<$classname$>(arena);\n"
|
||||
void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) {
|
||||
printer->Print(
|
||||
"template<> "
|
||||
"GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE "
|
||||
"$classname$* Arena::$create_func$< $classname$ >(Arena* arena) {\n"
|
||||
" return Arena::$create_func$Internal< $classname$ >(arena);\n"
|
||||
"}\n",
|
||||
"classname", classname_);
|
||||
} else {
|
||||
printer->Print(
|
||||
"$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n"
|
||||
" $classname$* n = new $classname$;\n"
|
||||
" if (arena != NULL) {\n"
|
||||
" arena->Own(n);\n"
|
||||
" }\n"
|
||||
" return n;\n"
|
||||
"}\n",
|
||||
"classname", classname_);
|
||||
}
|
||||
"classname", QualifiedClassName(descriptor_),
|
||||
"create_func", MessageCreateFunction(descriptor_));
|
||||
}
|
||||
|
||||
// Return the number of bits set in n, a non-negative integer.
|
||||
@ -2681,7 +2795,6 @@ GenerateClear(io::Printer* printer) {
|
||||
printer->Print("_extensions_.Clear();\n");
|
||||
}
|
||||
|
||||
int last_i = -1;
|
||||
int unconditional_budget = kMaxUnconditionalPrimitiveBytesClear;
|
||||
for (int i = 0; i < optimized_order_.size(); i++) {
|
||||
const FieldDescriptor* field = optimized_order_[i];
|
||||
@ -2693,197 +2806,162 @@ GenerateClear(io::Printer* printer) {
|
||||
unconditional_budget -= EstimateAlignmentSize(field);
|
||||
}
|
||||
|
||||
for (int i = 0; i < optimized_order_.size(); ) {
|
||||
// Detect infinite loops.
|
||||
GOOGLE_CHECK_NE(i, last_i);
|
||||
last_i = i;
|
||||
std::vector<std::vector<const FieldDescriptor*> > chunks_frag = CollectFields(
|
||||
optimized_order_,
|
||||
MatchRepeatedAndHasByteAndZeroInits(
|
||||
&has_bit_indices_, HasFieldPresence(descriptor_->file())));
|
||||
|
||||
// Merge next non-zero initializable chunk if it has the same has_byte index
|
||||
// and not meeting unconditional clear condition.
|
||||
std::vector<std::vector<const FieldDescriptor*> > chunks;
|
||||
if (!HasFieldPresence(descriptor_->file())) {
|
||||
// Don't bother with merging without has_bit field.
|
||||
chunks = chunks_frag;
|
||||
} else {
|
||||
// Note that only the next chunk is considered for merging.
|
||||
for (int i = 0; i < chunks_frag.size(); i++) {
|
||||
chunks.push_back(chunks_frag[i]);
|
||||
const FieldDescriptor* field = chunks_frag[i].front();
|
||||
const FieldDescriptor* next_field =
|
||||
(i + 1) < chunks_frag.size() ? chunks_frag[i + 1].front() : NULL;
|
||||
if (CanInitializeByZeroing(field) &&
|
||||
(chunks_frag[i].size() == 1 || unconditional_budget < 0) &&
|
||||
next_field != NULL &&
|
||||
has_bit_indices_[field->index()] / 8 ==
|
||||
has_bit_indices_[next_field->index()] / 8) {
|
||||
GOOGLE_CHECK(!CanInitializeByZeroing(next_field));
|
||||
// Insert next chunk to the current one and skip next chunk.
|
||||
chunks.back().insert(chunks.back().end(), chunks_frag[i + 1].begin(),
|
||||
chunks_frag[i + 1].end());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
|
||||
std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
|
||||
GOOGLE_CHECK(!chunk.empty());
|
||||
|
||||
// Step 2: Repeated fields don't use _has_bits_; emit code to clear them
|
||||
// here.
|
||||
for (; i < optimized_order_.size(); i++) {
|
||||
const FieldDescriptor* field = optimized_order_[i];
|
||||
const FieldGenerator& generator = field_generators_.get(field);
|
||||
if (chunk.front()->is_repeated()) {
|
||||
for (int i = 0; i < chunk.size(); i++) {
|
||||
const FieldDescriptor* field = chunk[i];
|
||||
const FieldGenerator& generator = field_generators_.get(field);
|
||||
|
||||
if (!field->is_repeated()) {
|
||||
break;
|
||||
generator.GenerateMessageClearingCode(printer);
|
||||
}
|
||||
|
||||
generator.GenerateMessageClearingCode(printer);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Step 3: Greedily seek runs of fields that can be cleared by
|
||||
// memset-to-0.
|
||||
int last_chunk = -1;
|
||||
int last_chunk_start = -1;
|
||||
int last_chunk_end = -1;
|
||||
uint32 last_chunk_mask = 0;
|
||||
|
||||
// Step 3: Non-repeated fields that can be cleared by memset-to-0, then
|
||||
// non-repeated, non-zero initializable fields.
|
||||
int last_chunk = HasFieldPresence(descriptor_->file())
|
||||
? has_bit_indices_[chunk.front()->index()] / 8
|
||||
: 0;
|
||||
int last_chunk_start = 0;
|
||||
int memset_run_start = -1;
|
||||
int memset_run_end = -1;
|
||||
for (; i < optimized_order_.size(); i++) {
|
||||
const FieldDescriptor* field = optimized_order_[i];
|
||||
|
||||
if (!CanInitializeByZeroing(field)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// "index" defines where in the _has_bits_ the field appears.
|
||||
// "i" is our loop counter within optimized_order_.
|
||||
int index = HasFieldPresence(descriptor_->file()) ?
|
||||
has_bit_indices_[field->index()] : 0;
|
||||
int chunk = index / 8;
|
||||
|
||||
if (last_chunk == -1) {
|
||||
last_chunk = chunk;
|
||||
last_chunk_start = i;
|
||||
} else if (chunk != last_chunk) {
|
||||
// Emit the fields for this chunk so far.
|
||||
break;
|
||||
}
|
||||
|
||||
if (memset_run_start == -1) {
|
||||
memset_run_start = i;
|
||||
}
|
||||
|
||||
memset_run_end = i;
|
||||
last_chunk_end = i;
|
||||
last_chunk_mask |= static_cast<uint32>(1) << (index % 32);
|
||||
}
|
||||
|
||||
if (memset_run_start != memset_run_end && unconditional_budget >= 0) {
|
||||
// Flush the memset fields.
|
||||
goto flush;
|
||||
}
|
||||
|
||||
// Step 4: Non-repeated, non-zero initializable fields.
|
||||
for (; i < optimized_order_.size(); i++) {
|
||||
const FieldDescriptor* field = optimized_order_[i];
|
||||
if (field->is_repeated() || CanInitializeByZeroing(field)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// "index" defines where in the _has_bits_ the field appears.
|
||||
// "i" is our loop counter within optimized_order_.
|
||||
int index = HasFieldPresence(descriptor_->file()) ?
|
||||
has_bit_indices_[field->index()] : 0;
|
||||
int chunk = index / 8;
|
||||
|
||||
if (last_chunk == -1) {
|
||||
last_chunk = chunk;
|
||||
last_chunk_start = i;
|
||||
} else if (chunk != last_chunk) {
|
||||
// Emit the fields for this chunk so far.
|
||||
break;
|
||||
}
|
||||
|
||||
last_chunk_end = i;
|
||||
last_chunk_mask |= static_cast<uint32>(1) << (index % 32);
|
||||
}
|
||||
|
||||
flush:
|
||||
|
||||
if (last_chunk != -1) {
|
||||
GOOGLE_DCHECK_NE(-1, last_chunk_start);
|
||||
GOOGLE_DCHECK_NE(-1, last_chunk_end);
|
||||
GOOGLE_DCHECK_NE(0, last_chunk_mask);
|
||||
|
||||
const int count = popcnt(last_chunk_mask);
|
||||
const bool have_outer_if = HasFieldPresence(descriptor_->file()) &&
|
||||
(last_chunk_start != last_chunk_end) &&
|
||||
(memset_run_start != last_chunk_start ||
|
||||
memset_run_end != last_chunk_end ||
|
||||
unconditional_budget < 0);
|
||||
|
||||
if (have_outer_if) {
|
||||
// Check (up to) 8 has_bits at a time if we have more than one field in
|
||||
// this chunk. Due to field layout ordering, we may check
|
||||
// _has_bits_[last_chunk * 8 / 32] multiple times.
|
||||
GOOGLE_DCHECK_LE(2, count);
|
||||
GOOGLE_DCHECK_GE(8, count);
|
||||
|
||||
if (cached_has_bit_index != last_chunk / 4) {
|
||||
cached_has_bit_index = last_chunk / 4;
|
||||
printer->Print(
|
||||
"cached_has_bits = _has_bits_[$idx$];\n",
|
||||
"idx", SimpleItoa(cached_has_bit_index));
|
||||
for (int i = 0; i < chunk.size(); i++) {
|
||||
const FieldDescriptor* field = chunk[i];
|
||||
if (CanInitializeByZeroing(field)) {
|
||||
if (memset_run_start == -1) {
|
||||
memset_run_start = i;
|
||||
}
|
||||
printer->Print(
|
||||
"if (cached_has_bits & $mask$u) {\n",
|
||||
"mask", SimpleItoa(last_chunk_mask));
|
||||
printer->Indent();
|
||||
memset_run_end = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (memset_run_start != -1) {
|
||||
if (memset_run_start == memset_run_end) {
|
||||
// For clarity, do not memset a single field.
|
||||
const FieldGenerator& generator =
|
||||
field_generators_.get(optimized_order_[memset_run_start]);
|
||||
generator.GenerateMessageClearingCode(printer);
|
||||
} else {
|
||||
const string first_field_name =
|
||||
FieldName(optimized_order_[memset_run_start]);
|
||||
const string last_field_name =
|
||||
FieldName(optimized_order_[memset_run_end]);
|
||||
const bool have_outer_if =
|
||||
HasFieldPresence(descriptor_->file()) && chunk.size() > 1 &&
|
||||
(memset_run_end != chunk.size() - 1 || unconditional_budget < 0);
|
||||
|
||||
printer->Print(
|
||||
if (have_outer_if) {
|
||||
uint32 last_chunk_mask = GenChunkMask(chunk, has_bit_indices_);
|
||||
const int count = popcnt(last_chunk_mask);
|
||||
|
||||
// Check (up to) 8 has_bits at a time if we have more than one field in
|
||||
// this chunk. Due to field layout ordering, we may check
|
||||
// _has_bits_[last_chunk * 8 / 32] multiple times.
|
||||
GOOGLE_DCHECK_LE(2, count);
|
||||
GOOGLE_DCHECK_GE(8, count);
|
||||
|
||||
if (cached_has_bit_index != last_chunk / 4) {
|
||||
cached_has_bit_index = last_chunk / 4;
|
||||
printer->Print("cached_has_bits = _has_bits_[$idx$];\n", "idx",
|
||||
SimpleItoa(cached_has_bit_index));
|
||||
}
|
||||
printer->Print("if (cached_has_bits & $mask$u) {\n", "mask",
|
||||
SimpleItoa(last_chunk_mask));
|
||||
printer->Indent();
|
||||
}
|
||||
|
||||
if (memset_run_start != -1) {
|
||||
if (memset_run_start == memset_run_end) {
|
||||
// For clarity, do not memset a single field.
|
||||
const FieldGenerator& generator =
|
||||
field_generators_.get(chunk[memset_run_start]);
|
||||
generator.GenerateMessageClearingCode(printer);
|
||||
} else {
|
||||
const string first_field_name = FieldName(chunk[memset_run_start]);
|
||||
const string last_field_name = FieldName(chunk[memset_run_end]);
|
||||
|
||||
printer->Print(
|
||||
"::memset(&$first$_, 0, static_cast<size_t>(\n"
|
||||
" reinterpret_cast<char*>(&$last$_) -\n"
|
||||
" reinterpret_cast<char*>(&$first$_)) + sizeof($last$_));\n",
|
||||
"first", first_field_name,
|
||||
"last", last_field_name);
|
||||
}
|
||||
|
||||
// Advance last_chunk_start to skip over the fields we zeroed/memset.
|
||||
last_chunk_start = memset_run_end + 1;
|
||||
"first", first_field_name, "last", last_field_name);
|
||||
}
|
||||
|
||||
// Go back and emit clears for each of the fields we processed.
|
||||
for (int j = last_chunk_start; j <= last_chunk_end; j++) {
|
||||
const FieldDescriptor* field = optimized_order_[j];
|
||||
const string fieldname = FieldName(field);
|
||||
const FieldGenerator& generator = field_generators_.get(field);
|
||||
// Advance last_chunk_start to skip over the fields we zeroed/memset.
|
||||
last_chunk_start = memset_run_end + 1;
|
||||
}
|
||||
|
||||
// It's faster to just overwrite primitive types, but we should only
|
||||
// clear strings and messages if they were set.
|
||||
//
|
||||
// TODO(kenton): Let the CppFieldGenerator decide this somehow.
|
||||
bool should_check_bit =
|
||||
// Go back and emit clears for each of the fields we processed.
|
||||
for (int j = last_chunk_start; j < chunk.size(); j++) {
|
||||
const FieldDescriptor* field = chunk[j];
|
||||
const string fieldname = FieldName(field);
|
||||
const FieldGenerator& generator = field_generators_.get(field);
|
||||
|
||||
// It's faster to just overwrite primitive types, but we should only
|
||||
// clear strings and messages if they were set.
|
||||
//
|
||||
// TODO(kenton): Let the CppFieldGenerator decide this somehow.
|
||||
bool should_check_bit =
|
||||
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
|
||||
field->cpp_type() == FieldDescriptor::CPPTYPE_STRING;
|
||||
|
||||
bool have_enclosing_if = false;
|
||||
if (should_check_bit &&
|
||||
// If no field presence, then always clear strings/messages as well.
|
||||
HasFieldPresence(descriptor_->file())) {
|
||||
if (!field->options().weak() &&
|
||||
cached_has_bit_index != (has_bit_indices_[field->index()] / 32)) {
|
||||
cached_has_bit_index = (has_bit_indices_[field->index()] / 32);
|
||||
printer->Print("cached_has_bits = _has_bits_[$new_index$];\n",
|
||||
"new_index", SimpleItoa(cached_has_bit_index));
|
||||
}
|
||||
if (!MaybeGenerateOptionalFieldCondition(printer, field,
|
||||
cached_has_bit_index)) {
|
||||
printer->Print(
|
||||
"if (has_$name$()) {\n",
|
||||
"name", fieldname);
|
||||
}
|
||||
printer->Indent();
|
||||
have_enclosing_if = true;
|
||||
bool have_enclosing_if = false;
|
||||
if (should_check_bit &&
|
||||
// If no field presence, then always clear strings/messages as well.
|
||||
HasFieldPresence(descriptor_->file())) {
|
||||
if (!field->options().weak() &&
|
||||
cached_has_bit_index != (has_bit_indices_[field->index()] / 32)) {
|
||||
cached_has_bit_index = (has_bit_indices_[field->index()] / 32);
|
||||
printer->Print("cached_has_bits = _has_bits_[$new_index$];\n",
|
||||
"new_index", SimpleItoa(cached_has_bit_index));
|
||||
}
|
||||
|
||||
generator.GenerateMessageClearingCode(printer);
|
||||
|
||||
if (have_enclosing_if) {
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
if (!MaybeGenerateOptionalFieldCondition(printer, field,
|
||||
cached_has_bit_index)) {
|
||||
printer->Print("if (has_$name$()) {\n", "name", fieldname);
|
||||
}
|
||||
printer->Indent();
|
||||
have_enclosing_if = true;
|
||||
}
|
||||
|
||||
if (have_outer_if) {
|
||||
generator.GenerateMessageClearingCode(printer);
|
||||
|
||||
if (have_enclosing_if) {
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (have_outer_if) {
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Unions.
|
||||
@ -3349,7 +3427,6 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
|
||||
"}\n");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<const FieldDescriptor*> ordered_fields =
|
||||
SortFieldsByNumber(descriptor_);
|
||||
|
||||
@ -3379,9 +3456,22 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
for (int i = 0; i < ordered_fields.size(); i++) {
|
||||
const FieldDescriptor* field = ordered_fields[i];
|
||||
const FieldGenerator& field_generator = field_generators_.get(field);
|
||||
if (field_generator.MergeFromCodedStreamNeedsArena()) {
|
||||
printer->Print(
|
||||
" ::google::protobuf::Arena* arena = GetArenaNoVirtual();\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure\n"
|
||||
" ::google::protobuf::uint32 tag;\n");
|
||||
"#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto "
|
||||
"failure\n"
|
||||
" ::google::protobuf::uint32 tag;\n");
|
||||
|
||||
if (!UseUnknownFieldSet(descriptor_->file(), options_)) {
|
||||
printer->Print(
|
||||
@ -4141,28 +4231,30 @@ GenerateByteSize(io::Printer* printer) {
|
||||
}
|
||||
}
|
||||
|
||||
int last_i = -1;
|
||||
for (int i = 0; i < optimized_order_.size(); ) {
|
||||
// Detect infinite loops.
|
||||
GOOGLE_CHECK_NE(i, last_i);
|
||||
last_i = i;
|
||||
std::vector<std::vector<const FieldDescriptor*> > chunks = CollectFields(
|
||||
optimized_order_,
|
||||
MatchRepeatedAndHasByteAndRequired(
|
||||
&has_bit_indices_, HasFieldPresence(descriptor_->file())));
|
||||
|
||||
// Skip required fields.
|
||||
for (; i < optimized_order_.size() &&
|
||||
optimized_order_[i]->is_required(); i++) {
|
||||
}
|
||||
// Remove chunks with required fields.
|
||||
chunks.erase(std::remove_if(chunks.begin(), chunks.end(), IsRequired),
|
||||
chunks.end());
|
||||
|
||||
for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
|
||||
const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
|
||||
GOOGLE_CHECK(!chunk.empty());
|
||||
|
||||
// Handle repeated fields.
|
||||
for (; i < optimized_order_.size(); i++) {
|
||||
const FieldDescriptor* field = optimized_order_[i];
|
||||
if (!field->is_repeated()) {
|
||||
break;
|
||||
}
|
||||
if (chunk.front()->is_repeated()) {
|
||||
for (int i = 0; i < chunk.size(); i++) {
|
||||
const FieldDescriptor* field = chunk[i];
|
||||
|
||||
PrintFieldComment(printer, field);
|
||||
const FieldGenerator& generator = field_generators_.get(field);
|
||||
generator.GenerateByteSize(printer);
|
||||
printer->Print("\n");
|
||||
PrintFieldComment(printer, field);
|
||||
const FieldGenerator& generator = field_generators_.get(field);
|
||||
generator.GenerateByteSize(printer);
|
||||
printer->Print("\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle optional (non-repeated/oneof) fields.
|
||||
@ -4174,92 +4266,62 @@ GenerateByteSize(io::Printer* printer) {
|
||||
// descriptor_->field(8), descriptor_->field(9), ...
|
||||
// descriptor_->field(15),
|
||||
// etc.
|
||||
int last_chunk = -1;
|
||||
int last_chunk_start = -1;
|
||||
int last_chunk_end = -1;
|
||||
uint32 last_chunk_mask = 0;
|
||||
for (; i < optimized_order_.size(); i++) {
|
||||
const FieldDescriptor* field = optimized_order_[i];
|
||||
if (field->is_repeated() || field->is_required()) {
|
||||
break;
|
||||
}
|
||||
int last_chunk = HasFieldPresence(descriptor_->file())
|
||||
? has_bit_indices_[chunk.front()->index()] / 8
|
||||
: 0;
|
||||
GOOGLE_DCHECK_NE(-1, last_chunk);
|
||||
|
||||
// "index" defines where in the _has_bits_ the field appears.
|
||||
// "i" is our loop counter within optimized_order_.
|
||||
int index = HasFieldPresence(descriptor_->file()) ?
|
||||
has_bit_indices_[field->index()] : 0;
|
||||
int chunk = index / 8;
|
||||
const bool have_outer_if =
|
||||
HasFieldPresence(descriptor_->file()) && chunk.size() > 1;
|
||||
|
||||
if (last_chunk == -1) {
|
||||
last_chunk = chunk;
|
||||
last_chunk_start = i;
|
||||
} else if (chunk != last_chunk) {
|
||||
// Emit the fields for this chunk so far.
|
||||
break;
|
||||
}
|
||||
if (have_outer_if) {
|
||||
uint32 last_chunk_mask = GenChunkMask(chunk, has_bit_indices_);
|
||||
const int count = popcnt(last_chunk_mask);
|
||||
|
||||
last_chunk_end = i;
|
||||
last_chunk_mask |= static_cast<uint32>(1) << (index % 32);
|
||||
// Check (up to) 8 has_bits at a time if we have more than one field in
|
||||
// this chunk. Due to field layout ordering, we may check
|
||||
// _has_bits_[last_chunk * 8 / 32] multiple times.
|
||||
GOOGLE_DCHECK_LE(2, count);
|
||||
GOOGLE_DCHECK_GE(8, count);
|
||||
|
||||
printer->Print("if (_has_bits_[$index$ / 32] & $mask$u) {\n", "index",
|
||||
SimpleItoa(last_chunk * 8), "mask",
|
||||
SimpleItoa(last_chunk_mask));
|
||||
printer->Indent();
|
||||
}
|
||||
|
||||
if (last_chunk != -1) {
|
||||
GOOGLE_DCHECK_NE(-1, last_chunk_start);
|
||||
GOOGLE_DCHECK_NE(-1, last_chunk_end);
|
||||
GOOGLE_DCHECK_NE(0, last_chunk_mask);
|
||||
// Go back and emit checks for each of the fields we processed.
|
||||
for (int j = 0; j < chunk.size(); j++) {
|
||||
const FieldDescriptor* field = chunk[j];
|
||||
const FieldGenerator& generator = field_generators_.get(field);
|
||||
|
||||
const int count = popcnt(last_chunk_mask);
|
||||
const bool have_outer_if = HasFieldPresence(descriptor_->file()) &&
|
||||
(last_chunk_start != last_chunk_end);
|
||||
PrintFieldComment(printer, field);
|
||||
|
||||
if (have_outer_if) {
|
||||
// Check (up to) 8 has_bits at a time if we have more than one field in
|
||||
// this chunk. Due to field layout ordering, we may check
|
||||
// _has_bits_[last_chunk * 8 / 32] multiple times.
|
||||
GOOGLE_DCHECK_LE(2, count);
|
||||
GOOGLE_DCHECK_GE(8, count);
|
||||
|
||||
printer->Print(
|
||||
"if (_has_bits_[$index$ / 32] & $mask$u) {\n",
|
||||
"index", SimpleItoa(last_chunk * 8),
|
||||
"mask", SimpleItoa(last_chunk_mask));
|
||||
bool have_enclosing_if = false;
|
||||
if (HasFieldPresence(descriptor_->file())) {
|
||||
printer->Print("if (has_$name$()) {\n", "name", FieldName(field));
|
||||
printer->Indent();
|
||||
have_enclosing_if = true;
|
||||
} else {
|
||||
// Without field presence: field is serialized only if it has a
|
||||
// non-default value.
|
||||
have_enclosing_if =
|
||||
EmitFieldNonDefaultCondition(printer, "this->", field);
|
||||
}
|
||||
|
||||
// Go back and emit checks for each of the fields we processed.
|
||||
for (int j = last_chunk_start; j <= last_chunk_end; j++) {
|
||||
const FieldDescriptor* field = optimized_order_[j];
|
||||
const FieldGenerator& generator = field_generators_.get(field);
|
||||
generator.GenerateByteSize(printer);
|
||||
|
||||
PrintFieldComment(printer, field);
|
||||
|
||||
bool have_enclosing_if = false;
|
||||
if (HasFieldPresence(descriptor_->file())) {
|
||||
printer->Print(
|
||||
"if (has_$name$()) {\n",
|
||||
"name", FieldName(field));
|
||||
printer->Indent();
|
||||
have_enclosing_if = true;
|
||||
} else {
|
||||
// Without field presence: field is serialized only if it has a
|
||||
// non-default value.
|
||||
have_enclosing_if = EmitFieldNonDefaultCondition(
|
||||
printer, "this->", field);
|
||||
}
|
||||
|
||||
generator.GenerateByteSize(printer);
|
||||
|
||||
if (have_enclosing_if) {
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
if (have_enclosing_if) {
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n"
|
||||
"\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (have_outer_if) {
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
if (have_outer_if) {
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -4359,10 +4421,17 @@ GenerateIsInitialized(io::Printer* printer) {
|
||||
!ShouldIgnoreRequiredFieldCheck(field, options_) &&
|
||||
scc_analyzer_->HasRequiredFields(field->message_type())) {
|
||||
if (field->is_repeated()) {
|
||||
printer->Print(
|
||||
"if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))"
|
||||
" return false;\n",
|
||||
"name", FieldName(field));
|
||||
if (IsImplicitWeakField(field, options_)) {
|
||||
printer->Print(
|
||||
"if (!::google::protobuf::internal::AllAreInitializedWeak(this->$name$_))"
|
||||
" return false;\n",
|
||||
"name", FieldName(field));
|
||||
} else {
|
||||
printer->Print(
|
||||
"if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))"
|
||||
" return false;\n",
|
||||
"name", FieldName(field));
|
||||
}
|
||||
} else if (field->options().weak()) {
|
||||
continue;
|
||||
} else {
|
||||
|
@ -106,6 +106,9 @@ class MessageGenerator {
|
||||
// Generate all non-inline methods for this class.
|
||||
void GenerateClassMethods(io::Printer* printer);
|
||||
|
||||
// Generate source file code that should go outside any namespace.
|
||||
void GenerateSourceInProto2Namespace(io::Printer* printer);
|
||||
|
||||
private:
|
||||
// Generate declarations and definitions of accessors for fields.
|
||||
void GenerateDependentBaseClassDefinition(io::Printer* printer);
|
||||
|
@ -80,11 +80,9 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
|
||||
(*variables)["type_default_instance"] =
|
||||
DefaultInstanceName(descriptor->message_type());
|
||||
(*variables)["type_reference_function"] =
|
||||
ReferenceFunctionName(descriptor->message_type());
|
||||
if (descriptor->options().weak() || !descriptor->containing_oneof()) {
|
||||
(*variables)["non_null_ptr_to_name"] =
|
||||
StrCat("this->", (*variables)["name"], "_");
|
||||
}
|
||||
IsImplicitWeakField(descriptor, options)
|
||||
? (" " + ReferenceFunctionName(descriptor->message_type()) + "();\n")
|
||||
: "";
|
||||
(*variables)["stream_writer"] =
|
||||
(*variables)["declared_type"] +
|
||||
(HasFastArraySerialization(descriptor->message_type()->file(), options)
|
||||
@ -96,14 +94,8 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
|
||||
SafeFunctionName(descriptor->containing_type(),
|
||||
descriptor, "release_");
|
||||
(*variables)["full_name"] = descriptor->full_name();
|
||||
if (options.proto_h && IsFieldDependent(descriptor)) {
|
||||
(*variables)["dependent_type"] = "T::" + DependentTypeName(descriptor);
|
||||
(*variables)["dependent_typename"] =
|
||||
"typename T::" + DependentTypeName(descriptor);
|
||||
} else {
|
||||
(*variables)["dependent_type"] = FieldMessageTypeName(descriptor);
|
||||
(*variables)["dependent_typename"] = FieldMessageTypeName(descriptor);
|
||||
}
|
||||
(*variables)["create_func"] =
|
||||
MessageCreateFunction(descriptor->message_type());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -114,7 +106,6 @@ MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
|
||||
const Options& options)
|
||||
: FieldGenerator(options),
|
||||
descriptor_(descriptor),
|
||||
dependent_field_(options.proto_h && IsFieldDependent(descriptor)),
|
||||
implicit_weak_field_(IsImplicitWeakField(descriptor, options)) {
|
||||
SetMessageVariables(descriptor, &variables_, options);
|
||||
}
|
||||
@ -130,24 +121,8 @@ GeneratePrivateMembers(io::Printer* printer) const {
|
||||
}
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateDependentAccessorDeclarations(io::Printer* printer) const {
|
||||
if (!dependent_field_) {
|
||||
return;
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$$type$* ${$mutable_$name$$}$();\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
if (SupportsArenas(descriptor_) && !implicit_weak_field_) {
|
||||
printer->Print(variables_,
|
||||
"private:\n"
|
||||
"void _slow_mutable_$name$();\n"
|
||||
"public:\n");
|
||||
}
|
||||
if (implicit_weak_field_) {
|
||||
// These private accessors are used by MergeFrom and
|
||||
// MergePartialFromCodedStream, and their purpose is to provide access to
|
||||
@ -163,11 +138,9 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Annotate("name", descriptor_);
|
||||
printer->Print(variables_, "$deprecated_attr$$type$* $release_name$();\n");
|
||||
printer->Annotate("release_name", descriptor_);
|
||||
if (!dependent_field_) {
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$$type$* ${$mutable_$name$$}$();\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$$type$* ${$mutable_$name$$}$();\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$void ${$set_allocated_$name$$}$"
|
||||
"($type$* $name$);\n");
|
||||
@ -216,22 +189,9 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
|
||||
" &$type_default_instance$)->New(GetArenaNoVirtual());\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" return $name$_;\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"void $classname$::_slow_mutable_$name$() {\n");
|
||||
if (SupportsArenas(descriptor_->message_type())) {
|
||||
printer->Print(variables_,
|
||||
" $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
|
||||
" GetArenaNoVirtual());\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
|
||||
" GetArenaNoVirtual());\n");
|
||||
}
|
||||
" return $name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"}\n");
|
||||
|
||||
printer->Print(variables_,
|
||||
"void $classname$::unsafe_arena_set_allocated_$name$(\n"
|
||||
@ -267,119 +227,39 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
|
||||
}
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
if (!dependent_field_) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<string, string> variables(variables_);
|
||||
// For the CRTP base class, all mutation methods are dependent, and so
|
||||
// they must be in the header.
|
||||
variables["dependent_classname"] =
|
||||
DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
|
||||
variables["this_message"] = DependentBaseDownCast();
|
||||
variables["casted_reference"] =
|
||||
ReinterpretCast(variables["dependent_typename"] + "*&",
|
||||
variables["this_message"] + variables["name"] + "_",
|
||||
implicit_weak_field_);
|
||||
if (!variables["set_hasbit"].empty()) {
|
||||
variables["set_hasbit"] =
|
||||
variables["this_message"] + variables["set_hasbit"];
|
||||
}
|
||||
if (!variables["clear_hasbit"].empty()) {
|
||||
variables["clear_hasbit"] =
|
||||
variables["this_message"] + variables["clear_hasbit"];
|
||||
}
|
||||
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables,
|
||||
"template <class T>\n"
|
||||
"inline $type$* $dependent_classname$::mutable_$name$() {\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables, " $type_reference_function$();\n");
|
||||
}
|
||||
printer->Print(variables,
|
||||
" $set_hasbit$\n"
|
||||
" $dependent_typename$*& $name$_ = $casted_reference$;\n"
|
||||
" if ($name$_ == NULL) {\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables,
|
||||
" $name$_ = reinterpret_cast<$dependent_typename$*>(\n"
|
||||
" reinterpret_cast<const google::protobuf::MessageLite*>(\n"
|
||||
" &$type_default_instance$)->New(\n"
|
||||
" $this_message$GetArenaNoVirtual()));\n");
|
||||
} else {
|
||||
printer->Print(variables,
|
||||
" $this_message$_slow_mutable_$name$();\n");
|
||||
}
|
||||
printer->Print(variables,
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $name$_;\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(variables,
|
||||
"template <class T>\n"
|
||||
"inline $type$* $dependent_classname$::mutable_$name$() {\n"
|
||||
" $set_hasbit$\n"
|
||||
" $dependent_typename$*& $name$_ = $casted_reference$;\n"
|
||||
" if ($name$_ == NULL) {\n"
|
||||
" $name$_ = new $dependent_typename$;\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
std::map<string, string> variables(variables_);
|
||||
variables["const_member"] = ReinterpretCast(
|
||||
"const " + variables["type"] + "*", variables["name"] + "_",
|
||||
implicit_weak_field_);
|
||||
printer->Print(variables,
|
||||
"inline const $type$& $classname$::$name$() const {\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables, " $type_reference_function$();\n");
|
||||
}
|
||||
printer->Print(variables,
|
||||
" const $type$* p = $const_member$;\n"
|
||||
printer->Print(variables_,
|
||||
"inline const $type$& $classname$::$name$() const {\n"
|
||||
"$type_reference_function$"
|
||||
" const $type$* p = $casted_member$;\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return p != NULL ? *p : *reinterpret_cast<const $type$*>(\n"
|
||||
" &$type_default_instance$);\n"
|
||||
"}\n");
|
||||
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::$release_name$() {\n"
|
||||
" // @@protoc_insertion_point(field_release:$full_name$)\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables, " $type_reference_function$();\n");
|
||||
}
|
||||
printer->Print(variables,
|
||||
" // @@protoc_insertion_point(field_release:$full_name$)\n"
|
||||
"$type_reference_function$"
|
||||
" $clear_hasbit$\n"
|
||||
" $type$* temp = $casted_member$;\n");
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
" if (GetArenaNoVirtual() != NULL) {\n"
|
||||
" temp = ::google::protobuf::internal::DuplicateIfNonNull(temp, NULL);\n"
|
||||
" }\n");
|
||||
}
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
" $name$_ = NULL;\n"
|
||||
" return temp;\n"
|
||||
"}\n");
|
||||
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
|
||||
" // @@protoc_insertion_point("
|
||||
"field_unsafe_arena_release:$full_name$)\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables, " $type_reference_function$();\n");
|
||||
}
|
||||
printer->Print(variables,
|
||||
" // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
|
||||
"$type_reference_function$"
|
||||
" $clear_hasbit$\n"
|
||||
" $type$* temp = $casted_member$;\n"
|
||||
" $name$_ = NULL;\n"
|
||||
@ -387,71 +267,58 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
"}\n");
|
||||
}
|
||||
|
||||
if (!dependent_field_) {
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables,
|
||||
"inline $type$* $classname$::mutable_$name$() {\n"
|
||||
" $set_hasbit$\n"
|
||||
" if ($name$_ == NULL) {\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables,
|
||||
" _internal_mutable_$name$();\n");
|
||||
} else {
|
||||
printer->Print(variables,
|
||||
" _slow_mutable_$name$();\n");
|
||||
}
|
||||
printer->Print(variables,
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $casted_member$;\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(variables,
|
||||
"inline $type$* $classname$::mutable_$name$() {\n"
|
||||
" $set_hasbit$\n"
|
||||
" if ($name$_ == NULL) {\n"
|
||||
" $name$_ = new $type$;\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $casted_member$;\n"
|
||||
"}\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::mutable_$name$() {\n"
|
||||
"$type_reference_function$"
|
||||
" $set_hasbit$\n"
|
||||
" if ($name$_ == NULL) {\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables_,
|
||||
" _internal_mutable_$name$();\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" $name$_ = ::google::protobuf::Arena::$create_func$< $type$ >(\n"
|
||||
" GetArenaNoVirtual());\n");
|
||||
}
|
||||
|
||||
printer->Print(variables_,
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $casted_member$;\n"
|
||||
"}\n");
|
||||
|
||||
// We handle the most common case inline, and delegate less common cases to
|
||||
// the slow fallback function.
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
"inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
|
||||
" ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n");
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
" if (message_arena == NULL) {\n");
|
||||
if (IsCrossFileMessage(descriptor_)) {
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
" delete reinterpret_cast< ::google::protobuf::MessageLite*>($name$_);\n");
|
||||
} else {
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
" delete $name$_;\n");
|
||||
}
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
" }\n"
|
||||
" if ($name$) {\n");
|
||||
if (SupportsArenas(descriptor_->message_type()) &&
|
||||
IsCrossFileMessage(descriptor_)) {
|
||||
// We have to read the arena through the virtual method, because the type
|
||||
// isn't defined in this file.
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::Arena* submessage_arena =\n"
|
||||
" reinterpret_cast< ::google::protobuf::MessageLite*>($name$)->GetArena();\n");
|
||||
} else if (!SupportsArenas(descriptor_->message_type())) {
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::Arena* submessage_arena = NULL;\n");
|
||||
} else {
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::Arena* submessage_arena =\n"
|
||||
" ::google::protobuf::Arena::GetArena($name$);\n");
|
||||
}
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
" if (message_arena != submessage_arena) {\n"
|
||||
" $name$ = ::google::protobuf::internal::GetOwnedMessage(\n"
|
||||
" message_arena, $name$, submessage_arena);\n"
|
||||
@ -461,13 +328,13 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" $clear_hasbit$\n"
|
||||
" }\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
" $name$_ = reinterpret_cast<MessageLite*>($name$);\n");
|
||||
} else {
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
" $name$_ = $name$;\n");
|
||||
}
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
@ -540,34 +407,12 @@ GenerateConstructorCode(io::Printer* printer) const {
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateCopyConstructorCode(io::Printer* printer) const {
|
||||
// For non-Arena enabled messages, everything always goes on the heap.
|
||||
//
|
||||
// For Arena enabled messages, the logic is a bit more convoluted.
|
||||
//
|
||||
// In the copy constructor, we call InternalMetadataWithArena::MergeFrom,
|
||||
// which does *not* copy the Arena pointer. In the generated MergeFrom
|
||||
// (see MessageFieldGenerator::GenerateMergingCode), we:
|
||||
// -> copy the has bits (but this is done in bulk by a memcpy in the copy
|
||||
// constructor)
|
||||
// -> check whether the destination field pointer is NULL (it will be, since
|
||||
// we're initializing it and would have called SharedCtor) and if so:
|
||||
// -> call _slow_mutable_$name$(), which calls either
|
||||
// ::google::protobuf::Arena::CreateMessage<>(GetArenaNoVirtual()), or
|
||||
// ::google::protobuf::Arena::Create<>(GetArenaNoVirtual())
|
||||
//
|
||||
// At this point, GetArenaNoVirtual returns NULL since the Arena pointer
|
||||
// wasn't copied, so both of these methods allocate the submessage on the
|
||||
// heap.
|
||||
|
||||
string new_expression = (implicit_weak_field_ ? "from.$name$_->New()"
|
||||
: "new $type$(*from.$name$_)");
|
||||
string output =
|
||||
"if (from.has_$name$()) {\n"
|
||||
" $name$_ = " + new_expression + ";\n"
|
||||
"} else {\n"
|
||||
" $name$_ = NULL;\n"
|
||||
"}\n";
|
||||
printer->Print(variables_, output.c_str());
|
||||
printer->Print(variables_,
|
||||
"if (from.has_$name$()) {\n"
|
||||
" $name$_ = new $type$(*from.$name$_);\n"
|
||||
"} else {\n"
|
||||
" $name$_ = NULL;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
@ -591,7 +436,7 @@ void MessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
|
||||
" $number$, *$non_null_ptr_to_name$, output);\n");
|
||||
" $number$, *$field_member$, output);\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
@ -599,7 +444,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" InternalWrite$declared_type$ToArray(\n"
|
||||
" $number$, *$non_null_ptr_to_name$, deterministic, target);\n");
|
||||
" $number$, *$field_member$, deterministic, target);\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
@ -607,7 +452,7 @@ GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
|
||||
" *$non_null_ptr_to_name$);\n");
|
||||
" *$field_member$);\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
@ -650,57 +495,27 @@ void MessageOneofFieldGenerator::GenerateNonInlineAccessorDefinitions(
|
||||
" message_arena, $name$, submessage_arena);\n"
|
||||
" }\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_ = $name$;\n"
|
||||
" $field_member$ = $name$;\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MessageOneofFieldGenerator::
|
||||
GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
// For the CRTP base class, all mutation methods are dependent, and so
|
||||
// they must be in the header.
|
||||
if (!dependent_base_) {
|
||||
return;
|
||||
}
|
||||
std::map<string, string> variables(variables_);
|
||||
variables["dependent_classname"] =
|
||||
DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
|
||||
variables["this_message"] = "reinterpret_cast<T*>(this)->";
|
||||
// Const message access is needed for the dependent getter.
|
||||
variables["this_const_message"] = "reinterpret_cast<const T*>(this)->";
|
||||
variables["tmpl"] = "template <class T>\n";
|
||||
variables["field_member"] = variables["this_message"] +
|
||||
variables["oneof_prefix"] + variables["name"] +
|
||||
"_";
|
||||
InternalGenerateInlineAccessorDefinitions(variables, printer);
|
||||
}
|
||||
|
||||
void MessageOneofFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
|
||||
std::map<string, string> variables(variables_);
|
||||
variables["dependent_classname"] = variables["classname"];
|
||||
variables["this_message"] = "";
|
||||
variables["this_const_message"] = "";
|
||||
variables["tmpl"] = "";
|
||||
variables["field_member"] =
|
||||
variables["oneof_prefix"] + variables["name"] + "_";
|
||||
variables["dependent_type"] = variables["type"];
|
||||
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::$release_name$() {\n"
|
||||
" // @@protoc_insertion_point(field_release:$full_name$)\n"
|
||||
" if ($this_message$has_$name$()) {\n"
|
||||
" $this_message$clear_has_$oneof_name$();\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" clear_has_$oneof_name$();\n"
|
||||
" $type$* temp = $field_member$;\n");
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables,
|
||||
" if ($this_message$GetArenaNoVirtual() != NULL) {\n"
|
||||
printer->Print(variables_,
|
||||
" if (GetArenaNoVirtual() != NULL) {\n"
|
||||
" temp = ::google::protobuf::internal::DuplicateIfNonNull(temp, NULL);\n"
|
||||
" }\n");
|
||||
}
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
" $field_member$ = NULL;\n"
|
||||
" return temp;\n"
|
||||
" } else {\n"
|
||||
@ -708,23 +523,23 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" }\n"
|
||||
"}\n");
|
||||
|
||||
printer->Print(variables,
|
||||
printer->Print(variables_,
|
||||
"inline const $type$& $classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return $this_const_message$has_$name$()\n"
|
||||
" ? *$this_const_message$$oneof_prefix$$name$_\n"
|
||||
" return has_$name$()\n"
|
||||
" ? *$field_member$\n"
|
||||
" : *reinterpret_cast< $type$*>(&$type_default_instance$);\n"
|
||||
"}\n");
|
||||
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables,
|
||||
"inline $type$* $dependent_classname$::unsafe_arena_release_$name$() {\n"
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_unsafe_arena_release"
|
||||
":$full_name$)\n"
|
||||
" if ($this_message$has_$name$()) {\n"
|
||||
" $this_message$clear_has_$oneof_name$();\n"
|
||||
" $type$* temp = $this_message$$oneof_prefix$$name$_;\n"
|
||||
" $this_message$$oneof_prefix$$name$_ = NULL;\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" clear_has_$oneof_name$();\n"
|
||||
" $type$* temp = $field_member$;\n"
|
||||
" $field_member$ = NULL;\n"
|
||||
" return temp;\n"
|
||||
" } else {\n"
|
||||
" return NULL;\n"
|
||||
@ -738,58 +553,24 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" clear_$oneof_name$();\n"
|
||||
" if ($name$) {\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_ = $name$;\n"
|
||||
" $field_member$ = $name$;\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
|
||||
"$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
if (dependent_base_) {
|
||||
return;
|
||||
}
|
||||
|
||||
InternalGenerateInlineAccessorDefinitions(variables, printer);
|
||||
}
|
||||
|
||||
void MessageOneofFieldGenerator::InternalGenerateInlineAccessorDefinitions(
|
||||
const std::map<string, string>& variables, io::Printer* printer) const {
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables,
|
||||
"$tmpl$"
|
||||
"inline $type$* $dependent_classname$::mutable_$name$() {\n"
|
||||
" if (!$this_message$has_$name$()) {\n"
|
||||
" $this_message$clear_$oneof_name$();\n"
|
||||
" $this_message$set_has_$name$();\n");
|
||||
if (SupportsArenas(descriptor_->message_type())) {
|
||||
printer->Print(variables,
|
||||
" $field_member$ = \n"
|
||||
" ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n"
|
||||
" $this_message$GetArenaNoVirtual());\n");
|
||||
} else {
|
||||
printer->Print(variables,
|
||||
" $this_message$$oneof_prefix$$name$_ = \n"
|
||||
" ::google::protobuf::Arena::Create< $dependent_typename$ >(\n"
|
||||
" $this_message$GetArenaNoVirtual());\n");
|
||||
}
|
||||
printer->Print(variables,
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $field_member$;\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(variables,
|
||||
"$tmpl$"
|
||||
"inline $type$* $dependent_classname$::mutable_$name$() {\n"
|
||||
" if (!$this_message$has_$name$()) {\n"
|
||||
" $this_message$clear_$oneof_name$();\n"
|
||||
" $this_message$set_has_$name$();\n"
|
||||
" $field_member$ = new $dependent_typename$;\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $field_member$;\n"
|
||||
"}\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::mutable_$name$() {\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $field_member$ = ::google::protobuf::Arena::$create_func$< $type$ >(\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $field_member$;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void MessageOneofFieldGenerator::
|
||||
@ -797,11 +578,11 @@ GenerateClearingCode(io::Printer* printer) const {
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
"if (GetArenaNoVirtual() == NULL) {\n"
|
||||
" delete $oneof_prefix$$name$_;\n"
|
||||
" delete $field_member$;\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"delete $oneof_prefix$$name$_;\n");
|
||||
"delete $field_member$;\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -834,7 +615,7 @@ RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
|
||||
: FieldGenerator(options),
|
||||
descriptor_(descriptor),
|
||||
dependent_field_(options.proto_h && IsFieldDependent(descriptor)),
|
||||
dependent_getter_(dependent_field_ && options.safe_boundary_check) {
|
||||
implicit_weak_field_(IsImplicitWeakField(descriptor, options)) {
|
||||
SetMessageVariables(descriptor, &variables_, options);
|
||||
}
|
||||
|
||||
@ -848,30 +629,12 @@ GeneratePrivateMembers(io::Printer* printer) const {
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
InternalGenerateTypeDependentAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$$type$* ${$mutable_$name$$}$(int index);\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
printer->Print(variables_, "$deprecated_attr$$type$* ${$add_$name$$}$();\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
if (dependent_getter_) {
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
|
||||
" $name$() const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n"
|
||||
" ${$mutable_$name$$}$();\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateDependentAccessorDeclarations(io::Printer* printer) const {
|
||||
if (dependent_getter_) {
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$const $type$& $name$(int index) const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
}
|
||||
if (dependent_field_) {
|
||||
InternalGenerateTypeDependentAccessorDeclarations(printer);
|
||||
}
|
||||
@ -879,20 +642,24 @@ GenerateDependentAccessorDeclarations(io::Printer* printer) const {
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
if (!dependent_getter_) {
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$const $type$& $name$(int index) const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$$type$* ${$mutable_$name$$}$(int index);\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n"
|
||||
" ${$mutable_$name$$}$();\n");
|
||||
printer->Annotate("{", "}", descriptor_);
|
||||
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$const $type$& $name$(int index) const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
if (!dependent_field_) {
|
||||
InternalGenerateTypeDependentAccessorDeclarations(printer);
|
||||
}
|
||||
if (!dependent_getter_) {
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
|
||||
" $name$() const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
|
||||
" $name$() const;\n");
|
||||
printer->Annotate("name", descriptor_);
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
@ -908,103 +675,97 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
variables["this_message"] = DependentBaseDownCast();
|
||||
variables["this_const_message"] = DependentBaseConstDownCast();
|
||||
|
||||
if (dependent_getter_) {
|
||||
printer->Print(variables,
|
||||
"template <class T>\n"
|
||||
"inline const $type$& $dependent_classname$::$name$(int index) const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return $this_const_message$$name$_.$cppget$(index);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
// Generate per-element accessors:
|
||||
printer->Print(variables,
|
||||
"template <class T>\n"
|
||||
"inline $type$* $dependent_classname$::mutable_$name$(int index) {\n"
|
||||
// TODO(dlj): move insertion points
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $this_message$$name$_.Mutable(index);\n"
|
||||
"}\n"
|
||||
"template <class T>\n"
|
||||
"inline $type$* $dependent_classname$::add_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_add:$full_name$)\n"
|
||||
"$type_reference_function$"
|
||||
" return $this_message$$name$_.Add();\n"
|
||||
"}\n");
|
||||
|
||||
if (dependent_getter_) {
|
||||
printer->Print(variables,
|
||||
"template <class T>\n"
|
||||
"inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
|
||||
"$dependent_classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_list:$full_name$)\n"
|
||||
" return $this_const_message$$name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
// Generate mutable access to the entire list:
|
||||
printer->Print(variables,
|
||||
"template <class T>\n"
|
||||
"inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
|
||||
"$dependent_classname$::mutable_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
|
||||
" return &$this_message$$name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
if (!dependent_getter_) {
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::mutable_$name$(int index) {\n"
|
||||
// TODO(dlj): move insertion points
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
"$type_reference_function$"
|
||||
" return $name$_.Mutable(index);\n"
|
||||
"}\n"
|
||||
"inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
|
||||
"$classname$::mutable_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
|
||||
"$type_reference_function$"
|
||||
" return &$name$_;\n"
|
||||
"}\n");
|
||||
|
||||
if (options_.safe_boundary_check) {
|
||||
printer->Print(variables_,
|
||||
"inline const $type$& $classname$::$name$(int index) const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return $name$_.$cppget$(index);\n"
|
||||
"$type_reference_function$"
|
||||
" return $name$_.InternalCheckedGet(index,\n"
|
||||
" *reinterpret_cast<const $type$*>(&$type_default_instance$));\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"inline const $type$& $classname$::$name$(int index) const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
"$type_reference_function$"
|
||||
" return $name$_.Get(index);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
if (!dependent_field_) {
|
||||
printer->Print(variables_,
|
||||
"inline $type$* $classname$::mutable_$name$(int index) {\n"
|
||||
// TODO(dlj): move insertion points
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $name$_.Mutable(index);\n"
|
||||
"}\n"
|
||||
"inline $type$* $classname$::add_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_add:$full_name$)\n"
|
||||
"$type_reference_function$"
|
||||
" return $name$_.Add();\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
if (!dependent_field_) {
|
||||
printer->Print(variables_,
|
||||
"inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
|
||||
"$classname$::mutable_$name$() {\n"
|
||||
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
|
||||
" return &$name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
if (!dependent_getter_) {
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
|
||||
"$classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_list:$full_name$)\n"
|
||||
" return $name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
|
||||
"$classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_list:$full_name$)\n"
|
||||
"$type_reference_function$"
|
||||
" return $name$_;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.Clear();\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"CastToBase(&$name$_)->Clear<"
|
||||
"::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>();\n");
|
||||
} else {
|
||||
printer->Print(variables_, "$name$_.Clear();\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateMergingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
"CastToBase(&$name$_)->MergeFrom<"
|
||||
"::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>(CastToBase("
|
||||
"from.$name$_));\n");
|
||||
} else {
|
||||
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n");
|
||||
printer->Print(
|
||||
variables_,
|
||||
"CastToBase(&$name$_)->InternalSwap(CastToBase(&other->$name$_));\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
@ -1015,9 +776,18 @@ GenerateConstructorCode(io::Printer* printer) const {
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::"
|
||||
"ReadMessage(input, add_$name$()));\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::"
|
||||
"ReadMessage(input, CastToBase(&$name$_)->AddWeak(\n"
|
||||
" reinterpret_cast<const ::google::protobuf::MessageLite*>(\n"
|
||||
" &$type_default_instance$))));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::"
|
||||
"ReadMessage(\n"
|
||||
" input, add_$name$()));\n");
|
||||
}
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::"
|
||||
@ -1031,7 +801,19 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
"for (unsigned int i = 0,\n"
|
||||
" n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) {\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
|
||||
" $number$, this->$name$(static_cast<int>(i)), output);\n"
|
||||
" $number$,\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
" CastToBase($name$_).Get<"
|
||||
"::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>("
|
||||
"static_cast<int>(i)),\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" this->$name$(static_cast<int>(i)),\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" output);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
@ -1056,9 +838,18 @@ GenerateByteSize(io::Printer* printer) const {
|
||||
"total_size += $tag_size$UL * count;\n"
|
||||
"for (unsigned int i = 0; i < count; i++) {\n"
|
||||
" total_size +=\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
|
||||
" this->$name$(static_cast<int>(i)));\n"
|
||||
"}\n");
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n");
|
||||
if (implicit_weak_field_) {
|
||||
printer->Print(
|
||||
variables_,
|
||||
" CastToBase($name$_).Get<"
|
||||
"::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>("
|
||||
"static_cast<int>(i)));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" this->$name$(static_cast<int>(i)));\n");
|
||||
}
|
||||
printer->Print(variables_, "}\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
@ -54,9 +54,7 @@ class MessageFieldGenerator : public FieldGenerator {
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GeneratePrivateMembers(io::Printer* printer) const;
|
||||
void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateAccessorDeclarations(io::Printer* printer) const;
|
||||
void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
@ -73,7 +71,6 @@ class MessageFieldGenerator : public FieldGenerator {
|
||||
|
||||
protected:
|
||||
const FieldDescriptor* descriptor_;
|
||||
const bool dependent_field_;
|
||||
const bool implicit_weak_field_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
@ -88,7 +85,6 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator {
|
||||
~MessageOneofFieldGenerator();
|
||||
|
||||
// implements FieldGenerator ---------------------------------------
|
||||
void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
|
||||
void GenerateClearingCode(io::Printer* printer) const;
|
||||
@ -101,9 +97,6 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator {
|
||||
void GenerateConstructorCode(io::Printer* printer) const;
|
||||
|
||||
private:
|
||||
void InternalGenerateInlineAccessorDefinitions(
|
||||
const std::map<string, string>& variables, io::Printer* printer) const;
|
||||
|
||||
const bool dependent_base_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
|
||||
};
|
||||
@ -136,7 +129,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
|
||||
|
||||
const FieldDescriptor* descriptor_;
|
||||
const bool dependent_field_;
|
||||
const bool dependent_getter_;
|
||||
const bool implicit_weak_field_;
|
||||
std::map<string, string> variables_;
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
|
||||
|
@ -54,6 +54,7 @@ struct Options {
|
||||
table_driven_parsing(false),
|
||||
table_driven_serialization(false),
|
||||
lite_implicit_weak_fields(false),
|
||||
num_cc_files(0),
|
||||
access_info_map(NULL) {}
|
||||
|
||||
string dllexport_decl;
|
||||
@ -65,6 +66,7 @@ struct Options {
|
||||
bool table_driven_parsing;
|
||||
bool table_driven_serialization;
|
||||
bool lite_implicit_weak_fields;
|
||||
int num_cc_files;
|
||||
string annotation_pragma_name;
|
||||
string annotation_guard_name;
|
||||
const AccessInfoMap* access_info_map;
|
||||
|
@ -215,7 +215,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
"inline $type$ $classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" return $oneof_prefix$$name$_;\n"
|
||||
" return $field_member$;\n"
|
||||
" }\n"
|
||||
" return $default$;\n"
|
||||
"}\n"
|
||||
@ -224,14 +224,14 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_ = value;\n"
|
||||
" $field_member$ = value;\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void PrimitiveOneofFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n");
|
||||
printer->Print(variables_, "$field_member$ = $default$;\n");
|
||||
}
|
||||
|
||||
void PrimitiveOneofFieldGenerator::
|
||||
@ -251,7 +251,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
"clear_$oneof_name$();\n"
|
||||
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
|
||||
" $type$, $wire_format_field_type$>(\n"
|
||||
" input, &$oneof_prefix$$name$_)));\n"
|
||||
" input, &$field_member$)));\n"
|
||||
"set_has_$name$();\n");
|
||||
}
|
||||
|
||||
|
@ -402,11 +402,11 @@ GenerateMessageClearingCode(io::Printer* printer) const {
|
||||
// When Arenas are disabled and field presence has been checked, we can
|
||||
// safely treat the ArenaStringPtr as a string*.
|
||||
if (descriptor_->default_value_string().empty()) {
|
||||
printer->Print(variables_,
|
||||
"(*$name$_.UnsafeRawStringPointer())->clear();\n");
|
||||
printer->Print(variables_, "$name$_.UnsafeMutablePointer()->clear();\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"(*$name$_.UnsafeRawStringPointer())->assign(*$default_variable$);\n");
|
||||
printer->Print(
|
||||
variables_,
|
||||
"$name$_.UnsafeMutablePointer()->assign(*$default_variable$);\n");
|
||||
}
|
||||
} else {
|
||||
if (descriptor_->default_value_string().empty()) {
|
||||
@ -504,6 +504,11 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
}
|
||||
}
|
||||
|
||||
bool StringFieldGenerator::
|
||||
MergeFromCodedStreamNeedsArena() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
@ -559,7 +564,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
"inline const ::std::string& $classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" return $oneof_prefix$$name$_.Get();\n"
|
||||
" return $field_member$.Get();\n"
|
||||
" }\n"
|
||||
" return *$default_variable$;\n"
|
||||
"}\n"
|
||||
@ -567,9 +572,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" $field_member$.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.Set$lite$($default_variable$, value,\n"
|
||||
" $field_member$.Set$lite$($default_variable$, value,\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n"
|
||||
@ -579,9 +584,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" $field_member$.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.Set$lite$(\n"
|
||||
" $field_member$.Set$lite$(\n"
|
||||
" $default_variable$, ::std::move(value), GetArenaNoVirtual());\n"
|
||||
" // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
|
||||
"}\n"
|
||||
@ -591,9 +596,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" $field_member$.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.Set$lite$($default_variable$,\n"
|
||||
" $field_member$.Set$lite$($default_variable$,\n"
|
||||
" $string_piece$(value), GetArenaNoVirtual());\n"
|
||||
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
|
||||
"}\n"
|
||||
@ -603,9 +608,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" $field_member$.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.Set$lite$(\n"
|
||||
" $field_member$.Set$lite$(\n"
|
||||
" $default_variable$, $string_piece$(\n"
|
||||
" reinterpret_cast<const char*>(value), size),\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
@ -615,9 +620,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" $field_member$.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" return $oneof_prefix$$name$_.Mutable($default_variable$,\n"
|
||||
" return $field_member$.Mutable($default_variable$,\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
"}\n"
|
||||
@ -625,7 +630,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" // @@protoc_insertion_point(field_release:$full_name$)\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" clear_has_$oneof_name$();\n"
|
||||
" return $oneof_prefix$$name$_.Release($default_variable$,\n"
|
||||
" return $field_member$.Release($default_variable$,\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
" } else {\n"
|
||||
" return NULL;\n"
|
||||
@ -633,12 +638,12 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
"}\n"
|
||||
"inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" $field_member$.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" if ($name$ != NULL) {\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.SetAllocated($default_variable$, $name$,\n"
|
||||
" $field_member$.SetAllocated($default_variable$, $name$,\n"
|
||||
" GetArenaNoVirtual());\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
|
||||
@ -649,7 +654,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" clear_has_$oneof_name$();\n"
|
||||
" return $oneof_prefix$$name$_.UnsafeArenaRelease(\n"
|
||||
" return $field_member$.UnsafeArenaRelease(\n"
|
||||
" $default_variable$, GetArenaNoVirtual());\n"
|
||||
" } else {\n"
|
||||
" return NULL;\n"
|
||||
@ -659,12 +664,12 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
"::std::string* $name$) {\n"
|
||||
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" $field_member$.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" if ($name$) {\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeArenaSetAllocated($default_variable$, "
|
||||
" $field_member$.UnsafeArenaSetAllocated($default_variable$, "
|
||||
"$name$, GetArenaNoVirtual());\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
|
||||
@ -677,7 +682,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
"inline const ::std::string& $classname$::$name$() const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" return $oneof_prefix$$name$_.GetNoArena();\n"
|
||||
" return $field_member$.GetNoArena();\n"
|
||||
" }\n"
|
||||
" return *$default_variable$;\n"
|
||||
"}\n"
|
||||
@ -686,9 +691,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" $field_member$.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n"
|
||||
" $field_member$.SetNoArena($default_variable$, value);\n"
|
||||
" // @@protoc_insertion_point(field_set:$full_name$)\n"
|
||||
"}\n"
|
||||
"#if LANG_CXX11\n"
|
||||
@ -697,10 +702,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" $field_member$.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.SetNoArena(\n"
|
||||
" $default_variable$, ::std::move(value));\n"
|
||||
" $field_member$.SetNoArena($default_variable$, ::std::move(value));\n"
|
||||
" // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
|
||||
"}\n"
|
||||
"#endif\n"
|
||||
@ -709,9 +713,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" $field_member$.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.SetNoArena($default_variable$,\n"
|
||||
" $field_member$.SetNoArena($default_variable$,\n"
|
||||
" $string_piece$(value));\n"
|
||||
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
|
||||
"}\n"
|
||||
@ -721,10 +725,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" $field_member$.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" $oneof_prefix$$name$_.SetNoArena($default_variable$, "
|
||||
"$string_piece$(\n"
|
||||
" $field_member$.SetNoArena($default_variable$, $string_piece$(\n"
|
||||
" reinterpret_cast<const char*>(value), size));\n"
|
||||
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
|
||||
"}\n"
|
||||
@ -732,29 +735,28 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
" if (!has_$name$()) {\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" $field_member$.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n"
|
||||
" return $field_member$.MutableNoArena($default_variable$);\n"
|
||||
"}\n"
|
||||
"inline ::std::string* $classname$::$release_name$() {\n"
|
||||
" // @@protoc_insertion_point(field_release:$full_name$)\n"
|
||||
" if (has_$name$()) {\n"
|
||||
" clear_has_$oneof_name$();\n"
|
||||
" return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n"
|
||||
" return $field_member$.ReleaseNoArena($default_variable$);\n"
|
||||
" } else {\n"
|
||||
" return NULL;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
|
||||
" if (!has_$name$()) {\n"
|
||||
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
|
||||
" $field_member$.UnsafeSetDefault($default_variable$);\n"
|
||||
" }\n"
|
||||
" clear_$oneof_name$();\n"
|
||||
" if ($name$ != NULL) {\n"
|
||||
" set_has_$name$();\n"
|
||||
" $oneof_prefix$$name$_.SetAllocatedNoArena($default_variable$,\n"
|
||||
" $name$);\n"
|
||||
" $field_member$.SetAllocatedNoArena($default_variable$, $name$);\n"
|
||||
" }\n"
|
||||
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
|
||||
"}\n");
|
||||
@ -765,12 +767,11 @@ void StringOneofFieldGenerator::
|
||||
GenerateClearingCode(io::Printer* printer) const {
|
||||
if (SupportsArenas(descriptor_)) {
|
||||
printer->Print(variables_,
|
||||
"$oneof_prefix$$name$_.Destroy($default_variable$,\n"
|
||||
"$field_member$.Destroy($default_variable$,\n"
|
||||
" GetArenaNoVirtual());\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"$oneof_prefix$$name$_."
|
||||
"DestroyNoArena($default_variable$);\n");
|
||||
"$field_member$.DestroyNoArena($default_variable$);\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -796,7 +797,7 @@ void StringOneofFieldGenerator::
|
||||
GenerateDestructorCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"if (has_$name$()) {\n"
|
||||
" $oneof_prefix$$name$_.DestroyNoArena($default_variable$);\n"
|
||||
" $field_member$.DestroyNoArena($default_variable$);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
@ -912,11 +913,21 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
|
||||
if (options_.safe_boundary_check) {
|
||||
printer->Print(variables_,
|
||||
"inline const ::std::string& $classname$::$name$(int index) const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return $name$_.InternalCheckedGet(\n"
|
||||
" index, ::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"inline const ::std::string& $classname$::$name$(int index) const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return $name$_.Get(index);\n"
|
||||
"}\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"inline const ::std::string& $classname$::$name$(int index) const {\n"
|
||||
" // @@protoc_insertion_point(field_get:$full_name$)\n"
|
||||
" return $name$_.$cppget$(index);\n"
|
||||
"}\n"
|
||||
"inline ::std::string* $classname$::mutable_$name$(int index) {\n"
|
||||
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
|
||||
" return $name$_.Mutable(index);\n"
|
||||
@ -991,7 +1002,8 @@ GenerateMergingCode(io::Printer* printer) const {
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateSwappingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n");
|
||||
printer->Print(variables_,
|
||||
"$name$_.InternalSwap(CastToBase(&other->$name$_));\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
|
@ -69,6 +69,8 @@ class StringFieldGenerator : public FieldGenerator {
|
||||
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
|
||||
void GenerateByteSize(io::Printer* printer) const;
|
||||
|
||||
bool MergeFromCodedStreamNeedsArena() const;
|
||||
|
||||
protected:
|
||||
const FieldDescriptor* descriptor_;
|
||||
std::map<string, string> variables_;
|
||||
|
@ -995,75 +995,76 @@ TEST(GeneratedMessageTest, TestEmbedOptimizedForSize) {
|
||||
|
||||
TEST(GeneratedMessageTest, TestSpaceUsed) {
|
||||
unittest::TestAllTypes message1;
|
||||
// sizeof provides a lower bound on SpaceUsed().
|
||||
EXPECT_LE(sizeof(unittest::TestAllTypes), message1.SpaceUsed());
|
||||
const int empty_message_size = message1.SpaceUsed();
|
||||
// sizeof provides a lower bound on SpaceUsedLong().
|
||||
EXPECT_LE(sizeof(unittest::TestAllTypes), message1.SpaceUsedLong());
|
||||
const size_t empty_message_size = message1.SpaceUsedLong();
|
||||
|
||||
// Setting primitive types shouldn't affect the space used.
|
||||
message1.set_optional_int32(123);
|
||||
message1.set_optional_int64(12345);
|
||||
message1.set_optional_uint32(123);
|
||||
message1.set_optional_uint64(12345);
|
||||
EXPECT_EQ(empty_message_size, message1.SpaceUsed());
|
||||
EXPECT_EQ(empty_message_size, message1.SpaceUsedLong());
|
||||
|
||||
// On some STL implementations, setting the string to a small value should
|
||||
// only increase SpaceUsed() by the size of a string object, though this is
|
||||
// not true everywhere.
|
||||
// only increase SpaceUsedLong() by the size of a string object, though this
|
||||
// is not true everywhere.
|
||||
message1.set_optional_string("abc");
|
||||
EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsed());
|
||||
EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsedLong());
|
||||
|
||||
// Setting a string to a value larger than the string object itself should
|
||||
// increase SpaceUsed(), because it cannot store the value internally.
|
||||
// increase SpaceUsedLong(), because it cannot store the value internally.
|
||||
message1.set_optional_string(string(sizeof(string) + 1, 'x'));
|
||||
int min_expected_increase = message1.optional_string().capacity() +
|
||||
sizeof(string);
|
||||
EXPECT_LE(empty_message_size + min_expected_increase,
|
||||
message1.SpaceUsed());
|
||||
message1.SpaceUsedLong());
|
||||
|
||||
int previous_size = message1.SpaceUsed();
|
||||
size_t previous_size = message1.SpaceUsedLong();
|
||||
// Adding an optional message should increase the size by the size of the
|
||||
// nested message type. NestedMessage is simple enough (1 int field) that it
|
||||
// is equal to sizeof(NestedMessage)
|
||||
message1.mutable_optional_nested_message();
|
||||
ASSERT_EQ(sizeof(unittest::TestAllTypes::NestedMessage),
|
||||
message1.optional_nested_message().SpaceUsed());
|
||||
message1.optional_nested_message().SpaceUsedLong());
|
||||
EXPECT_EQ(previous_size +
|
||||
sizeof(unittest::TestAllTypes::NestedMessage),
|
||||
message1.SpaceUsed());
|
||||
message1.SpaceUsedLong());
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageTest, TestOneofSpaceUsed) {
|
||||
unittest::TestOneof2 message1;
|
||||
EXPECT_LE(sizeof(unittest::TestOneof2), message1.SpaceUsed());
|
||||
EXPECT_LE(sizeof(unittest::TestOneof2), message1.SpaceUsedLong());
|
||||
|
||||
const int empty_message_size = message1.SpaceUsed();
|
||||
const size_t empty_message_size = message1.SpaceUsedLong();
|
||||
// Setting primitive types shouldn't affect the space used.
|
||||
message1.set_foo_int(123);
|
||||
message1.set_bar_int(12345);
|
||||
EXPECT_EQ(empty_message_size, message1.SpaceUsed());
|
||||
EXPECT_EQ(empty_message_size, message1.SpaceUsedLong());
|
||||
|
||||
// Setting a string in oneof to a small value should only increase SpaceUsed()
|
||||
// by the size of a string object.
|
||||
// Setting a string in oneof to a small value should only increase
|
||||
// SpaceUsedLong() by the size of a string object.
|
||||
message1.set_foo_string("abc");
|
||||
EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsed());
|
||||
EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsedLong());
|
||||
|
||||
// Setting a string in oneof to a value larger than the string object itself
|
||||
// should increase SpaceUsed(), because it cannot store the value internally.
|
||||
// should increase SpaceUsedLong(), because it cannot store the value
|
||||
// internally.
|
||||
message1.set_foo_string(string(sizeof(string) + 1, 'x'));
|
||||
int min_expected_increase = message1.foo_string().capacity() +
|
||||
sizeof(string);
|
||||
EXPECT_LE(empty_message_size + min_expected_increase,
|
||||
message1.SpaceUsed());
|
||||
message1.SpaceUsedLong());
|
||||
|
||||
// Setting a message in oneof should delete the other fields and increase the
|
||||
// size by the size of the nested message type. NestedMessage is simple enough
|
||||
// that it is equal to sizeof(NestedMessage)
|
||||
message1.mutable_foo_message();
|
||||
ASSERT_EQ(sizeof(unittest::TestOneof2::NestedMessage),
|
||||
message1.foo_message().SpaceUsed());
|
||||
message1.foo_message().SpaceUsedLong());
|
||||
EXPECT_EQ(empty_message_size +
|
||||
sizeof(unittest::TestOneof2::NestedMessage),
|
||||
message1.SpaceUsed());
|
||||
message1.SpaceUsedLong());
|
||||
}
|
||||
|
||||
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
|
||||
|
@ -72,9 +72,7 @@ class CppMetadataTest : public ::testing::Test {
|
||||
TestTempDir();
|
||||
|
||||
const bool result =
|
||||
atu::CaptureMetadata(filename, cpp_out,
|
||||
/* meta_file_suffix */ "", &cli, file,
|
||||
/* outputs */ NULL);
|
||||
atu::RunProtoCompiler(filename, cpp_out, &cli, file);
|
||||
|
||||
if (!result) {
|
||||
return result;
|
||||
|
@ -1259,19 +1259,9 @@ GenerateParsingConstructor(io::Printer* printer) {
|
||||
printer->Indent();
|
||||
|
||||
printer->Print(
|
||||
"case 0:\n" // zero signals EOF / limit reached
|
||||
" done = true;\n"
|
||||
" break;\n"
|
||||
"default: {\n"
|
||||
" if (!parseUnknownField$suffix$(\n"
|
||||
" input, unknownFields, extensionRegistry, tag)) {\n"
|
||||
" done = true;\n" // it's an endgroup tag
|
||||
" }\n"
|
||||
" break;\n"
|
||||
"}\n",
|
||||
"suffix",
|
||||
descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ? "Proto3"
|
||||
: "");
|
||||
"case 0:\n" // zero signals EOF / limit reached
|
||||
" done = true;\n"
|
||||
" break;\n");
|
||||
|
||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||
const FieldDescriptor* field = sorted_fields[i];
|
||||
@ -1309,6 +1299,18 @@ GenerateParsingConstructor(io::Printer* printer) {
|
||||
}
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"default: {\n"
|
||||
" if (!parseUnknownField$suffix$(\n"
|
||||
" input, unknownFields, extensionRegistry, tag)) {\n"
|
||||
" done = true;\n" // it's an endgroup tag
|
||||
" }\n"
|
||||
" break;\n"
|
||||
"}\n",
|
||||
"suffix",
|
||||
descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ? "Proto3"
|
||||
: "");
|
||||
|
||||
printer->Outdent();
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
|
@ -1005,37 +1005,6 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFromStream(
|
||||
" done = true;\n"
|
||||
" break;\n");
|
||||
|
||||
if (descriptor_->extension_range_count() > 0) {
|
||||
if (descriptor_->options().message_set_wire_format()) {
|
||||
printer->Print(
|
||||
"default: {\n"
|
||||
" if (!parseUnknownFieldAsMessageSet(\n"
|
||||
" getDefaultInstanceForType(), input, extensionRegistry,\n"
|
||||
" tag)) {\n"
|
||||
" done = true;\n" // it's an endgroup tag
|
||||
" }\n"
|
||||
" break;\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"default: {\n"
|
||||
" if (!parseUnknownField(getDefaultInstanceForType(),\n"
|
||||
" input, extensionRegistry, tag)) {\n"
|
||||
" done = true;\n" // it's an endgroup tag
|
||||
" }\n"
|
||||
" break;\n"
|
||||
"}\n");
|
||||
}
|
||||
} else {
|
||||
printer->Print(
|
||||
"default: {\n"
|
||||
" if (!parseUnknownField(tag, input)) {\n"
|
||||
" done = true;\n" // it's an endgroup tag
|
||||
" }\n"
|
||||
" break;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
google::protobuf::scoped_array<const FieldDescriptor* > sorted_fields(
|
||||
SortFieldsByNumber(descriptor_));
|
||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||
@ -1073,6 +1042,37 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFromStream(
|
||||
}
|
||||
}
|
||||
|
||||
if (descriptor_->extension_range_count() > 0) {
|
||||
if (descriptor_->options().message_set_wire_format()) {
|
||||
printer->Print(
|
||||
"default: {\n"
|
||||
" if (!parseUnknownFieldAsMessageSet(\n"
|
||||
" getDefaultInstanceForType(), input, extensionRegistry,\n"
|
||||
" tag)) {\n"
|
||||
" done = true;\n" // it's an endgroup tag
|
||||
" }\n"
|
||||
" break;\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"default: {\n"
|
||||
" if (!parseUnknownField(getDefaultInstanceForType(),\n"
|
||||
" input, extensionRegistry, tag)) {\n"
|
||||
" done = true;\n" // it's an endgroup tag
|
||||
" }\n"
|
||||
" break;\n"
|
||||
"}\n");
|
||||
}
|
||||
} else {
|
||||
printer->Print(
|
||||
"default: {\n"
|
||||
" if (!parseUnknownField(tag, input)) {\n"
|
||||
" done = true;\n" // it's an endgroup tag
|
||||
" }\n"
|
||||
" break;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
|
@ -195,9 +195,9 @@ string ModuleAlias(const string& filename) {
|
||||
// We'll worry about this problem if/when we actually see it. This name isn't
|
||||
// exposed to users so we can change it later if we need to.
|
||||
string basename = StripProto(filename);
|
||||
StripString(&basename, "-", '$');
|
||||
StripString(&basename, "/", '_');
|
||||
StripString(&basename, ".", '_');
|
||||
ReplaceCharacters(&basename, "-", '$');
|
||||
ReplaceCharacters(&basename, "/", '_');
|
||||
ReplaceCharacters(&basename, ".", '_');
|
||||
return basename + "_pb";
|
||||
}
|
||||
|
||||
@ -1028,7 +1028,7 @@ string JSFieldTypeAnnotation(const GeneratorOptions& options,
|
||||
if (!IsPrimitive(jstype)) {
|
||||
jstype = "!" + jstype;
|
||||
}
|
||||
jstype = "Array.<" + jstype + ">";
|
||||
jstype = "Array<" + jstype + ">";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1558,6 +1558,22 @@ bool GenerateJspbAllowedSet(const GeneratorOptions& options,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Embeds base64 encoded GeneratedCodeInfo proto in a comment at the end of
|
||||
// file.
|
||||
void EmbedCodeAnnotations(const GeneratedCodeInfo& annotations,
|
||||
io::Printer* printer) {
|
||||
// Serialize annotations proto into base64 string.
|
||||
string meta_content;
|
||||
annotations.SerializeToString(&meta_content);
|
||||
string meta_64;
|
||||
Base64Escape(meta_content, &meta_64);
|
||||
|
||||
// Print base64 encoded annotations at the end of output file in
|
||||
// a comment.
|
||||
printer->Print("\n// Below is base64 encoded GeneratedCodeInfo proto");
|
||||
printer->Print("\n// $encoded_proto$\n", "encoded_proto", meta_64);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void Generator::GenerateHeader(const GeneratorOptions& options,
|
||||
@ -2822,7 +2838,7 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
|
||||
"so that it\n"
|
||||
" * works in OPTIMIZED mode.\n"
|
||||
" *\n"
|
||||
" * @type {!Object.<number, jspb.ExtensionFieldInfo>}\n"
|
||||
" * @type {!Object<number, jspb.ExtensionFieldInfo>}\n"
|
||||
" */\n"
|
||||
"$class$.extensions = {};\n"
|
||||
"\n",
|
||||
@ -2843,7 +2859,7 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
|
||||
"so that it\n"
|
||||
" * works in OPTIMIZED mode.\n"
|
||||
" *\n"
|
||||
" * @type {!Object.<number, jspb.ExtensionFieldBinaryInfo>}\n"
|
||||
" * @type {!Object<number, jspb.ExtensionFieldBinaryInfo>}\n"
|
||||
" */\n"
|
||||
"$class$.extensionsBinary = {};\n"
|
||||
"\n",
|
||||
@ -3195,7 +3211,7 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
|
||||
"/**\n"
|
||||
" * A tuple of {field number, class constructor} for the extension\n"
|
||||
" * field named `$name$`.\n"
|
||||
" * @type {!jspb.ExtensionFieldInfo.<$extensionType$>}\n"
|
||||
" * @type {!jspb.ExtensionFieldInfo<$extensionType$>}\n"
|
||||
" */\n"
|
||||
"$class$.$name$ = new jspb.ExtensionFieldInfo(\n",
|
||||
"name", JSObjectFieldName(options, field),
|
||||
@ -3634,10 +3650,7 @@ bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files,
|
||||
}
|
||||
|
||||
if (options.annotate_code) {
|
||||
const string meta_file = filename + ".meta";
|
||||
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> info_output(
|
||||
context->Open(meta_file));
|
||||
annotations.SerializeToZeroCopyStream(info_output.get());
|
||||
EmbedCodeAnnotations(annotations, &printer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ namespace compiler {
|
||||
|
||||
// Returns the list of the names of files in all_files in the form of a
|
||||
// comma-separated string.
|
||||
string CommaSeparatedList(const std::vector<const FileDescriptor*> all_files) {
|
||||
string CommaSeparatedList(const std::vector<const FileDescriptor*>& all_files) {
|
||||
std::vector<string> names;
|
||||
for (size_t i = 0; i < all_files.size(); i++) {
|
||||
names.push_back(all_files[i]->name());
|
||||
|
@ -325,13 +325,6 @@ const Version& Version::default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
Version* Version::New(::google::protobuf::Arena* arena) const {
|
||||
Version* n = new Version;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void Version::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.Version)
|
||||
@ -342,7 +335,7 @@ void Version::Clear() {
|
||||
cached_has_bits = _has_bits_[0];
|
||||
if (cached_has_bits & 0x00000001u) {
|
||||
GOOGLE_DCHECK(!suffix_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
|
||||
(*suffix_.UnsafeRawStringPointer())->clear();
|
||||
suffix_.UnsafeMutablePointer()->clear();
|
||||
}
|
||||
if (cached_has_bits & 14u) {
|
||||
::memset(&major_, 0, static_cast<size_t>(
|
||||
@ -723,13 +716,6 @@ const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
CodeGeneratorRequest* CodeGeneratorRequest::New(::google::protobuf::Arena* arena) const {
|
||||
CodeGeneratorRequest* n = new CodeGeneratorRequest;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void CodeGeneratorRequest::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest)
|
||||
@ -743,7 +729,7 @@ void CodeGeneratorRequest::Clear() {
|
||||
if (cached_has_bits & 3u) {
|
||||
if (cached_has_bits & 0x00000001u) {
|
||||
GOOGLE_DCHECK(!parameter_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
|
||||
(*parameter_.UnsafeRawStringPointer())->clear();
|
||||
parameter_.UnsafeMutablePointer()->clear();
|
||||
}
|
||||
if (cached_has_bits & 0x00000002u) {
|
||||
GOOGLE_DCHECK(compiler_version_ != NULL);
|
||||
@ -813,7 +799,8 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream(
|
||||
case 15: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(input, add_proto_file()));
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
|
||||
input, add_proto_file()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
@ -870,14 +857,16 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
|
||||
// optional .google.protobuf.compiler.Version compiler_version = 3;
|
||||
if (cached_has_bits & 0x00000002u) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
||||
3, *this->compiler_version_, output);
|
||||
3, *compiler_version_, output);
|
||||
}
|
||||
|
||||
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||
for (unsigned int i = 0,
|
||||
n = static_cast<unsigned int>(this->proto_file_size()); i < n; i++) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
||||
15, this->proto_file(static_cast<int>(i)), output);
|
||||
15,
|
||||
this->proto_file(static_cast<int>(i)),
|
||||
output);
|
||||
}
|
||||
|
||||
if (_internal_metadata_.have_unknown_fields()) {
|
||||
@ -920,7 +909,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
|
||||
if (cached_has_bits & 0x00000002u) {
|
||||
target = ::google::protobuf::internal::WireFormatLite::
|
||||
InternalWriteMessageToArray(
|
||||
3, *this->compiler_version_, deterministic, target);
|
||||
3, *compiler_version_, deterministic, target);
|
||||
}
|
||||
|
||||
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
|
||||
@ -979,7 +968,7 @@ size_t CodeGeneratorRequest::ByteSizeLong() const {
|
||||
if (has_compiler_version()) {
|
||||
total_size += 1 +
|
||||
::google::protobuf::internal::WireFormatLite::MessageSize(
|
||||
*this->compiler_version_);
|
||||
*compiler_version_);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1051,8 +1040,8 @@ void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) {
|
||||
}
|
||||
void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
|
||||
using std::swap;
|
||||
file_to_generate_.InternalSwap(&other->file_to_generate_);
|
||||
proto_file_.InternalSwap(&other->proto_file_);
|
||||
file_to_generate_.InternalSwap(CastToBase(&other->file_to_generate_));
|
||||
CastToBase(&proto_file_)->InternalSwap(CastToBase(&other->proto_file_));
|
||||
parameter_.Swap(&other->parameter_);
|
||||
swap(compiler_version_, other->compiler_version_);
|
||||
swap(_has_bits_[0], other->_has_bits_[0]);
|
||||
@ -1138,13 +1127,6 @@ const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance()
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
CodeGeneratorResponse_File* CodeGeneratorResponse_File::New(::google::protobuf::Arena* arena) const {
|
||||
CodeGeneratorResponse_File* n = new CodeGeneratorResponse_File;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void CodeGeneratorResponse_File::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File)
|
||||
@ -1156,15 +1138,15 @@ void CodeGeneratorResponse_File::Clear() {
|
||||
if (cached_has_bits & 7u) {
|
||||
if (cached_has_bits & 0x00000001u) {
|
||||
GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
|
||||
(*name_.UnsafeRawStringPointer())->clear();
|
||||
name_.UnsafeMutablePointer()->clear();
|
||||
}
|
||||
if (cached_has_bits & 0x00000002u) {
|
||||
GOOGLE_DCHECK(!insertion_point_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
|
||||
(*insertion_point_.UnsafeRawStringPointer())->clear();
|
||||
insertion_point_.UnsafeMutablePointer()->clear();
|
||||
}
|
||||
if (cached_has_bits & 0x00000004u) {
|
||||
GOOGLE_DCHECK(!content_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
|
||||
(*content_.UnsafeRawStringPointer())->clear();
|
||||
content_.UnsafeMutablePointer()->clear();
|
||||
}
|
||||
}
|
||||
_has_bits_.Clear();
|
||||
@ -1518,13 +1500,6 @@ const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
CodeGeneratorResponse* CodeGeneratorResponse::New(::google::protobuf::Arena* arena) const {
|
||||
CodeGeneratorResponse* n = new CodeGeneratorResponse;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void CodeGeneratorResponse::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse)
|
||||
@ -1536,7 +1511,7 @@ void CodeGeneratorResponse::Clear() {
|
||||
cached_has_bits = _has_bits_[0];
|
||||
if (cached_has_bits & 0x00000001u) {
|
||||
GOOGLE_DCHECK(!error_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
|
||||
(*error_.UnsafeRawStringPointer())->clear();
|
||||
error_.UnsafeMutablePointer()->clear();
|
||||
}
|
||||
_has_bits_.Clear();
|
||||
_internal_metadata_.Clear();
|
||||
@ -1572,7 +1547,8 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream(
|
||||
case 15: {
|
||||
if (static_cast< ::google::protobuf::uint8>(tag) ==
|
||||
static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) {
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(input, add_file()));
|
||||
DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
|
||||
input, add_file()));
|
||||
} else {
|
||||
goto handle_unusual;
|
||||
}
|
||||
@ -1620,7 +1596,9 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
|
||||
for (unsigned int i = 0,
|
||||
n = static_cast<unsigned int>(this->file_size()); i < n; i++) {
|
||||
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
|
||||
15, this->file(static_cast<int>(i)), output);
|
||||
15,
|
||||
this->file(static_cast<int>(i)),
|
||||
output);
|
||||
}
|
||||
|
||||
if (_internal_metadata_.have_unknown_fields()) {
|
||||
@ -1752,7 +1730,7 @@ void CodeGeneratorResponse::Swap(CodeGeneratorResponse* other) {
|
||||
}
|
||||
void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
|
||||
using std::swap;
|
||||
file_.InternalSwap(&other->file_);
|
||||
CastToBase(&file_)->InternalSwap(CastToBase(&other->file_));
|
||||
error_.Swap(&other->error_);
|
||||
swap(_has_bits_[0], other->_has_bits_[0]);
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
@ -1769,5 +1747,21 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::Version* Arena::Create< ::google::protobuf::compiler::Version >(Arena* arena) {
|
||||
return Arena::CreateInternal< ::google::protobuf::compiler::Version >(arena);
|
||||
}
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::CodeGeneratorRequest* Arena::Create< ::google::protobuf::compiler::CodeGeneratorRequest >(Arena* arena) {
|
||||
return Arena::CreateInternal< ::google::protobuf::compiler::CodeGeneratorRequest >(arena);
|
||||
}
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::CodeGeneratorResponse_File* Arena::Create< ::google::protobuf::compiler::CodeGeneratorResponse_File >(Arena* arena) {
|
||||
return Arena::CreateInternal< ::google::protobuf::compiler::CodeGeneratorResponse_File >(arena);
|
||||
}
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::CodeGeneratorResponse* Arena::Create< ::google::protobuf::compiler::CodeGeneratorResponse >(Arena* arena) {
|
||||
return Arena::CreateInternal< ::google::protobuf::compiler::CodeGeneratorResponse >(arena);
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
@ -84,6 +84,14 @@ LIBPROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_;
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorRequest* Arena::Create< ::google::protobuf::compiler::CodeGeneratorRequest>(Arena*);
|
||||
template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorResponse* Arena::Create< ::google::protobuf::compiler::CodeGeneratorResponse>(Arena*);
|
||||
template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorResponse_File* Arena::Create< ::google::protobuf::compiler::CodeGeneratorResponse_File>(Arena*);
|
||||
template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::Version* Arena::Create< ::google::protobuf::compiler::Version>(Arena*);
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
|
||||
// ===================================================================
|
||||
@ -139,9 +147,13 @@ class LIBPROTOC_EXPORT Version : public ::google::protobuf::Message /* @@protoc_
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline Version* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
inline Version* New() const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<Version>(NULL);
|
||||
}
|
||||
|
||||
Version* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
Version* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<Version>(arena);
|
||||
}
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const Version& from);
|
||||
@ -287,9 +299,13 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline CodeGeneratorRequest* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
inline CodeGeneratorRequest* New() const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<CodeGeneratorRequest>(NULL);
|
||||
}
|
||||
|
||||
CodeGeneratorRequest* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
CodeGeneratorRequest* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<CodeGeneratorRequest>(arena);
|
||||
}
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const CodeGeneratorRequest& from);
|
||||
@ -351,11 +367,11 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
|
||||
int proto_file_size() const;
|
||||
void clear_proto_file();
|
||||
static const int kProtoFileFieldNumber = 15;
|
||||
const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
|
||||
::google::protobuf::FileDescriptorProto* mutable_proto_file(int index);
|
||||
::google::protobuf::FileDescriptorProto* add_proto_file();
|
||||
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
|
||||
mutable_proto_file();
|
||||
const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
|
||||
::google::protobuf::FileDescriptorProto* add_proto_file();
|
||||
const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
|
||||
proto_file() const;
|
||||
|
||||
@ -453,9 +469,13 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline CodeGeneratorResponse_File* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
inline CodeGeneratorResponse_File* New() const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<CodeGeneratorResponse_File>(NULL);
|
||||
}
|
||||
|
||||
CodeGeneratorResponse_File* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
CodeGeneratorResponse_File* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<CodeGeneratorResponse_File>(arena);
|
||||
}
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const CodeGeneratorResponse_File& from);
|
||||
@ -607,9 +627,13 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline CodeGeneratorResponse* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
inline CodeGeneratorResponse* New() const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<CodeGeneratorResponse>(NULL);
|
||||
}
|
||||
|
||||
CodeGeneratorResponse* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
CodeGeneratorResponse* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<CodeGeneratorResponse>(arena);
|
||||
}
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const CodeGeneratorResponse& from);
|
||||
@ -651,11 +675,11 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
|
||||
int file_size() const;
|
||||
void clear_file();
|
||||
static const int kFileFieldNumber = 15;
|
||||
const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
|
||||
::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index);
|
||||
::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
|
||||
::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
|
||||
mutable_file();
|
||||
const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
|
||||
::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
|
||||
const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
|
||||
file() const;
|
||||
|
||||
@ -973,23 +997,23 @@ inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* paramet
|
||||
inline int CodeGeneratorRequest::proto_file_size() const {
|
||||
return proto_file_.size();
|
||||
}
|
||||
inline const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
|
||||
return proto_file_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
|
||||
return proto_file_.Mutable(index);
|
||||
}
|
||||
inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
|
||||
return proto_file_.Add();
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
|
||||
CodeGeneratorRequest::mutable_proto_file() {
|
||||
// @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
|
||||
return &proto_file_;
|
||||
}
|
||||
inline const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
|
||||
return proto_file_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
|
||||
return proto_file_.Add();
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
|
||||
CodeGeneratorRequest::proto_file() const {
|
||||
// @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
|
||||
@ -1026,7 +1050,8 @@ inline ::google::protobuf::compiler::Version* CodeGeneratorRequest::release_comp
|
||||
inline ::google::protobuf::compiler::Version* CodeGeneratorRequest::mutable_compiler_version() {
|
||||
set_has_compiler_version();
|
||||
if (compiler_version_ == NULL) {
|
||||
compiler_version_ = new ::google::protobuf::compiler::Version;
|
||||
compiler_version_ = ::google::protobuf::Arena::Create< ::google::protobuf::compiler::Version >(
|
||||
GetArenaNoVirtual());
|
||||
}
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
|
||||
return compiler_version_;
|
||||
@ -1317,23 +1342,23 @@ inline int CodeGeneratorResponse::file_size() const {
|
||||
inline void CodeGeneratorResponse::clear_file() {
|
||||
file_.Clear();
|
||||
}
|
||||
inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file)
|
||||
return file_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
|
||||
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file)
|
||||
return file_.Mutable(index);
|
||||
}
|
||||
inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
|
||||
return file_.Add();
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
|
||||
CodeGeneratorResponse::mutable_file() {
|
||||
// @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
|
||||
return &file_;
|
||||
}
|
||||
inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
|
||||
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file)
|
||||
return file_.Get(index);
|
||||
}
|
||||
inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
|
||||
// @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
|
||||
return file_.Add();
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
|
||||
CodeGeneratorResponse::file() const {
|
||||
// @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
|
||||
|
@ -32,7 +32,10 @@
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <google/protobuf/stubs/hash.h>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#ifndef _SHARED_PTR_H
|
||||
@ -41,8 +44,6 @@
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/logging.h>
|
||||
@ -375,15 +376,13 @@ class PrefixRemover {
|
||||
string prefix_;
|
||||
};
|
||||
|
||||
// A DescriptorPool contains a bunch of hash_maps to implement the
|
||||
// A DescriptorPool contains a bunch of hash-maps to implement the
|
||||
// various Find*By*() methods. Since hashtable lookups are O(1), it's
|
||||
// most efficient to construct a fixed set of large hash_maps used by
|
||||
// most efficient to construct a fixed set of large hash-maps used by
|
||||
// all objects in the pool rather than construct one or more small
|
||||
// hash_maps for each object.
|
||||
// hash-maps for each object.
|
||||
//
|
||||
// The keys to these hash_maps are (parent, name) or (parent, number)
|
||||
// pairs. Unfortunately STL doesn't provide hash functions for pair<>,
|
||||
// so we must invent our own.
|
||||
// The keys to these hash-maps are (parent, name) or (parent, number) pairs.
|
||||
//
|
||||
// TODO(kenton): Use StringPiece rather than const char* in keys? It would
|
||||
// be a lot cleaner but we'd just have to convert it back to const char*
|
||||
@ -398,6 +397,13 @@ struct PointerStringPairEqual {
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::pair<const Descriptor*, int> DescriptorIntPair;
|
||||
typedef std::pair<const EnumDescriptor*, int> EnumIntPair;
|
||||
|
||||
#define HASH_MAP hash_map
|
||||
#define HASH_SET hash_set
|
||||
#define HASH_FXN hash
|
||||
|
||||
template<typename PairType>
|
||||
struct PointerIntegerPairHash {
|
||||
size_t operator()(const PairType& p) const {
|
||||
@ -417,9 +423,6 @@ struct PointerIntegerPairHash {
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::pair<const Descriptor*, int> DescriptorIntPair;
|
||||
typedef std::pair<const EnumDescriptor*, int> EnumIntPair;
|
||||
|
||||
struct PointerStringPairHash {
|
||||
size_t operator()(const PointerStringPair& p) const {
|
||||
// FIXME(kenton): What is the best way to compute this hash? I have
|
||||
@ -445,31 +448,37 @@ struct PointerStringPairHash {
|
||||
|
||||
const Symbol kNullSymbol;
|
||||
|
||||
typedef hash_map<const char*, Symbol,
|
||||
hash<const char*>, streq>
|
||||
SymbolsByNameMap;
|
||||
typedef hash_map<PointerStringPair, Symbol,
|
||||
typedef HASH_MAP<const char*, Symbol, HASH_FXN<const char*>, streq>
|
||||
SymbolsByNameMap;
|
||||
|
||||
typedef HASH_MAP<PointerStringPair, Symbol, PointerStringPairHash,
|
||||
PointerStringPairEqual>
|
||||
SymbolsByParentMap;
|
||||
|
||||
typedef HASH_MAP<const char*, const FileDescriptor*, HASH_FXN<const char*>,
|
||||
streq>
|
||||
FilesByNameMap;
|
||||
|
||||
typedef HASH_MAP<PointerStringPair, const FieldDescriptor*,
|
||||
PointerStringPairHash, PointerStringPairEqual>
|
||||
SymbolsByParentMap;
|
||||
typedef hash_map<const char*, const FileDescriptor*,
|
||||
hash<const char*>, streq>
|
||||
FilesByNameMap;
|
||||
typedef hash_map<PointerStringPair, const FieldDescriptor*,
|
||||
PointerStringPairHash, PointerStringPairEqual>
|
||||
FieldsByNameMap;
|
||||
typedef hash_map<DescriptorIntPair, const FieldDescriptor*,
|
||||
PointerIntegerPairHash<DescriptorIntPair> >
|
||||
FieldsByNumberMap;
|
||||
typedef hash_map<EnumIntPair, const EnumValueDescriptor*,
|
||||
PointerIntegerPairHash<EnumIntPair> >
|
||||
EnumValuesByNumberMap;
|
||||
// This is a map rather than a hash_map, since we use it to iterate
|
||||
FieldsByNameMap;
|
||||
|
||||
typedef HASH_MAP<DescriptorIntPair, const FieldDescriptor*,
|
||||
PointerIntegerPairHash<DescriptorIntPair>,
|
||||
std::equal_to<DescriptorIntPair> >
|
||||
FieldsByNumberMap;
|
||||
|
||||
typedef HASH_MAP<EnumIntPair, const EnumValueDescriptor*,
|
||||
PointerIntegerPairHash<EnumIntPair>,
|
||||
std::equal_to<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 std::map<DescriptorIntPair, const FieldDescriptor*>
|
||||
ExtensionsGroupedByDescriptorMap;
|
||||
typedef hash_map<string, const SourceCodeInfo_Location*> LocationsByPathMap;
|
||||
typedef HASH_MAP<string, const SourceCodeInfo_Location*> LocationsByPathMap;
|
||||
|
||||
std::set<string>* allowed_proto3_extendees_ = NULL;
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(allowed_proto3_extendees_init_);
|
||||
@ -564,17 +573,17 @@ class DescriptorPool::Tables {
|
||||
// execution of the current public API call, but for compatibility with
|
||||
// legacy clients, this is cleared at the beginning of each public API call.
|
||||
// Not used when fallback_database_ == NULL.
|
||||
hash_set<string> known_bad_files_;
|
||||
HASH_SET<string> known_bad_files_;
|
||||
|
||||
// A set of symbols which we have tried to load from the fallback database
|
||||
// and encountered errors. We will not attempt to load them again during
|
||||
// execution of the current public API call, but for compatibility with
|
||||
// legacy clients, this is cleared at the beginning of each public API call.
|
||||
hash_set<string> known_bad_symbols_;
|
||||
HASH_SET<string> known_bad_symbols_;
|
||||
|
||||
// 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_;
|
||||
HASH_SET<const Descriptor*> extensions_loaded_from_db_;
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Finding items.
|
||||
@ -787,14 +796,13 @@ class FileDescriptorTables {
|
||||
};
|
||||
|
||||
DescriptorPool::Tables::Tables()
|
||||
// Start some hash_map and hash_set objects with a small # of buckets
|
||||
// Start some hash-map and hash-set objects with a small # of buckets
|
||||
: known_bad_files_(3),
|
||||
known_bad_symbols_(3),
|
||||
extensions_loaded_from_db_(3),
|
||||
symbols_by_name_(3),
|
||||
files_by_name_(3) {}
|
||||
|
||||
|
||||
DescriptorPool::Tables::~Tables() {
|
||||
GOOGLE_DCHECK(checkpoints_.empty());
|
||||
// Note that the deletion order is important, since the destructors of some
|
||||
@ -948,8 +956,10 @@ inline Symbol FileDescriptorTables::FindNestedSymbolOfType(
|
||||
Symbol DescriptorPool::Tables::FindByNameHelper(
|
||||
const DescriptorPool* pool, const string& name) {
|
||||
MutexLockMaybe lock(pool->mutex_);
|
||||
known_bad_symbols_.clear();
|
||||
known_bad_files_.clear();
|
||||
if (pool->fallback_database_ != NULL) {
|
||||
known_bad_symbols_.clear();
|
||||
known_bad_files_.clear();
|
||||
}
|
||||
Symbol result = FindSymbol(name);
|
||||
|
||||
if (result.IsNull() && pool->underlay_ != NULL) {
|
||||
@ -1403,8 +1413,10 @@ void DescriptorPool::InternalAddGeneratedFile(
|
||||
|
||||
const FileDescriptor* DescriptorPool::FindFileByName(const string& name) const {
|
||||
MutexLockMaybe lock(mutex_);
|
||||
tables_->known_bad_symbols_.clear();
|
||||
tables_->known_bad_files_.clear();
|
||||
if (fallback_database_ != NULL) {
|
||||
tables_->known_bad_symbols_.clear();
|
||||
tables_->known_bad_files_.clear();
|
||||
}
|
||||
const FileDescriptor* result = tables_->FindFile(name);
|
||||
if (result != NULL) return result;
|
||||
if (underlay_ != NULL) {
|
||||
@ -1421,8 +1433,10 @@ const FileDescriptor* DescriptorPool::FindFileByName(const string& name) const {
|
||||
const FileDescriptor* DescriptorPool::FindFileContainingSymbol(
|
||||
const string& symbol_name) const {
|
||||
MutexLockMaybe lock(mutex_);
|
||||
tables_->known_bad_symbols_.clear();
|
||||
tables_->known_bad_files_.clear();
|
||||
if (fallback_database_ != NULL) {
|
||||
tables_->known_bad_symbols_.clear();
|
||||
tables_->known_bad_files_.clear();
|
||||
}
|
||||
Symbol result = tables_->FindSymbol(symbol_name);
|
||||
if (!result.IsNull()) return result.GetFile();
|
||||
if (underlay_ != NULL) {
|
||||
@ -1508,8 +1522,10 @@ const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
|
||||
}
|
||||
}
|
||||
MutexLockMaybe lock(mutex_);
|
||||
tables_->known_bad_symbols_.clear();
|
||||
tables_->known_bad_files_.clear();
|
||||
if (fallback_database_ != NULL) {
|
||||
tables_->known_bad_symbols_.clear();
|
||||
tables_->known_bad_files_.clear();
|
||||
}
|
||||
const FieldDescriptor* result = tables_->FindExtension(extendee, number);
|
||||
if (result != NULL) {
|
||||
return result;
|
||||
@ -1531,8 +1547,10 @@ void DescriptorPool::FindAllExtensions(
|
||||
const Descriptor* extendee,
|
||||
std::vector<const FieldDescriptor*>* out) const {
|
||||
MutexLockMaybe lock(mutex_);
|
||||
tables_->known_bad_symbols_.clear();
|
||||
tables_->known_bad_files_.clear();
|
||||
if (fallback_database_ != NULL) {
|
||||
tables_->known_bad_symbols_.clear();
|
||||
tables_->known_bad_files_.clear();
|
||||
}
|
||||
|
||||
// Initialize tables_->extensions_ from the fallback database first
|
||||
// (but do this only once per descriptor).
|
||||
@ -4539,7 +4557,7 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
|
||||
}
|
||||
}
|
||||
|
||||
hash_set<string> reserved_name_set;
|
||||
HASH_SET<string> reserved_name_set;
|
||||
for (int i = 0; i < proto.reserved_name_size(); i++) {
|
||||
const string& name = proto.reserved_name(i);
|
||||
if (reserved_name_set.find(name) == reserved_name_set.end()) {
|
||||
@ -5125,7 +5143,7 @@ void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto,
|
||||
}
|
||||
}
|
||||
|
||||
hash_set<string> reserved_name_set;
|
||||
HASH_SET<string> reserved_name_set;
|
||||
for (int i = 0; i < proto.reserved_name_size(); i++) {
|
||||
const string& name = proto.reserved_name(i);
|
||||
if (reserved_name_set.find(name) == reserved_name_set.end()) {
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -431,6 +431,7 @@ 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.
|
||||
@ -973,6 +974,7 @@ TEST_F(DescriptorTest, FieldEnumType) {
|
||||
EXPECT_EQ(enum_, bar_->enum_type());
|
||||
}
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
// Test simple flat messages and fields.
|
||||
@ -1943,6 +1945,7 @@ TEST_F(ExtensionDescriptorTest, FindAllExtensions) {
|
||||
EXPECT_EQ(39, extensions[3]->number());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) {
|
||||
DescriptorPool pool;
|
||||
FileDescriptorProto file_proto;
|
||||
|
@ -191,9 +191,6 @@ const Duration& Duration::default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
Duration* Duration::New(::google::protobuf::Arena* arena) const {
|
||||
return ::google::protobuf::Arena::CreateMessage<Duration>(arena);
|
||||
}
|
||||
|
||||
void Duration::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.Duration)
|
||||
@ -427,5 +424,12 @@ void Duration::InternalSwap(Duration* other) {
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Duration* Arena::CreateMessage< ::google::protobuf::Duration >(Arena* arena) {
|
||||
return Arena::CreateMessageInternal< ::google::protobuf::Duration >(arena);
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
@ -57,6 +57,11 @@ LIBPROTOBUF_EXPORT extern DurationDefaultTypeInternal _Duration_default_instance
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Duration* Arena::CreateMessage< ::google::protobuf::Duration>(Arena*);
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
@ -111,9 +116,13 @@ class LIBPROTOBUF_EXPORT Duration : public ::google::protobuf::Message /* @@prot
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline Duration* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
inline Duration* New() const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::CreateMessage<Duration>(NULL);
|
||||
}
|
||||
|
||||
Duration* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
Duration* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::CreateMessage<Duration>(arena);
|
||||
}
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const Duration& from);
|
||||
|
@ -263,7 +263,7 @@ class DynamicMessage : public Message {
|
||||
|
||||
Message* New() const;
|
||||
Message* New(::google::protobuf::Arena* arena) const;
|
||||
::google::protobuf::Arena* GetArena() const { return NULL; };
|
||||
::google::protobuf::Arena* GetArena() const { return arena_; }
|
||||
|
||||
int GetCachedSize() const;
|
||||
void SetCachedSize(int size) const;
|
||||
@ -282,7 +282,6 @@ class DynamicMessage : public Message {
|
||||
#endif // !_MSC_VER
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
|
||||
DynamicMessage(const TypeInfo* type_info, ::google::protobuf::Arena* arena);
|
||||
|
||||
void SharedCtor(bool lock_factory);
|
||||
@ -302,25 +301,25 @@ class DynamicMessage : public Message {
|
||||
}
|
||||
|
||||
const TypeInfo* type_info_;
|
||||
Arena* const arena_;
|
||||
// TODO(kenton): Make this an atomic<int> when C++ supports it.
|
||||
mutable int cached_byte_size_;
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
|
||||
};
|
||||
|
||||
DynamicMessage::DynamicMessage(const TypeInfo* type_info)
|
||||
: type_info_(type_info),
|
||||
cached_byte_size_(0) {
|
||||
: type_info_(type_info), arena_(NULL), cached_byte_size_(0) {
|
||||
SharedCtor(true);
|
||||
}
|
||||
|
||||
DynamicMessage::DynamicMessage(const TypeInfo* type_info,
|
||||
::google::protobuf::Arena* arena)
|
||||
: type_info_(type_info),
|
||||
cached_byte_size_(0) {
|
||||
: type_info_(type_info), arena_(arena), cached_byte_size_(0) {
|
||||
SharedCtor(true);
|
||||
}
|
||||
|
||||
DynamicMessage::DynamicMessage(const TypeInfo* type_info, bool lock_factory)
|
||||
: type_info_(type_info), cached_byte_size_(0) {
|
||||
: type_info_(type_info), arena_(NULL), cached_byte_size_(0) {
|
||||
SharedCtor(lock_factory);
|
||||
}
|
||||
|
||||
@ -342,10 +341,10 @@ void DynamicMessage::SharedCtor(bool lock_factory) {
|
||||
}
|
||||
|
||||
new (OffsetToPointer(type_info_->internal_metadata_offset))
|
||||
InternalMetadataWithArena;
|
||||
InternalMetadataWithArena(arena_);
|
||||
|
||||
if (type_info_->extensions_offset != -1) {
|
||||
new (OffsetToPointer(type_info_->extensions_offset)) ExtensionSet;
|
||||
new (OffsetToPointer(type_info_->extensions_offset)) ExtensionSet(arena_);
|
||||
}
|
||||
for (int i = 0; i < descriptor->field_count(); i++) {
|
||||
const FieldDescriptor* field = descriptor->field(i);
|
||||
@ -354,14 +353,14 @@ void DynamicMessage::SharedCtor(bool lock_factory) {
|
||||
continue;
|
||||
}
|
||||
switch (field->cpp_type()) {
|
||||
#define HANDLE_TYPE(CPPTYPE, TYPE) \
|
||||
case FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
||||
if (!field->is_repeated()) { \
|
||||
new(field_ptr) TYPE(field->default_value_##TYPE()); \
|
||||
} else { \
|
||||
new(field_ptr) RepeatedField<TYPE>(); \
|
||||
} \
|
||||
break;
|
||||
#define HANDLE_TYPE(CPPTYPE, TYPE) \
|
||||
case FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
||||
if (!field->is_repeated()) { \
|
||||
new (field_ptr) TYPE(field->default_value_##TYPE()); \
|
||||
} else { \
|
||||
new (field_ptr) RepeatedField<TYPE>(arena_); \
|
||||
} \
|
||||
break;
|
||||
|
||||
HANDLE_TYPE(INT32 , int32 );
|
||||
HANDLE_TYPE(INT64 , int64 );
|
||||
@ -376,7 +375,7 @@ void DynamicMessage::SharedCtor(bool lock_factory) {
|
||||
if (!field->is_repeated()) {
|
||||
new(field_ptr) int(field->default_value_enum()->number());
|
||||
} else {
|
||||
new(field_ptr) RepeatedField<int>();
|
||||
new (field_ptr) RepeatedField<int>(arena_);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -397,7 +396,7 @@ void DynamicMessage::SharedCtor(bool lock_factory) {
|
||||
ArenaStringPtr* asp = new(field_ptr) ArenaStringPtr();
|
||||
asp->UnsafeSetDefault(default_value);
|
||||
} else {
|
||||
new(field_ptr) RepeatedPtrField<string>();
|
||||
new (field_ptr) RepeatedPtrField<string>(arena_);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -412,15 +411,28 @@ void DynamicMessage::SharedCtor(bool lock_factory) {
|
||||
// when the constructor is called inside GetPrototype(), in which
|
||||
// case we have already locked the factory.
|
||||
if (lock_factory) {
|
||||
new (field_ptr) DynamicMapField(
|
||||
type_info_->factory->GetPrototype(field->message_type()));
|
||||
if (arena_ != NULL) {
|
||||
new (field_ptr) DynamicMapField(
|
||||
type_info_->factory->GetPrototype(field->message_type()),
|
||||
arena_);
|
||||
} else {
|
||||
new (field_ptr) DynamicMapField(
|
||||
type_info_->factory->GetPrototype(field->message_type()));
|
||||
}
|
||||
} else {
|
||||
new (field_ptr)
|
||||
DynamicMapField(type_info_->factory->GetPrototypeNoLock(
|
||||
field->message_type()));
|
||||
if (arena_ != NULL) {
|
||||
new (field_ptr)
|
||||
DynamicMapField(type_info_->factory->GetPrototypeNoLock(
|
||||
field->message_type()),
|
||||
arena_);
|
||||
} else {
|
||||
new (field_ptr)
|
||||
DynamicMapField(type_info_->factory->GetPrototypeNoLock(
|
||||
field->message_type()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
new (field_ptr) RepeatedPtrField<Message>();
|
||||
new (field_ptr) RepeatedPtrField<Message>(arena_);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -568,19 +580,17 @@ void DynamicMessage::CrossLinkPrototypes() {
|
||||
}
|
||||
}
|
||||
|
||||
Message* DynamicMessage::New() const {
|
||||
void* new_base = operator new(type_info_->size);
|
||||
memset(new_base, 0, type_info_->size);
|
||||
return new(new_base) DynamicMessage(type_info_);
|
||||
}
|
||||
Message* DynamicMessage::New() const { return New(NULL); }
|
||||
|
||||
Message* DynamicMessage::New(::google::protobuf::Arena* arena) const {
|
||||
if (arena != NULL) {
|
||||
Message* message = New();
|
||||
arena->Own(message);
|
||||
return message;
|
||||
void* new_base = Arena::CreateArray<char>(arena, type_info_->size);
|
||||
memset(new_base, 0, type_info_->size);
|
||||
return new (new_base) DynamicMessage(type_info_, arena);
|
||||
} else {
|
||||
return New();
|
||||
void* new_base = operator new(type_info_->size);
|
||||
memset(new_base, 0, type_info_->size);
|
||||
return new (new_base) DynamicMessage(type_info_);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
class DynamicMessageTest : public testing::Test {
|
||||
class DynamicMessageTest : public ::testing::TestWithParam<bool> {
|
||||
protected:
|
||||
DescriptorPool pool_;
|
||||
DynamicMessageFactory factory_;
|
||||
@ -144,38 +144,54 @@ TEST_F(DynamicMessageTest, Defaults) {
|
||||
reflection_tester.ExpectClearViaReflection(*prototype_);
|
||||
}
|
||||
|
||||
TEST_F(DynamicMessageTest, IndependentOffsets) {
|
||||
TEST_P(DynamicMessageTest, IndependentOffsets) {
|
||||
// Check that all fields have independent offsets by setting each
|
||||
// one to a unique value then checking that they all still have those
|
||||
// unique values (i.e. they don't stomp each other).
|
||||
google::protobuf::scoped_ptr<Message> message(prototype_->New());
|
||||
Arena arena;
|
||||
Message* message = prototype_->New(GetParam()? &arena : NULL);
|
||||
TestUtil::ReflectionTester reflection_tester(descriptor_);
|
||||
|
||||
reflection_tester.SetAllFieldsViaReflection(message.get());
|
||||
reflection_tester.SetAllFieldsViaReflection(message);
|
||||
reflection_tester.ExpectAllFieldsSetViaReflection(*message);
|
||||
|
||||
if (!GetParam()) {
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DynamicMessageTest, Extensions) {
|
||||
TEST_P(DynamicMessageTest, Extensions) {
|
||||
// Check that extensions work.
|
||||
google::protobuf::scoped_ptr<Message> message(extensions_prototype_->New());
|
||||
Arena arena;
|
||||
Message* message = extensions_prototype_->New(GetParam()? &arena : NULL);
|
||||
TestUtil::ReflectionTester reflection_tester(extensions_descriptor_);
|
||||
|
||||
reflection_tester.SetAllFieldsViaReflection(message.get());
|
||||
reflection_tester.SetAllFieldsViaReflection(message);
|
||||
reflection_tester.ExpectAllFieldsSetViaReflection(*message);
|
||||
|
||||
if (!GetParam()) {
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DynamicMessageTest, PackedFields) {
|
||||
TEST_P(DynamicMessageTest, PackedFields) {
|
||||
// Check that packed fields work properly.
|
||||
google::protobuf::scoped_ptr<Message> message(packed_prototype_->New());
|
||||
Arena arena;
|
||||
Message* message = packed_prototype_->New(GetParam()? &arena : NULL);
|
||||
TestUtil::ReflectionTester reflection_tester(packed_descriptor_);
|
||||
|
||||
reflection_tester.SetPackedFieldsViaReflection(message.get());
|
||||
reflection_tester.SetPackedFieldsViaReflection(message);
|
||||
reflection_tester.ExpectPackedFieldsSetViaReflection(*message);
|
||||
|
||||
if (!GetParam()) {
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DynamicMessageTest, Oneof) {
|
||||
TEST_P(DynamicMessageTest, Oneof) {
|
||||
// Check that oneof fields work properly.
|
||||
google::protobuf::scoped_ptr<Message> message(oneof_prototype_->New());
|
||||
Arena arena;
|
||||
Message* message = oneof_prototype_->New(GetParam()? &arena : NULL);
|
||||
|
||||
// Check default values.
|
||||
const Descriptor* descriptor = message->GetDescriptor();
|
||||
@ -226,29 +242,46 @@ TEST_F(DynamicMessageTest, Oneof) {
|
||||
|
||||
// Check set functions.
|
||||
TestUtil::ReflectionTester reflection_tester(oneof_descriptor_);
|
||||
reflection_tester.SetOneofViaReflection(message.get());
|
||||
reflection_tester.SetOneofViaReflection(message);
|
||||
reflection_tester.ExpectOneofSetViaReflection(*message);
|
||||
|
||||
if (!GetParam()) {
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DynamicMessageTest, SpaceUsed) {
|
||||
TEST_P(DynamicMessageTest, SpaceUsed) {
|
||||
// Test that SpaceUsed() works properly
|
||||
|
||||
// Since we share the implementation with generated messages, we don't need
|
||||
// to test very much here. Just make sure it appears to be working.
|
||||
|
||||
google::protobuf::scoped_ptr<Message> message(prototype_->New());
|
||||
Arena arena;
|
||||
Message* message = prototype_->New(GetParam()? &arena : NULL);
|
||||
TestUtil::ReflectionTester reflection_tester(descriptor_);
|
||||
|
||||
int initial_space_used = message->SpaceUsed();
|
||||
|
||||
reflection_tester.SetAllFieldsViaReflection(message.get());
|
||||
reflection_tester.SetAllFieldsViaReflection(message);
|
||||
EXPECT_LT(initial_space_used, message->SpaceUsed());
|
||||
|
||||
if (!GetParam()) {
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DynamicMessageTest, Arena) {
|
||||
Arena arena;
|
||||
Message* message = prototype_->New(&arena);
|
||||
(void)message; // avoid unused-variable error.
|
||||
Message* extension_message = extensions_prototype_->New(&arena);
|
||||
Message* packed_message = packed_prototype_->New(&arena);
|
||||
Message* oneof_message = oneof_prototype_->New(&arena);
|
||||
|
||||
// avoid unused-variable error.
|
||||
(void)message;
|
||||
(void)extension_message;
|
||||
(void)packed_message;
|
||||
(void)oneof_message;
|
||||
// Return without freeing: should not leak.
|
||||
}
|
||||
|
||||
@ -286,6 +319,7 @@ TEST_F(DynamicMessageTest, Proto3) {
|
||||
delete message;
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(UseArena, DynamicMessageTest, ::testing::Bool());
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
@ -180,9 +180,6 @@ const Empty& Empty::default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
Empty* Empty::New(::google::protobuf::Arena* arena) const {
|
||||
return ::google::protobuf::Arena::CreateMessage<Empty>(arena);
|
||||
}
|
||||
|
||||
void Empty::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.Empty)
|
||||
@ -338,5 +335,12 @@ void Empty::InternalSwap(Empty* other) {
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Empty* Arena::CreateMessage< ::google::protobuf::Empty >(Arena* arena) {
|
||||
return Arena::CreateMessageInternal< ::google::protobuf::Empty >(arena);
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
@ -57,6 +57,11 @@ LIBPROTOBUF_EXPORT extern EmptyDefaultTypeInternal _Empty_default_instance_;
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> LIBPROTOBUF_EXPORT ::google::protobuf::Empty* Arena::CreateMessage< ::google::protobuf::Empty>(Arena*);
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
@ -111,9 +116,13 @@ class LIBPROTOBUF_EXPORT Empty : public ::google::protobuf::Message /* @@protoc_
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline Empty* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
inline Empty* New() const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::CreateMessage<Empty>(NULL);
|
||||
}
|
||||
|
||||
Empty* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
Empty* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::CreateMessage<Empty>(arena);
|
||||
}
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const Empty& from);
|
||||
|
@ -33,6 +33,7 @@
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/stubs/hash.h>
|
||||
#include <utility>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/once.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
@ -750,8 +751,10 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
|
||||
|
||||
// RepeatedPtrField<MessageLite> does not know how to Add() since it cannot
|
||||
// allocate an abstract object, so we have to be tricky.
|
||||
MessageLite* result = extension->repeated_message_value
|
||||
->AddFromCleared<GenericTypeHandler<MessageLite> >();
|
||||
MessageLite* result =
|
||||
reinterpret_cast< ::google::protobuf::internal::RepeatedPtrFieldBase*>(
|
||||
extension->repeated_message_value)
|
||||
->AddFromCleared<GenericTypeHandler<MessageLite> >();
|
||||
if (result == NULL) {
|
||||
result = prototype.New(arena_);
|
||||
extension->repeated_message_value->AddAllocated(result);
|
||||
@ -925,8 +928,10 @@ void ExtensionSet::InternalExtensionMergeFrom(
|
||||
other_extension.repeated_message_value;
|
||||
for (int i = 0; i < other_repeated_message->size(); i++) {
|
||||
const MessageLite& other_message = other_repeated_message->Get(i);
|
||||
MessageLite* target = extension->repeated_message_value
|
||||
->AddFromCleared<GenericTypeHandler<MessageLite> >();
|
||||
MessageLite* target =
|
||||
reinterpret_cast< ::google::protobuf::internal::RepeatedPtrFieldBase*>(
|
||||
extension->repeated_message_value)
|
||||
->AddFromCleared<GenericTypeHandler<MessageLite> >();
|
||||
if (target == NULL) {
|
||||
target = other_message.New(arena_);
|
||||
extension->repeated_message_value->AddAllocated(target);
|
||||
@ -1747,6 +1752,9 @@ void ExtensionSet::Extension::Free() {
|
||||
// Defined in extension_set_heavy.cc.
|
||||
// int ExtensionSet::Extension::SpaceUsedExcludingSelf() const
|
||||
|
||||
// Dummy key method to avoid weak vtable.
|
||||
void ExtensionSet::LazyMessageExtension::UnusedKeyMethod() {}
|
||||
|
||||
// ==================================================================
|
||||
// Default repeated field instances for iterator-compatible accessors
|
||||
|
||||
|
@ -483,6 +483,8 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void UnusedKeyMethod(); // Dummy key method to avoid weak vtable.
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyMessageExtension);
|
||||
};
|
||||
struct Extension {
|
||||
|
@ -259,8 +259,10 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
|
||||
|
||||
// RepeatedPtrField<Message> does not know how to Add() since it cannot
|
||||
// allocate an abstract object, so we have to be tricky.
|
||||
MessageLite* result = extension->repeated_message_value
|
||||
->AddFromCleared<GenericTypeHandler<MessageLite> >();
|
||||
MessageLite* result =
|
||||
reinterpret_cast< ::google::protobuf::internal::RepeatedPtrFieldBase*>(
|
||||
extension->repeated_message_value)
|
||||
->AddFromCleared<GenericTypeHandler<MessageLite> >();
|
||||
if (result == NULL) {
|
||||
const MessageLite* prototype;
|
||||
if (extension->repeated_message_value->size() == 0) {
|
||||
@ -391,7 +393,9 @@ size_t ExtensionSet::Extension::SpaceUsedExcludingSelfLong() const {
|
||||
// type handler.
|
||||
total_size +=
|
||||
sizeof(*repeated_message_value) +
|
||||
RepeatedMessage_SpaceUsedExcludingSelfLong(repeated_message_value);
|
||||
RepeatedMessage_SpaceUsedExcludingSelfLong(
|
||||
reinterpret_cast< ::google::protobuf::internal::RepeatedPtrFieldBase*>(
|
||||
repeated_message_value));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -792,11 +792,16 @@ TEST(ExtensionSetTest, SpaceUsedExcludingSelf) {
|
||||
message.AddExtension(unittest::repeated_##type##_extension, value); \
|
||||
EXPECT_EQ(empty_repeated_field_size, message.SpaceUsed()) << #type; \
|
||||
message.ClearExtension(unittest::repeated_##type##_extension); \
|
||||
const int old_capacity = \
|
||||
message.GetRepeatedExtension(unittest::repeated_##type##_extension) \
|
||||
.Capacity(); \
|
||||
EXPECT_GE(old_capacity, kMinRepeatedFieldAllocationSize); \
|
||||
for (int i = 0; i < 16; ++i) { \
|
||||
message.AddExtension(unittest::repeated_##type##_extension, value); \
|
||||
} \
|
||||
int expected_size = sizeof(cpptype) * (16 - \
|
||||
kMinRepeatedFieldAllocationSize) + empty_repeated_field_size; \
|
||||
int expected_size = sizeof(cpptype) * \
|
||||
(message.GetRepeatedExtension(unittest::repeated_##type##_extension) \
|
||||
.Capacity() - old_capacity) + empty_repeated_field_size; \
|
||||
EXPECT_LE(expected_size, message.SpaceUsed()) << #type; \
|
||||
} while (0)
|
||||
|
||||
|
@ -169,13 +169,6 @@ const FieldMask& FieldMask::default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
|
||||
FieldMask* FieldMask::New(::google::protobuf::Arena* arena) const {
|
||||
FieldMask* n = new FieldMask;
|
||||
if (arena != NULL) {
|
||||
arena->Own(n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void FieldMask::Clear() {
|
||||
// @@protoc_insertion_point(message_clear_start:google.protobuf.FieldMask)
|
||||
@ -355,7 +348,7 @@ void FieldMask::Swap(FieldMask* other) {
|
||||
}
|
||||
void FieldMask::InternalSwap(FieldMask* other) {
|
||||
using std::swap;
|
||||
paths_.InternalSwap(&other->paths_);
|
||||
paths_.InternalSwap(CastToBase(&other->paths_));
|
||||
_internal_metadata_.Swap(&other->_internal_metadata_);
|
||||
swap(_cached_size_, other->_cached_size_);
|
||||
}
|
||||
@ -369,5 +362,12 @@ void FieldMask::InternalSwap(FieldMask* other) {
|
||||
// @@protoc_insertion_point(namespace_scope)
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::FieldMask* Arena::Create< ::google::protobuf::FieldMask >(Arena* arena) {
|
||||
return Arena::CreateInternal< ::google::protobuf::FieldMask >(arena);
|
||||
}
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
// @@protoc_insertion_point(global_scope)
|
||||
|
@ -57,6 +57,11 @@ LIBPROTOBUF_EXPORT extern FieldMaskDefaultTypeInternal _FieldMask_default_instan
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
template<> LIBPROTOBUF_EXPORT ::google::protobuf::FieldMask* Arena::Create< ::google::protobuf::FieldMask>(Arena*);
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
// ===================================================================
|
||||
|
||||
@ -104,9 +109,13 @@ class LIBPROTOBUF_EXPORT FieldMask : public ::google::protobuf::Message /* @@pro
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
inline FieldMask* New() const PROTOBUF_FINAL { return New(NULL); }
|
||||
inline FieldMask* New() const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<FieldMask>(NULL);
|
||||
}
|
||||
|
||||
FieldMask* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
|
||||
FieldMask* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL {
|
||||
return ::google::protobuf::Arena::Create<FieldMask>(arena);
|
||||
}
|
||||
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
|
||||
void CopyFrom(const FieldMask& from);
|
||||
|
@ -41,7 +41,6 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/template_util.h>
|
||||
#include <google/protobuf/generated_enum_util.h>
|
||||
|
||||
namespace google {
|
||||
|
@ -31,7 +31,7 @@
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
|
||||
|
||||
#include <google/protobuf/stubs/template_util.h>
|
||||
#include <google/protobuf/stubs/type_traits.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
@ -1124,9 +1124,6 @@ string GeneratedMessageReflection::GetString(
|
||||
return GetField<ArenaStringPtr>(message, field).Get();
|
||||
}
|
||||
}
|
||||
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return GetEmptyString(); // Make compiler happy.
|
||||
}
|
||||
}
|
||||
|
||||
@ -1144,9 +1141,6 @@ const string& GeneratedMessageReflection::GetStringReference(
|
||||
return GetField<ArenaStringPtr>(message, field).Get();
|
||||
}
|
||||
}
|
||||
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return GetEmptyString(); // Make compiler happy.
|
||||
}
|
||||
}
|
||||
|
||||
@ -1188,9 +1182,6 @@ string GeneratedMessageReflection::GetRepeatedString(
|
||||
case FieldOptions::STRING:
|
||||
return GetRepeatedPtrField<string>(message, field, index);
|
||||
}
|
||||
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return GetEmptyString(); // Make compiler happy.
|
||||
}
|
||||
}
|
||||
|
||||
@ -1206,9 +1197,6 @@ const string& GeneratedMessageReflection::GetRepeatedStringReference(
|
||||
case FieldOptions::STRING:
|
||||
return GetRepeatedPtrField<string>(message, field, index);
|
||||
}
|
||||
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return GetEmptyString(); // Make compiler happy.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -655,12 +655,9 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection PROTOBUF_FINAL : public Refl
|
||||
// dynamic_cast_if_available() implements this logic. If RTTI is
|
||||
// enabled, it does a dynamic_cast. If RTTI is disabled, it just returns
|
||||
// NULL.
|
||||
//
|
||||
// If you need to compile without RTTI, simply #define GOOGLE_PROTOBUF_NO_RTTI.
|
||||
// On MSVC, this should be detected automatically.
|
||||
template<typename To, typename From>
|
||||
inline To dynamic_cast_if_available(From from) {
|
||||
#if defined(GOOGLE_PROTOBUF_NO_RTTI) || (defined(_MSC_VER)&&!defined(_CPPRTTI))
|
||||
#ifdef GOOGLE_PROTOBUF_NO_RTTI
|
||||
// Avoid the compiler warning about unused variables.
|
||||
(void)from;
|
||||
return NULL;
|
||||
@ -688,8 +685,7 @@ T* DynamicCastToGenerated(const Message* from) {
|
||||
const Message* unused = static_cast<T*>(NULL);
|
||||
(void)unused;
|
||||
|
||||
#if defined(GOOGLE_PROTOBUF_NO_RTTI) || \
|
||||
(defined(_MSC_VER) && !defined(_CPPRTTI))
|
||||
#ifdef GOOGLE_PROTOBUF_NO_RTTI
|
||||
bool ok = &T::default_instance() ==
|
||||
from->GetReflection()->GetMessageFactory()->GetPrototype(
|
||||
from->GetDescriptor());
|
||||
|
@ -307,6 +307,7 @@ inline bool HandleEnum(const ParseTable& table, io::CodedInputStream* input,
|
||||
class RepeatedMessageTypeHandler {
|
||||
public:
|
||||
typedef MessageLite Type;
|
||||
typedef MessageLite WeakType;
|
||||
static Arena* GetArena(Type* t) { return t->GetArena(); }
|
||||
static void* GetMaybeArenaPointer(Type* t) {
|
||||
return t->GetMaybeArenaPointer();
|
||||
@ -351,7 +352,7 @@ inline bool ReadMessage(io::CodedInputStream* input, MessageLite* value) {
|
||||
std::pair<io::CodedInputStream::Limit, int> p =
|
||||
input->IncrementRecursionDepthAndPushLimit(length);
|
||||
if (GOOGLE_PREDICT_FALSE(p.second < 0 ||
|
||||
!value->MergePartialFromCodedStream(input))) {
|
||||
!value->MergePartialFromCodedStream(input))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -394,7 +395,8 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!UnknownFieldHandler::Skip(msg, table, input, tag))) {
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
!UnknownFieldHandler::Skip(msg, table, input, tag))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -421,7 +423,7 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table,
|
||||
#define HANDLE_TYPE(TYPE, CPPTYPE) \
|
||||
case (WireFormatLite::TYPE_##TYPE): { \
|
||||
CPPTYPE value; \
|
||||
if (GOOGLE_PREDICT_FALSE( \
|
||||
if (GOOGLE_PREDICT_FALSE( \
|
||||
(!WireFormatLite::ReadPrimitive< \
|
||||
CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)))) { \
|
||||
return false; \
|
||||
@ -432,8 +434,8 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table,
|
||||
case (WireFormatLite::TYPE_##TYPE) | kRepeatedMask: { \
|
||||
google::protobuf::RepeatedField<CPPTYPE>* values = \
|
||||
Raw<google::protobuf::RepeatedField<CPPTYPE> >(msg, offset); \
|
||||
if (GOOGLE_PREDICT_FALSE((!WireFormatLite::ReadRepeatedPrimitive< \
|
||||
CPPTYPE, WireFormatLite::TYPE_##TYPE>( \
|
||||
if (GOOGLE_PREDICT_FALSE((!WireFormatLite::ReadRepeatedPrimitive< \
|
||||
CPPTYPE, WireFormatLite::TYPE_##TYPE>( \
|
||||
data->tag_size, tag, input, values)))) { \
|
||||
return false; \
|
||||
} \
|
||||
@ -442,7 +444,7 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table,
|
||||
case (WireFormatLite::TYPE_##TYPE) | kOneofMask: { \
|
||||
uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset); \
|
||||
CPPTYPE value; \
|
||||
if (GOOGLE_PREDICT_FALSE( \
|
||||
if (GOOGLE_PREDICT_FALSE( \
|
||||
(!WireFormatLite::ReadPrimitive< \
|
||||
CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)))) { \
|
||||
return false; \
|
||||
@ -578,29 +580,32 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table,
|
||||
}
|
||||
#endif
|
||||
case WireFormatLite::TYPE_ENUM: {
|
||||
if (GOOGLE_PREDICT_FALSE((!HandleEnum<UnknownFieldHandler, InternalMetadata,
|
||||
Cardinality_SINGULAR>(
|
||||
table, input, msg, has_bits, presence_index, offset, tag,
|
||||
field_number)))) {
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!HandleEnum<UnknownFieldHandler, InternalMetadata,
|
||||
Cardinality_SINGULAR>(
|
||||
table, input, msg, has_bits, presence_index, offset, tag,
|
||||
field_number)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_ENUM | kRepeatedMask: {
|
||||
if (GOOGLE_PREDICT_FALSE((!HandleEnum<UnknownFieldHandler, InternalMetadata,
|
||||
Cardinality_REPEATED>(
|
||||
table, input, msg, has_bits, presence_index, offset, tag,
|
||||
field_number)))) {
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!HandleEnum<UnknownFieldHandler, InternalMetadata,
|
||||
Cardinality_REPEATED>(
|
||||
table, input, msg, has_bits, presence_index, offset, tag,
|
||||
field_number)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WireFormatLite::TYPE_ENUM | kOneofMask: {
|
||||
uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset);
|
||||
if (GOOGLE_PREDICT_FALSE((!HandleEnum<UnknownFieldHandler, InternalMetadata,
|
||||
Cardinality_ONEOF>(
|
||||
table, input, msg, oneof_case, presence_index, offset, tag,
|
||||
field_number)))) {
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
(!HandleEnum<UnknownFieldHandler, InternalMetadata,
|
||||
Cardinality_ONEOF>(table, input, msg, oneof_case,
|
||||
presence_index, offset, tag,
|
||||
field_number)))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@ -619,8 +624,8 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table,
|
||||
*submsg_holder = submsg;
|
||||
}
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadGroup(
|
||||
field_number, input, submsg))) {
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
!WireFormatLite::ReadGroup(field_number, input, submsg))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -635,8 +640,8 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table,
|
||||
MessageLite* submsg =
|
||||
MergePartialFromCodedStreamHelper::Add(field, prototype);
|
||||
|
||||
if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadGroup(
|
||||
field_number, input, submsg))) {
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
!WireFormatLite::ReadGroup(field_number, input, submsg))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -727,7 +732,7 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table,
|
||||
case WireFormatLite::TYPE_##TYPE: { \
|
||||
google::protobuf::RepeatedField<CPPTYPE>* values = \
|
||||
Raw<google::protobuf::RepeatedField<CPPTYPE> >(msg, offset); \
|
||||
if (GOOGLE_PREDICT_FALSE( \
|
||||
if (GOOGLE_PREDICT_FALSE( \
|
||||
(!WireFormatLite::ReadPackedPrimitive< \
|
||||
CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, values)))) { \
|
||||
return false; \
|
||||
@ -809,7 +814,8 @@ bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table,
|
||||
}
|
||||
|
||||
// process unknown field.
|
||||
if (GOOGLE_PREDICT_FALSE(!UnknownFieldHandler::Skip(msg, table, input, tag))) {
|
||||
if (GOOGLE_PREDICT_FALSE(
|
||||
!UnknownFieldHandler::Skip(msg, table, input, tag))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user