Merge pull request #3988 from acozzette/down-integrate

Integrated internal changes from Google
This commit is contained in:
Adam Cozzette 2017-12-05 13:02:36 -08:00 committed by GitHub
commit 9021f623e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
142 changed files with 4472 additions and 3286 deletions

View File

@ -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 \

View File

@ -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

View File

@ -54,4 +54,3 @@ Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT32
Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT64
Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT32
Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64

View File

@ -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

View File

@ -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>

View File

@ -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());

View 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;
}
}
}

View File

@ -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();
}
/**

View File

@ -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() {

View File

@ -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;
}
}

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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));

View File

@ -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());
}
}

View File

@ -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() + "\"");

View File

@ -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();

View File

@ -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(

View File

@ -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) {

View File

@ -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_ = [];

View File

@ -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_;

View File

@ -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);

View File

@ -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));
}

View File

@ -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.

View File

@ -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;

View File

@ -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');

View File

@ -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;

View File

@ -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) {

View File

@ -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 = {};

View File

@ -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([]);

View File

@ -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.
**/

View File

@ -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

View File

@ -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('.', '/'),

View File

@ -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.

View File

@ -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

View File

@ -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()

View File

@ -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):

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -938,7 +938,7 @@ def _SkipField(tokenizer):
tokenizer.ConsumeIdentifier()
tokenizer.Consume(']')
else:
tokenizer.ConsumeIdentifier()
tokenizer.ConsumeIdentifierOrNumber()
_SkipFieldContents(tokenizer)

View File

@ -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 \

View File

@ -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)

View File

@ -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);

View File

@ -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.
//

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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
};

View File

@ -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

View File

@ -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_;

View File

@ -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) {

View File

@ -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);

View File

@ -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::

View File

@ -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() {}

View File

@ -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)

View File

@ -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) {

View File

@ -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(

View File

@ -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;
}

View File

@ -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);

View File

@ -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 {

View File

@ -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);

View File

@ -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");
}

View File

@ -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);

View File

@ -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;

View File

@ -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");
}

View File

@ -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::

View File

@ -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_;

View File

@ -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

View File

@ -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;

View File

@ -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(

View File

@ -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(

View File

@ -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);
}
}
}

View File

@ -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());

View File

@ -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)

View File

@ -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)

View 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

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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_);
}
}

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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 {

View File

@ -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 {

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -41,7 +41,6 @@
#include <string>
#include <google/protobuf/stubs/template_util.h>
#include <google/protobuf/generated_enum_util.h>
namespace google {

View File

@ -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 {

View File

@ -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.
}
}

View File

@ -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());

View File

@ -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