Integrated internal changes from Google

This commit is contained in:
Adam Cozzette 2016-11-17 16:48:38 -08:00
parent e28286fa05
commit 5a76e633ea
286 changed files with 15368 additions and 13628 deletions

View File

@ -1,8 +1,11 @@
import com.google.protobuf.conformance.Conformance;
import com.google.protobuf.util.JsonFormat;
import com.google.protobuf.util.JsonFormat.TypeRegistry;
import com.google.protobuf.ByteString;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.conformance.Conformance;
import com.google.protobuf.util.JsonFormat.TypeRegistry;
import com.google.protobuf.util.JsonFormat;
import java.io.IOException;
import java.nio.ByteBuffer;
class ConformanceJava {
private int testCount = 0;
@ -47,13 +50,182 @@ class ConformanceJava {
writeToStdout(buf);
}
private enum BinaryDecoder {
BYTE_STRING_DECODER() {
@Override
public Conformance.TestAllTypes parse(ByteString bytes)
throws InvalidProtocolBufferException {
return Conformance.TestAllTypes.parseFrom(bytes);
}
},
BYTE_ARRAY_DECODER() {
@Override
public Conformance.TestAllTypes parse(ByteString bytes)
throws InvalidProtocolBufferException {
return Conformance.TestAllTypes.parseFrom(bytes.toByteArray());
}
},
ARRAY_BYTE_BUFFER_DECODER() {
@Override
public Conformance.TestAllTypes parse(ByteString bytes)
throws InvalidProtocolBufferException {
ByteBuffer buffer = ByteBuffer.allocate(bytes.size());
bytes.copyTo(buffer);
buffer.flip();
try {
return Conformance.TestAllTypes.parseFrom(CodedInputStream.newInstance(buffer));
} catch (InvalidProtocolBufferException e) {
throw e;
} catch (IOException e) {
throw new RuntimeException(
"ByteString based ByteBuffer should not throw IOException.", e);
}
}
},
READONLY_ARRAY_BYTE_BUFFER_DECODER() {
@Override
public Conformance.TestAllTypes parse(ByteString bytes)
throws InvalidProtocolBufferException {
try {
return Conformance.TestAllTypes.parseFrom(
CodedInputStream.newInstance(bytes.asReadOnlyByteBuffer()));
} catch (InvalidProtocolBufferException e) {
throw e;
} catch (IOException e) {
throw new RuntimeException(
"ByteString based ByteBuffer should not throw IOException.", e);
}
}
},
DIRECT_BYTE_BUFFER_DECODER() {
@Override
public Conformance.TestAllTypes parse(ByteString bytes)
throws InvalidProtocolBufferException {
ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
bytes.copyTo(buffer);
buffer.flip();
try {
return Conformance.TestAllTypes.parseFrom(CodedInputStream.newInstance(buffer));
} catch (InvalidProtocolBufferException e) {
throw e;
} catch (IOException e) {
throw new RuntimeException(
"ByteString based ByteBuffer should not throw IOException.", e);
}
}
},
READONLY_DIRECT_BYTE_BUFFER_DECODER() {
@Override
public Conformance.TestAllTypes parse(ByteString bytes)
throws InvalidProtocolBufferException {
ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
bytes.copyTo(buffer);
buffer.flip();
try {
return Conformance.TestAllTypes.parseFrom(
CodedInputStream.newInstance(buffer.asReadOnlyBuffer()));
} catch (InvalidProtocolBufferException e) {
throw e;
} catch (IOException e) {
throw new RuntimeException(
"ByteString based ByteBuffer should not throw IOException.", e);
}
}
},
INPUT_STREAM_DECODER() {
@Override
public Conformance.TestAllTypes parse(ByteString bytes)
throws InvalidProtocolBufferException {
try {
return Conformance.TestAllTypes.parseFrom(bytes.newInput());
} catch (InvalidProtocolBufferException e) {
throw e;
} catch (IOException e) {
throw new RuntimeException(
"ByteString based InputStream should not throw IOException.", e);
}
}
};
public abstract Conformance.TestAllTypes parse(ByteString bytes)
throws InvalidProtocolBufferException;
}
private Conformance.TestAllTypes parseBinary(ByteString bytes)
throws InvalidProtocolBufferException {
Conformance.TestAllTypes[] messages =
new Conformance.TestAllTypes[BinaryDecoder.values().length];
InvalidProtocolBufferException[] exceptions =
new InvalidProtocolBufferException[BinaryDecoder.values().length];
boolean hasMessage = false;
boolean hasException = false;
for (int i = 0; i < BinaryDecoder.values().length; ++i) {
try {
messages[i] = BinaryDecoder.values()[i].parse(bytes);
hasMessage = true;
} catch (InvalidProtocolBufferException e) {
exceptions[i] = e;
hasException = true;
}
}
if (hasMessage && hasException) {
StringBuilder sb =
new StringBuilder("Binary decoders disagreed on whether the payload was valid.\n");
for (int i = 0; i < BinaryDecoder.values().length; ++i) {
sb.append(BinaryDecoder.values()[i].name());
if (messages[i] != null) {
sb.append(" accepted the payload.\n");
} else {
sb.append(" rejected the payload.\n");
}
}
throw new RuntimeException(sb.toString());
}
if (hasException) {
// We do not check if exceptions are equal. Different implementations may return different
// exception messages. Throw an arbitrary one out instead.
throw exceptions[0];
}
// Fast path comparing all the messages with the first message, assuming equality being
// symmetric and transitive.
boolean allEqual = true;
for (int i = 1; i < messages.length; ++i) {
if (!messages[0].equals(messages[i])) {
allEqual = false;
break;
}
}
// Slow path: compare and find out all unequal pairs.
if (!allEqual) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < messages.length - 1; ++i) {
for (int j = i + 1; j < messages.length; ++j) {
if (!messages[i].equals(messages[j])) {
sb.append(BinaryDecoder.values()[i].name())
.append(" and ")
.append(BinaryDecoder.values()[j].name())
.append(" parsed the payload differently.\n");
}
}
}
throw new RuntimeException(sb.toString());
}
return messages[0];
}
private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
Conformance.TestAllTypes testMessage;
switch (request.getPayloadCase()) {
case PROTOBUF_PAYLOAD: {
try {
testMessage = Conformance.TestAllTypes.parseFrom(request.getProtobufPayload());
testMessage = parseBinary(request.getProtobufPayload());
} catch (InvalidProtocolBufferException e) {
return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
}

View File

@ -685,7 +685,7 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
R"({
"fieldname1": 1,
"fieldName2": 2,
"fieldName3": 3,
"FieldName3": 3,
"fieldName4": 4
})",
R"(
@ -725,12 +725,12 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
RunValidJsonTest(
"FieldNameWithDoubleUnderscores", RECOMMENDED,
R"({
"fieldName13": 13,
"fieldName14": 14,
"FieldName13": 13,
"FieldName14": 14,
"fieldName15": 15,
"fieldName16": 16,
"fieldName17": 17,
"fieldName18": 18
"FieldName18": 18
})",
R"(
__field_name13: 13
@ -873,21 +873,19 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
"optionalNestedMessage": {a: 1},
"optional_nested_message": {}
})");
// NOTE: The spec for JSON support is still being sorted out, these may not
// all be correct.
// Serializers should use lowerCamelCase by default.
RunValidJsonTestWithValidator(
"FieldNameInLowerCamelCase", REQUIRED,
R"({
"fieldname1": 1,
"fieldName2": 2,
"fieldName3": 3,
"FieldName3": 3,
"fieldName4": 4
})",
[](const Json::Value& value) {
return value.isMember("fieldname1") &&
value.isMember("fieldName2") &&
value.isMember("fieldName3") &&
value.isMember("FieldName3") &&
value.isMember("fieldName4");
});
RunValidJsonTestWithValidator(
@ -921,20 +919,20 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
RunValidJsonTestWithValidator(
"FieldNameWithDoubleUnderscores", RECOMMENDED,
R"({
"fieldName13": 13,
"fieldName14": 14,
"FieldName13": 13,
"FieldName14": 14,
"fieldName15": 15,
"fieldName16": 16,
"fieldName17": 17,
"fieldName18": 18
"FieldName18": 18
})",
[](const Json::Value& value) {
return value.isMember("fieldName13") &&
value.isMember("fieldName14") &&
return value.isMember("FieldName13") &&
value.isMember("FieldName14") &&
value.isMember("fieldName15") &&
value.isMember("fieldName16") &&
value.isMember("fieldName17") &&
value.isMember("fieldName18");
value.isMember("FieldName18");
});
// Integer fields.

View File

@ -17,9 +17,6 @@ Recommended.JsonInput.FieldNameDuplicate
Recommended.JsonInput.FieldNameDuplicateDifferentCasing1
Recommended.JsonInput.FieldNameDuplicateDifferentCasing2
Recommended.JsonInput.FieldNameNotQuoted
Recommended.JsonInput.FieldNameWithDoubleUnderscores.JsonOutput
Recommended.JsonInput.FieldNameWithDoubleUnderscores.ProtobufOutput
Recommended.JsonInput.FieldNameWithDoubleUnderscores.Validator
Recommended.JsonInput.MapFieldValueIsNull
Recommended.JsonInput.RepeatedFieldMessageElementIsNull
Recommended.JsonInput.RepeatedFieldPrimitiveElementIsNull
@ -35,10 +32,6 @@ Recommended.JsonInput.TrailingCommaInAnObject
Recommended.JsonInput.TrailingCommaInAnObjectWithNewlines
Recommended.JsonInput.TrailingCommaInAnObjectWithSpace
Recommended.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace
Required.JsonInput.DoubleFieldTooSmall
Required.JsonInput.FieldNameInLowerCamelCase.Validator
Required.JsonInput.FieldNameInSnakeCase.JsonOutput
Required.JsonInput.FieldNameInSnakeCase.ProtobufOutput
Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE

View File

@ -20,9 +20,6 @@ Recommended.JsonInput.DoubleFieldNegativeInfinityNotQuoted
Recommended.JsonInput.FieldMaskInvalidCharacter
Recommended.JsonInput.FieldNameDuplicate
Recommended.JsonInput.FieldNameNotQuoted
Recommended.JsonInput.FieldNameWithDoubleUnderscores.JsonOutput
Recommended.JsonInput.FieldNameWithDoubleUnderscores.ProtobufOutput
Recommended.JsonInput.FieldNameWithDoubleUnderscores.Validator
Recommended.JsonInput.FloatFieldInfinityNotQuoted
Recommended.JsonInput.FloatFieldNanNotQuoted
Recommended.JsonInput.FloatFieldNegativeInfinityNotQuoted
@ -35,15 +32,15 @@ Recommended.JsonInput.StringFieldSingleQuoteValue
Recommended.JsonInput.StringFieldSurrogateInWrongOrder
Recommended.JsonInput.StringFieldUnpairedHighSurrogate
Recommended.JsonInput.StringFieldUnpairedLowSurrogate
Recommended.JsonInput.StringFieldUppercaseEscapeLetter
Recommended.JsonInput.Uint32MapFieldKeyNotQuoted
Recommended.JsonInput.Uint64MapFieldKeyNotQuoted
Required.JsonInput.EnumFieldNotQuoted
Required.JsonInput.FieldNameInLowerCamelCase.Validator
Required.JsonInput.FieldNameInSnakeCase.JsonOutput
Required.JsonInput.FieldNameInSnakeCase.ProtobufOutput
Required.JsonInput.Int32FieldLeadingZero
Required.JsonInput.Int32FieldNegativeWithLeadingZero
Required.JsonInput.Int32FieldPlusSign
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
Required.JsonInput.StringFieldNotAString
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
Required.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE

View File

@ -1,18 +1,12 @@
Recommended.JsonInput.DoubleFieldInfinityNotQuoted
Recommended.JsonInput.DoubleFieldNanNotQuoted
Recommended.JsonInput.DoubleFieldNegativeInfinityNotQuoted
Recommended.JsonInput.FieldNameWithDoubleUnderscores.JsonOutput
Recommended.JsonInput.FieldNameWithDoubleUnderscores.ProtobufOutput
Recommended.JsonInput.FieldNameWithDoubleUnderscores.Validator
Recommended.JsonInput.FloatFieldInfinityNotQuoted
Recommended.JsonInput.FloatFieldNanNotQuoted
Recommended.JsonInput.FloatFieldNegativeInfinityNotQuoted
Required.JsonInput.BytesFieldInvalidBase64Characters
Required.JsonInput.DoubleFieldTooSmall
Required.JsonInput.EnumFieldUnknownValue.Validator
Required.JsonInput.FieldNameInLowerCamelCase.Validator
Required.JsonInput.FieldNameInSnakeCase.JsonOutput
Required.JsonInput.FieldNameInSnakeCase.ProtobufOutput
Required.JsonInput.FloatFieldTooLarge
Required.JsonInput.FloatFieldTooSmall
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool

View File

@ -10,18 +10,12 @@
Recommended.JsonInput.DoubleFieldInfinityNotQuoted
Recommended.JsonInput.DoubleFieldNanNotQuoted
Recommended.JsonInput.DoubleFieldNegativeInfinityNotQuoted
Recommended.JsonInput.FieldNameWithDoubleUnderscores.JsonOutput
Recommended.JsonInput.FieldNameWithDoubleUnderscores.ProtobufOutput
Recommended.JsonInput.FieldNameWithDoubleUnderscores.Validator
Recommended.JsonInput.FloatFieldInfinityNotQuoted
Recommended.JsonInput.FloatFieldNanNotQuoted
Recommended.JsonInput.FloatFieldNegativeInfinityNotQuoted
Required.JsonInput.BytesFieldInvalidBase64Characters
Required.JsonInput.DoubleFieldTooSmall
Required.JsonInput.EnumFieldUnknownValue.Validator
Required.JsonInput.FieldNameInLowerCamelCase.Validator
Required.JsonInput.FieldNameInSnakeCase.JsonOutput
Required.JsonInput.FieldNameInSnakeCase.ProtobufOutput
Required.JsonInput.FloatFieldTooLarge
Required.JsonInput.FloatFieldTooSmall
Required.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool

View File

@ -232,7 +232,7 @@ public abstract class AbstractParser<MessageType extends MessageLite>
}
size = CodedInputStream.readRawVarint32(firstByte, input);
} catch (IOException e) {
throw new InvalidProtocolBufferException(e.getMessage());
throw new InvalidProtocolBufferException(e);
}
InputStream limitedInput = new LimitedInputStream(input, size);
return parsePartialFrom(limitedInput, extensionRegistry);

View File

@ -51,14 +51,12 @@ import java.util.List;
import java.util.NoSuchElementException;
/**
* Immutable sequence of bytes. Substring is supported by sharing the reference
* to the immutable underlying bytes. Concatenation is likewise supported
* without copying (long strings) by building a tree of pieces in
* {@link RopeByteString}.
* <p>
* Like {@link String}, the contents of a {@link ByteString} can never be
* observed to change, not even in the presence of a data race or incorrect
* API usage in the client code.
* Immutable sequence of bytes. Substring is supported by sharing the reference to the immutable
* underlying bytes. Concatenation is likewise supported without copying (long strings) by building
* a tree of pieces in {@link RopeByteString}.
*
* <p>Like {@link String}, the contents of a {@link ByteString} can never be observed to change, not
* even in the presence of a data race or incorrect API usage in the client code.
*
* @author crazybob@google.com Bob Lee
* @author kenton@google.com Kenton Varda
@ -565,7 +563,9 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
// Create a balanced concatenation of the next "length" elements from the
// iterable.
private static ByteString balancedConcat(Iterator<ByteString> iterator, int length) {
assert length >= 1;
if (length < 1) {
throw new IllegalArgumentException(String.format("length (%s) must be >= 1", length));
}
ByteString result;
if (length == 1) {
result = iterator.next();

View File

@ -2123,7 +2123,7 @@ public final class Descriptors {
// Can't happen, because addPackage() only fails when the name
// conflicts with a non-package, but we have not yet added any
// non-packages at this point.
assert false;
throw new AssertionError(e);
}
}
}

View File

@ -297,7 +297,7 @@ public final class DynamicMessage extends AbstractMessage {
} catch (InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(builder.buildPartial());
} catch (IOException e) {
throw new InvalidProtocolBufferException(e.getMessage())
throw new InvalidProtocolBufferException(e)
.setUnfinishedMessage(builder.buildPartial());
}
return builder.buildPartial();

View File

@ -32,7 +32,6 @@ package com.google.protobuf;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;

View File

@ -105,9 +105,9 @@ public class ExtensionRegistryLite {
/**
* Construct a new, empty instance.
*
* <p>
* This may be an {@code ExtensionRegistry} if the full (non-Lite) proto libraries are available.
*
* <p>This may be an {@code ExtensionRegistry} if the full (non-Lite) proto libraries are
* available.
*/
public static ExtensionRegistryLite newInstance() {
return ExtensionRegistryFactory.create();
@ -121,6 +121,7 @@ public class ExtensionRegistryLite {
return ExtensionRegistryFactory.createEmpty();
}
/** Returns an unmodifiable view of the registry. */
public ExtensionRegistryLite getUnmodifiable() {
return new ExtensionRegistryLite(this);

View File

@ -39,7 +39,6 @@ import com.google.protobuf.Internal.IntList;
import com.google.protobuf.Internal.LongList;
import com.google.protobuf.Internal.ProtobufList;
import com.google.protobuf.WireFormat.FieldType;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectStreamException;
@ -479,7 +478,6 @@ public abstract class GeneratedMessageLite<
CodedInputStream input,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
int wireType = WireFormat.getTagWireType(tag);
int fieldNumber = WireFormat.getTagFieldNumber(tag);
// TODO(dweis): How much bytecode would be saved by not requiring the generated code to
@ -487,6 +485,17 @@ public abstract class GeneratedMessageLite<
GeneratedExtension<MessageType, ?> extension = extensionRegistry.findLiteExtensionByNumber(
defaultInstance, fieldNumber);
return parseExtension(input, extensionRegistry, extension, tag, fieldNumber);
}
private boolean parseExtension(
CodedInputStream input,
ExtensionRegistryLite extensionRegistry,
GeneratedExtension<?, ?> extension,
int tag,
int fieldNumber)
throws IOException {
int wireType = WireFormat.getTagWireType(tag);
boolean unknown = false;
boolean packed = false;
if (extension == null) {
@ -508,7 +517,7 @@ public abstract class GeneratedMessageLite<
if (unknown) { // Unknown field or wrong wire type. Skip.
return parseUnknownField(tag, input);
}
if (packed) {
int length = input.readRawVarint32();
int limit = input.pushLimit(length);
@ -587,9 +596,147 @@ public abstract class GeneratedMessageLite<
extension.singularToFieldSetType(value));
}
}
return true;
}
/**
* Parse an unknown field or an extension. For use by generated code only.
*
* <p>For use by generated code only.
*
* @return {@code true} unless the tag is an end-group tag.
*/
protected <MessageType extends MessageLite> boolean parseUnknownFieldAsMessageSet(
MessageType defaultInstance,
CodedInputStream input,
ExtensionRegistryLite extensionRegistry,
int tag)
throws IOException {
if (tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
mergeMessageSetExtensionFromCodedStream(defaultInstance, input, extensionRegistry);
return true;
}
// TODO(dweis): Do we really want to support non message set wire format in message sets?
// Full runtime does... So we do for now.
int wireType = WireFormat.getTagWireType(tag);
if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
return parseUnknownField(defaultInstance, input, extensionRegistry, tag);
} else {
// TODO(dweis): Should we throw on invalid input? Full runtime does not...
return input.skipField(tag);
}
}
/**
* Merges the message set from the input stream; requires message set wire format.
*
* @param defaultInstance the default instance of the containing message we are parsing in
* @param input the stream to parse from
* @param extensionRegistry the registry to use when parsing
*/
private <MessageType extends MessageLite> void mergeMessageSetExtensionFromCodedStream(
MessageType defaultInstance,
CodedInputStream input,
ExtensionRegistryLite extensionRegistry)
throws IOException {
// The wire format for MessageSet is:
// message MessageSet {
// repeated group Item = 1 {
// required int32 typeId = 2;
// required bytes message = 3;
// }
// }
// "typeId" is the extension's field number. The extension can only be
// a message type, where "message" contains the encoded bytes of that
// message.
//
// In practice, we will probably never see a MessageSet item in which
// the message appears before the type ID, or where either field does not
// appear exactly once. However, in theory such cases are valid, so we
// should be prepared to accept them.
int typeId = 0;
ByteString rawBytes = null; // If we encounter "message" before "typeId"
GeneratedExtension<?, ?> extension = null;
// Read bytes from input, if we get it's type first then parse it eagerly,
// otherwise we store the raw bytes in a local variable.
while (true) {
final int tag = input.readTag();
if (tag == 0) {
break;
}
if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
typeId = input.readUInt32();
if (typeId != 0) {
extension = extensionRegistry.findLiteExtensionByNumber(defaultInstance, typeId);
}
} else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
if (typeId != 0) {
if (extension != null) {
// We already know the type, so we can parse directly from the
// input with no copying. Hooray!
eagerlyMergeMessageSetExtension(input, extension, extensionRegistry, typeId);
rawBytes = null;
continue;
}
}
// We haven't seen a type ID yet or we want parse message lazily.
rawBytes = input.readBytes();
} else { // Unknown tag. Skip it.
if (!input.skipField(tag)) {
break; // End of group
}
}
}
input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
// Process the raw bytes.
if (rawBytes != null && typeId != 0) { // Zero is not a valid type ID.
if (extension != null) { // We known the type
mergeMessageSetExtensionFromBytes(rawBytes, extensionRegistry, extension);
} else { // We don't know how to parse this. Ignore it.
if (rawBytes != null) {
mergeLengthDelimitedField(typeId, rawBytes);
}
}
}
}
private void eagerlyMergeMessageSetExtension(
CodedInputStream input,
GeneratedExtension<?, ?> extension,
ExtensionRegistryLite extensionRegistry,
int typeId)
throws IOException {
int fieldNumber = typeId;
int tag = WireFormat.makeTag(typeId, WireFormat.WIRETYPE_LENGTH_DELIMITED);
parseExtension(input, extensionRegistry, extension, tag, fieldNumber);
}
private void mergeMessageSetExtensionFromBytes(
ByteString rawBytes,
ExtensionRegistryLite extensionRegistry,
GeneratedExtension<?, ?> extension)
throws IOException {
MessageLite.Builder subBuilder = null;
MessageLite existingValue = (MessageLite) extensions.getField(extension.descriptor);
if (existingValue != null) {
subBuilder = existingValue.toBuilder();
}
if (subBuilder == null) {
subBuilder = extension.getMessageDefaultInstance().newBuilderForType();
}
rawBytes.newCodedInput().readMessage(subBuilder, extensionRegistry);
MessageLite value = subBuilder.build();
extensions.setField(extension.descriptor, extension.singularToFieldSetType(value));
}
private void verifyExtensionContainingType(
final GeneratedExtension<MessageType, ?> extension) {
@ -807,14 +954,6 @@ public abstract class GeneratedMessageLite<
return instance.getExtension(extension, index);
}
// This is implemented here only to work around an apparent bug in the
// Java compiler and/or build system. See bug #1898463. The mere presence
// of this dummy clone() implementation makes it go away.
@Override
public BuilderType clone() {
return super.clone();
}
/** Set the value of an extension. */
public final <Type> BuilderType setExtension(
final ExtensionLite<MessageType, Type> extension,

View File

@ -36,6 +36,16 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.Descriptors.OneofDescriptor;
// In opensource protobuf, we have versioned this GeneratedMessageV3 class to GeneratedMessageV3V3 and
// in the future may have GeneratedMessageV3V4 etc. This allows us to change some aspects of this
// class without breaking binary compatibility with old generated code that still subclasses
// the old GeneratedMessageV3 class. To allow these different GeneratedMessageV3V? classes to
// interoperate (e.g., a GeneratedMessageV3V3 object has a message extension field whose class
// type is GeneratedMessageV3V4), these classes still share a common parent class AbstarctMessage
// and are using the same GeneratedMessage.GeneratedExtension class for extension definitions.
// Since this class becomes GeneratedMessageV3V? in opensource, we have to add an import here
// to be able to use GeneratedMessage.GeneratedExtension. The GeneratedExtension definition in
// this file is also excluded from opensource to avoid conflict.
import com.google.protobuf.GeneratedMessage.GeneratedExtension;
import java.io.IOException;
@ -1207,14 +1217,6 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
return super.clear();
}
// This is implemented here only to work around an apparent bug in the
// Java compiler and/or build system. See bug #1898463. The mere presence
// of this clone() implementation makes it go away.
@Override
public BuilderType clone() {
return super.clone();
}
private void ensureExtensionsIsMutable() {
if (extensions.isImmutable()) {
extensions = extensions.clone();
@ -1610,6 +1612,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
FieldDescriptor getDescriptor();
}
// =================================================================
/** Calls Class.getMethod and throws a RuntimeException if it fails. */
@ -1705,11 +1708,6 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
initialized = false;
}
private boolean isMapFieldEnabled(FieldDescriptor field) {
boolean result = true;
return result;
}
/**
* Ensures the field accessors are initialized. This method is thread-safe.
*
@ -1733,7 +1731,7 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
}
if (field.isRepeated()) {
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
if (field.isMapField() && isMapFieldEnabled(field)) {
if (field.isMapField()) {
fields[i] = new MapFieldAccessor(
field, camelCaseNames[i], messageClass, builderClass);
} else {

View File

@ -284,29 +284,8 @@ public class LazyFieldLite {
return;
}
// At this point we have two fully parsed messages. We can't merge directly from one to the
// other because only generated builder code contains methods to mergeFrom another parsed
// message. We have to serialize one instance and then merge the bytes into the other. This may
// drop extensions from one of the messages if one of the values had an extension set on it
// directly.
//
// To mitigate this we prefer serializing a message that has an extension registry, and
// therefore a chance that all extensions set on it are in that registry.
//
// NOTE: The check for other.extensionRegistry not being null must come first because at this
// point in time if other.extensionRegistry is not null then this.extensionRegistry will not be
// null either.
if (other.extensionRegistry != null) {
setValue(mergeValueAndBytes(this.value, other.toByteString(), other.extensionRegistry));
return;
} else if (this.extensionRegistry != null) {
setValue(mergeValueAndBytes(other.value, this.toByteString(), this.extensionRegistry));
return;
} else {
// All extensions from the other message will be dropped because we have no registry.
setValue(mergeValueAndBytes(this.value, other.toByteString(), EMPTY_REGISTRY));
return;
}
// At this point we have two fully parsed messages.
setValue(this.value.toBuilder().mergeFrom(other.value).build());
}
/**

View File

@ -109,7 +109,7 @@ public final class MapEntry<K, V> extends AbstractMessage {
} catch (InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(this);
} catch (IOException e) {
throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(this);
throw new InvalidProtocolBufferException(e).setUnfinishedMessage(this);
}
}

View File

@ -95,7 +95,7 @@ final class MessageLiteToString {
// Try to reflectively get the value and toString() the field as if it were repeated. This
// only works if the method names have not be proguarded out or renamed.
Method listMethod = nameToNoArgMethod.get("get" + suffix);
if (listMethod != null) {
if (listMethod != null && listMethod.getReturnType().equals(List.class)) {
printField(
buffer,
indent,
@ -115,7 +115,7 @@ final class MessageLiteToString {
// Heuristic to skip bytes based accessors for string fields.
continue;
}
String camelCase = suffix.substring(0, 1).toLowerCase() + suffix.substring(1);
// Try to reflectively get the value and toString() the field as if it were optional. This

View File

@ -1022,7 +1022,7 @@ public final class UnknownFieldSet implements MessageLite {
} catch (InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(builder.buildPartial());
} catch (IOException e) {
throw new InvalidProtocolBufferException(e.getMessage())
throw new InvalidProtocolBufferException(e)
.setUnfinishedMessage(builder.buildPartial());
}
return builder.buildPartial();

View File

@ -175,6 +175,41 @@ public final class UnknownFieldSetLite {
}
}
/**
* Serializes the set and writes it to {@code output} using {@code MessageSet} wire format.
*
* <p>For use by generated code only.
*/
public void writeAsMessageSetTo(CodedOutputStream output) throws IOException {
for (int i = 0; i < count; i++) {
int fieldNumber = WireFormat.getTagFieldNumber(tags[i]);
output.writeRawMessageSetExtension(fieldNumber, (ByteString) objects[i]);
}
}
/**
* Get the number of bytes required to encode this field, including field
* number, using {@code MessageSet} wire format.
*/
public int getSerializedSizeAsMessageSet() {
int size = memoizedSerializedSize;
if (size != -1) {
return size;
}
size = 0;
for (int i = 0; i < count; i++) {
int tag = tags[i];
int fieldNumber = WireFormat.getTagFieldNumber(tag);
size += CodedOutputStream.computeRawMessageSetExtensionSize(
fieldNumber, (ByteString) objects[i]);
}
memoizedSerializedSize = size;
return size;
}
/**
* Get the number of bytes required to encode this set.
*
@ -268,7 +303,8 @@ public final class UnknownFieldSetLite {
}
}
private void storeField(int tag, Object value) {
// Package private for unsafe experimental runtime.
void storeField(int tag, Object value) {
ensureCapacity();
tags[count] = tag;

View File

@ -31,7 +31,6 @@
package com.google.protobuf;
import static protobuf_unittest.UnittestProto.optionalInt32Extension;
import static protobuf_unittest.UnittestProto.optionalInt64Extension;
import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestAllTypes;
@ -219,29 +218,6 @@ public class LazyFieldLiteTest extends TestCase {
assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
}
public void testMergeMightLoseExtensions() throws Exception {
// Test that we don't know about the extensions when parsing.
TestAllExtensions message1 =
TestAllExtensions.newBuilder().setExtension(optionalInt32Extension, 1).build();
TestAllExtensions message2 =
TestAllExtensions.newBuilder().setExtension(optionalInt64Extension, 2L).build();
LazyFieldLite field = LazyFieldLite.fromValue(message1);
field.merge(LazyFieldLite.fromValue(message2));
// We lose the extensions from message 2 because we have to serialize it and then parse it
// again, using the empty registry this time.
TestAllExtensions value =
(TestAllExtensions) field.getValue(TestAllExtensions.getDefaultInstance());
assertTrue(value.hasExtension(optionalInt32Extension));
assertEquals(Integer.valueOf(1), value.getExtension(optionalInt32Extension));
assertFalse(value.hasExtension(optionalInt64Extension));
// The field is still there, it is just unknown.
assertTrue(value.getUnknownFields()
.hasField(optionalInt64Extension.getDescriptor().getNumber()));
}
// Help methods.

View File

@ -101,6 +101,19 @@ public class LazyMessageLiteTest extends TestCase {
assertEquals(119, outer.getRepeatedInner(0).getNum());
assertEquals(122, outer.getRepeatedInner(1).getNum());
}
public void testRepeatedMutability() throws Exception {
LazyMessageLite outer = LazyMessageLite.newBuilder()
.addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119))
.addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122))
.build();
outer = LazyMessageLite.parseFrom(outer.toByteArray());
try {
outer.getRepeatedInnerList().set(1, null);
fail();
} catch (UnsupportedOperationException expected) {}
}
public void testAddAll() {
ArrayList<LazyInnerMessageLite> inners = new ArrayList<LazyInnerMessageLite>();

View File

@ -45,6 +45,7 @@ import com.google.protobuf.UnittestLite.TestAllTypesLite.OneofFieldCase;
import com.google.protobuf.UnittestLite.TestAllTypesLite.OptionalGroup;
import com.google.protobuf.UnittestLite.TestAllTypesLite.RepeatedGroup;
import com.google.protobuf.UnittestLite.TestAllTypesLiteOrBuilder;
import com.google.protobuf.UnittestLite.TestHugeFieldNumbersLite;
import com.google.protobuf.UnittestLite.TestNestedExtensionLite;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar;
import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.BarPrime;
@ -1424,6 +1425,12 @@ public class LiteTest extends TestCase {
assertToStringEquals("", TestAllTypesLite.getDefaultInstance());
}
public void testToStringScalarFieldsSuffixedWithList() throws Exception {
assertToStringEquals("deceptively_named_list: 7", TestAllTypesLite.newBuilder()
.setDeceptivelyNamedList(7)
.build());
}
public void testToStringPrimitives() throws Exception {
TestAllTypesLite proto = TestAllTypesLite.newBuilder()
.setOptionalInt32(1)
@ -2235,6 +2242,25 @@ public class LiteTest extends TestCase {
assertFalse(other.equals(mine));
}
public void testHugeFieldNumbers() throws InvalidProtocolBufferException {
TestHugeFieldNumbersLite message =
TestHugeFieldNumbersLite.newBuilder()
.setOptionalInt32(1)
.addRepeatedInt32(2)
.setOptionalEnum(ForeignEnumLite.FOREIGN_LITE_FOO)
.setOptionalString("xyz")
.setOptionalMessage(ForeignMessageLite.newBuilder().setC(3).build())
.build();
TestHugeFieldNumbersLite parsedMessage =
TestHugeFieldNumbersLite.parseFrom(message.toByteArray());
assertEquals(1, parsedMessage.getOptionalInt32());
assertEquals(2, parsedMessage.getRepeatedInt32(0));
assertEquals(ForeignEnumLite.FOREIGN_LITE_FOO, parsedMessage.getOptionalEnum());
assertEquals("xyz", parsedMessage.getOptionalString());
assertEquals(3, parsedMessage.getOptionalMessage().getC());
}
private void assertEqualsAndHashCodeAreFalse(Object o1, Object o2) {
assertFalse(o1.equals(o2));
assertFalse(o1.hashCode() == o2.hashCode());

View File

@ -501,7 +501,6 @@ public final class MapForProto2LiteTest extends TestCase {
assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
}
public void testIterationOrder() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValues(builder);

View File

@ -58,26 +58,26 @@ public class MapForProto2Test extends TestCase {
builder.getMutableInt32ToInt32Field().put(1, 11);
builder.getMutableInt32ToInt32Field().put(2, 22);
builder.getMutableInt32ToInt32Field().put(3, 33);
//
builder.getMutableInt32ToStringField().put(1, "11");
builder.getMutableInt32ToStringField().put(2, "22");
builder.getMutableInt32ToStringField().put(3, "33");
//
builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
//
builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
//
builder.getMutableInt32ToMessageField().put(
1, MessageValue.newBuilder().setValue(11).build());
builder.getMutableInt32ToMessageField().put(
2, MessageValue.newBuilder().setValue(22).build());
builder.getMutableInt32ToMessageField().put(
3, MessageValue.newBuilder().setValue(33).build());
//
builder.getMutableStringToInt32Field().put("1", 11);
builder.getMutableStringToInt32Field().put("2", 22);
builder.getMutableStringToInt32Field().put("3", 33);
@ -120,6 +120,7 @@ public class MapForProto2Test extends TestCase {
setMapValuesUsingAccessors(usingAccessorsBuilder);
TestMap usingAccessors = usingAccessorsBuilder.build();
assertMapValuesSet(usingAccessors);
assertEquals(usingAccessors, usingMutableMap);
}
@ -169,25 +170,25 @@ public class MapForProto2Test extends TestCase {
builder.getMutableInt32ToInt32Field().put(1, 111);
builder.getMutableInt32ToInt32Field().remove(2);
builder.getMutableInt32ToInt32Field().put(4, 44);
//
builder.getMutableInt32ToStringField().put(1, "111");
builder.getMutableInt32ToStringField().remove(2);
builder.getMutableInt32ToStringField().put(4, "44");
//
builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
builder.getMutableInt32ToBytesField().remove(2);
builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
//
builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
builder.getMutableInt32ToEnumField().remove(2);
builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
//
builder.getMutableInt32ToMessageField().put(
1, MessageValue.newBuilder().setValue(111).build());
builder.getMutableInt32ToMessageField().remove(2);
builder.getMutableInt32ToMessageField().put(
4, MessageValue.newBuilder().setValue(44).build());
//
builder.getMutableStringToInt32Field().put("1", 111);
builder.getMutableStringToInt32Field().remove("2");
builder.getMutableStringToInt32Field().put("4", 44);
@ -230,8 +231,9 @@ public class MapForProto2Test extends TestCase {
setMapValuesUsingAccessors(usingAccessorsBuilder);
TestMap usingAccessors = usingAccessorsBuilder.build();
assertMapValuesSet(usingAccessors);
assertEquals(usingAccessors, usingMutableMap);
assertEquals(usingAccessors, usingMutableMap);
//
usingMutableMapBuilder = usingMutableMap.toBuilder();
updateMapValuesUsingMutableMap(usingMutableMapBuilder);
usingMutableMap = usingMutableMapBuilder.build();
@ -335,7 +337,7 @@ public class MapForProto2Test extends TestCase {
assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
builder.getMutableInt32ToInt32Field().put(2, 3);
assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
//
Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
enumMap.put(1, TestMap.EnumValue.BAR);
assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
@ -350,7 +352,7 @@ public class MapForProto2Test extends TestCase {
assertEquals(
newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
builder.getInt32ToEnumField());
//
Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
stringMap.put(1, "1");
assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
@ -365,7 +367,7 @@ public class MapForProto2Test extends TestCase {
assertEquals(
newMap(1, "1", 2, "2"),
builder.getInt32ToStringField());
//
Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
@ -384,7 +386,7 @@ public class MapForProto2Test extends TestCase {
2, TestMap.MessageValue.getDefaultInstance()),
builder.getInt32ToMessageField());
}
//
public void testMutableMapLifecycle_collections() {
TestMap.Builder builder = TestMap.newBuilder();
Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
@ -431,18 +433,19 @@ public class MapForProto2Test extends TestCase {
assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
}
public void testGettersAndSetters() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
TestMap message = builder.build();
assertMapValuesCleared(message);
builder = message.toBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
message = builder.build();
assertMapValuesSet(message);
builder = message.toBuilder();
updateMapValuesUsingMutableMap(builder);
updateMapValuesUsingAccessors(builder);
message = builder.build();
assertMapValuesUpdated(message);
@ -455,7 +458,7 @@ public class MapForProto2Test extends TestCase {
public void testPutAll() throws Exception {
TestMap.Builder sourceBuilder = TestMap.newBuilder();
setMapValuesUsingMutableMap(sourceBuilder);
setMapValuesUsingAccessors(sourceBuilder);
TestMap source = sourceBuilder.build();
assertMapValuesSet(source);
@ -507,14 +510,14 @@ public class MapForProto2Test extends TestCase {
public void testSerializeAndParse() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
TestMap message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesSet(message);
builder = message.toBuilder();
updateMapValuesUsingMutableMap(builder);
updateMapValuesUsingAccessors(builder);
message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
message = TestMap.parser().parseFrom(message.toByteString());
@ -579,7 +582,7 @@ public class MapForProto2Test extends TestCase {
public void testMergeFrom() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
TestMap message = builder.build();
TestMap.Builder other = TestMap.newBuilder();
@ -594,22 +597,22 @@ public class MapForProto2Test extends TestCase {
// We can't control the order of elements in a HashMap. The best we can do
// here is to add elements in different order.
TestMap.Builder b1 = TestMap.newBuilder();
b1.getMutableInt32ToInt32Field().put(1, 2);
b1.getMutableInt32ToInt32Field().put(3, 4);
b1.getMutableInt32ToInt32Field().put(5, 6);
b1.putInt32ToInt32Field(1, 2);
b1.putInt32ToInt32Field(3, 4);
b1.putInt32ToInt32Field(5, 6);
TestMap m1 = b1.build();
TestMap.Builder b2 = TestMap.newBuilder();
b2.getMutableInt32ToInt32Field().put(5, 6);
b2.getMutableInt32ToInt32Field().put(1, 2);
b2.getMutableInt32ToInt32Field().put(3, 4);
b2.putInt32ToInt32Field(5, 6);
b2.putInt32ToInt32Field(1, 2);
b2.putInt32ToInt32Field(3, 4);
TestMap m2 = b2.build();
assertEquals(m1, m2);
assertEquals(m1.hashCode(), m2.hashCode());
// Make sure we did compare map fields.
b2.getMutableInt32ToInt32Field().put(1, 0);
b2.putInt32ToInt32Field(1, 0);
m2 = b2.build();
assertFalse(m1.equals(m2));
// Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
@ -684,13 +687,11 @@ public class MapForProto2Test extends TestCase {
public void testReflectionApi() throws Exception {
// In reflection API, map fields are just repeated message fields.
TestMap.Builder builder = TestMap.newBuilder();
builder.getMutableInt32ToInt32Field().put(1, 2);
builder.getMutableInt32ToInt32Field().put(3, 4);
builder.getMutableInt32ToMessageField().put(
11, MessageValue.newBuilder().setValue(22).build());
builder.getMutableInt32ToMessageField().put(
33, MessageValue.newBuilder().setValue(44).build());
TestMap.Builder builder = TestMap.newBuilder()
.putInt32ToInt32Field(1, 2)
.putInt32ToInt32Field(3, 4)
.putInt32ToMessageField(11, MessageValue.newBuilder().setValue(22).build())
.putInt32ToMessageField(33, MessageValue.newBuilder().setValue(44).build());
TestMap message = builder.build();
// Test getField(), getRepeatedFieldCount(), getRepeatedField().
@ -760,7 +761,7 @@ public class MapForProto2Test extends TestCase {
public void testTextFormat() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
TestMap message = builder.build();
String textData = TextFormat.printToString(message);
@ -774,7 +775,7 @@ public class MapForProto2Test extends TestCase {
public void testDynamicMessage() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
TestMap message = builder.build();
Message dynamicDefaultInstance =
@ -819,10 +820,9 @@ public class MapForProto2Test extends TestCase {
}
public void testUnknownEnumValues() throws Exception {
TestUnknownEnumValue.Builder builder =
TestUnknownEnumValue.newBuilder();
builder.getMutableInt32ToInt32Field().put(1, 1);
builder.getMutableInt32ToInt32Field().put(2, 54321);
TestUnknownEnumValue.Builder builder = TestUnknownEnumValue.newBuilder()
.putInt32ToInt32Field(1, 1)
.putInt32ToInt32Field(2, 54321);
ByteString data = builder.build().toByteString();
TestMap message = TestMap.parseFrom(data);
@ -841,26 +841,21 @@ public class MapForProto2Test extends TestCase {
assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
}
public void testRequiredMessage() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
builder.getMutableRequiredMessageMap().put(0,
MessageWithRequiredFields.newBuilder().buildPartial());
builder.putRequiredMessageMap(0, MessageWithRequiredFields.newBuilder().buildPartial());
TestMap message = builder.buildPartial();
assertFalse(message.isInitialized());
builder.getMutableRequiredMessageMap().put(0,
MessageWithRequiredFields.newBuilder().setValue(1).build());
builder.putRequiredMessageMap(0, MessageWithRequiredFields.newBuilder().setValue(1).build());
message = builder.build();
assertTrue(message.isInitialized());
}
public void testRecursiveMap() throws Exception {
TestRecursiveMap.Builder builder = TestRecursiveMap.newBuilder();
builder.getMutableRecursiveMapField().put(
1, TestRecursiveMap.newBuilder().setValue(2).build());
builder.getMutableRecursiveMapField().put(
3, TestRecursiveMap.newBuilder().setValue(4).build());
builder.putRecursiveMapField(1, TestRecursiveMap.newBuilder().setValue(2).build());
builder.putRecursiveMapField(3, TestRecursiveMap.newBuilder().setValue(4).build());
ByteString data = builder.build().toByteString();
TestRecursiveMap message = TestRecursiveMap.parseFrom(data);
@ -870,7 +865,7 @@ public class MapForProto2Test extends TestCase {
public void testIterationOrder() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
TestMap message = builder.build();
assertEquals(Arrays.asList("1", "2", "3"),
@ -879,7 +874,7 @@ public class MapForProto2Test extends TestCase {
public void testContains() {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
assertMapContainsSetValues(builder);
assertMapContainsSetValues(builder.build());
}
@ -920,7 +915,7 @@ public class MapForProto2Test extends TestCase {
TestMap.Builder builder = TestMap.newBuilder();
assertMapCounts(0, builder);
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
assertMapCounts(3, builder);
TestMap message = builder.build();
@ -1091,7 +1086,7 @@ public class MapForProto2Test extends TestCase {
public void testRemove() {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1));
for (int times = 0; times < 2; times++) {
builder.removeInt32ToInt32Field(1);
@ -1137,7 +1132,7 @@ public class MapForProto2Test extends TestCase {
map_test.Message1.Builder builder =
map_test.Message1.newBuilder();
builder.getMutableMapField().put("key", true);
builder.putMapField("key", true);
map_test.Message1 message = builder.build();
Message mapEntry = (Message) message.getRepeatedField(
message.getDescriptorForType().findFieldByName("map_field"), 0);

View File

@ -60,26 +60,26 @@ public class MapTest extends TestCase {
builder.getMutableInt32ToInt32Field().put(1, 11);
builder.getMutableInt32ToInt32Field().put(2, 22);
builder.getMutableInt32ToInt32Field().put(3, 33);
//
builder.getMutableInt32ToStringField().put(1, "11");
builder.getMutableInt32ToStringField().put(2, "22");
builder.getMutableInt32ToStringField().put(3, "33");
//
builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
//
builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
//
builder.getMutableInt32ToMessageField().put(
1, MessageValue.newBuilder().setValue(11).build());
builder.getMutableInt32ToMessageField().put(
2, MessageValue.newBuilder().setValue(22).build());
builder.getMutableInt32ToMessageField().put(
3, MessageValue.newBuilder().setValue(33).build());
//
builder.getMutableStringToInt32Field().put("1", 11);
builder.getMutableStringToInt32Field().put("2", 22);
builder.getMutableStringToInt32Field().put("3", 33);
@ -122,6 +122,7 @@ public class MapTest extends TestCase {
setMapValuesUsingAccessors(usingAccessorsBuilder);
TestMap usingAccessors = usingAccessorsBuilder.build();
assertMapValuesSet(usingAccessors);
assertEquals(usingAccessors, usingMutableMap);
}
@ -171,25 +172,25 @@ public class MapTest extends TestCase {
builder.getMutableInt32ToInt32Field().put(1, 111);
builder.getMutableInt32ToInt32Field().remove(2);
builder.getMutableInt32ToInt32Field().put(4, 44);
//
builder.getMutableInt32ToStringField().put(1, "111");
builder.getMutableInt32ToStringField().remove(2);
builder.getMutableInt32ToStringField().put(4, "44");
//
builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
builder.getMutableInt32ToBytesField().remove(2);
builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
//
builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
builder.getMutableInt32ToEnumField().remove(2);
builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
//
builder.getMutableInt32ToMessageField().put(
1, MessageValue.newBuilder().setValue(111).build());
builder.getMutableInt32ToMessageField().remove(2);
builder.getMutableInt32ToMessageField().put(
4, MessageValue.newBuilder().setValue(44).build());
//
builder.getMutableStringToInt32Field().put("1", 111);
builder.getMutableStringToInt32Field().remove("2");
builder.getMutableStringToInt32Field().put("4", 44);
@ -232,8 +233,9 @@ public class MapTest extends TestCase {
setMapValuesUsingAccessors(usingAccessorsBuilder);
TestMap usingAccessors = usingAccessorsBuilder.build();
assertMapValuesSet(usingAccessors);
assertEquals(usingAccessors, usingMutableMap);
assertEquals(usingAccessors, usingMutableMap);
//
usingMutableMapBuilder = usingMutableMap.toBuilder();
updateMapValuesUsingMutableMap(usingMutableMapBuilder);
usingMutableMap = usingMutableMapBuilder.build();
@ -337,7 +339,7 @@ public class MapTest extends TestCase {
assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
builder.getMutableInt32ToInt32Field().put(2, 3);
assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
//
Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
enumMap.put(1, TestMap.EnumValue.BAR);
assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
@ -352,7 +354,7 @@ public class MapTest extends TestCase {
assertEquals(
newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
builder.getInt32ToEnumField());
//
Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
stringMap.put(1, "1");
assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
@ -363,11 +365,11 @@ public class MapTest extends TestCase {
// expected
}
assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
builder.getMutableInt32ToStringField().put(2, "2");
builder.putInt32ToStringField(2, "2");
assertEquals(
newMap(1, "1", 2, "2"),
builder.getInt32ToStringField());
//
Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
@ -380,13 +382,13 @@ public class MapTest extends TestCase {
}
assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
builder.getInt32ToMessageField());
builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance());
builder.putInt32ToMessageField(2, TestMap.MessageValue.getDefaultInstance());
assertEquals(
newMap(1, TestMap.MessageValue.getDefaultInstance(),
2, TestMap.MessageValue.getDefaultInstance()),
builder.getInt32ToMessageField());
}
//
public void testMutableMapLifecycle_collections() {
TestMap.Builder builder = TestMap.newBuilder();
Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
@ -433,18 +435,19 @@ public class MapTest extends TestCase {
assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
}
public void testGettersAndSetters() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
TestMap message = builder.build();
assertMapValuesCleared(message);
builder = message.toBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
message = builder.build();
assertMapValuesSet(message);
builder = message.toBuilder();
updateMapValuesUsingMutableMap(builder);
updateMapValuesUsingAccessors(builder);
message = builder.build();
assertMapValuesUpdated(message);
@ -457,7 +460,7 @@ public class MapTest extends TestCase {
public void testPutAll() throws Exception {
TestMap.Builder sourceBuilder = TestMap.newBuilder();
setMapValuesUsingMutableMap(sourceBuilder);
setMapValuesUsingAccessors(sourceBuilder);
TestMap source = sourceBuilder.build();
assertMapValuesSet(source);
@ -467,15 +470,16 @@ public class MapTest extends TestCase {
}
public void testPutAllForUnknownEnumValues() throws Exception {
TestMap.Builder sourceBuilder = TestMap.newBuilder();
sourceBuilder.getMutableInt32ToEnumFieldValue().put(0, 0);
sourceBuilder.getMutableInt32ToEnumFieldValue().put(1, 1);
sourceBuilder.getMutableInt32ToEnumFieldValue().put(2, 1000); // unknown value.
TestMap source = sourceBuilder.build();
TestMap source = TestMap.newBuilder()
.putAllInt32ToEnumFieldValue(newMap(
0, 0,
1, 1,
2, 1000)) // unknown value.
.build();
TestMap.Builder destinationBuilder = TestMap.newBuilder();
destinationBuilder.putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue());
TestMap destination = destinationBuilder.build();
TestMap destination = TestMap.newBuilder()
.putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue())
.build();
assertEquals(0, destination.getInt32ToEnumFieldValue().get(0).intValue());
assertEquals(1, destination.getInt32ToEnumFieldValue().get(1).intValue());
@ -542,14 +546,14 @@ public class MapTest extends TestCase {
public void testSerializeAndParse() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
TestMap message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesSet(message);
builder = message.toBuilder();
updateMapValuesUsingMutableMap(builder);
updateMapValuesUsingAccessors(builder);
message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
message = TestMap.parser().parseFrom(message.toByteString());
@ -614,7 +618,7 @@ public class MapTest extends TestCase {
public void testMergeFrom() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
TestMap message = builder.build();
TestMap.Builder other = TestMap.newBuilder();
@ -628,23 +632,23 @@ public class MapTest extends TestCase {
// We can't control the order of elements in a HashMap. The best we can do
// here is to add elements in different order.
TestMap.Builder b1 = TestMap.newBuilder();
b1.getMutableInt32ToInt32Field().put(1, 2);
b1.getMutableInt32ToInt32Field().put(3, 4);
b1.getMutableInt32ToInt32Field().put(5, 6);
TestMap.Builder b1 = TestMap.newBuilder()
.putInt32ToInt32Field(1, 2)
.putInt32ToInt32Field(3, 4)
.putInt32ToInt32Field(5, 6);
TestMap m1 = b1.build();
TestMap.Builder b2 = TestMap.newBuilder();
b2.getMutableInt32ToInt32Field().put(5, 6);
b2.getMutableInt32ToInt32Field().put(1, 2);
b2.getMutableInt32ToInt32Field().put(3, 4);
TestMap.Builder b2 = TestMap.newBuilder()
.putInt32ToInt32Field(5, 6)
.putInt32ToInt32Field(1, 2)
.putInt32ToInt32Field(3, 4);
TestMap m2 = b2.build();
assertEquals(m1, m2);
assertEquals(m1.hashCode(), m2.hashCode());
// Make sure we did compare map fields.
b2.getMutableInt32ToInt32Field().put(1, 0);
b2.putInt32ToInt32Field(1, 0);
m2 = b2.build();
assertFalse(m1.equals(m2));
// Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
@ -652,7 +656,7 @@ public class MapTest extends TestCase {
// Regression test for b/18549190: if a map is a subset of the other map,
// equals() should return false.
b2.getMutableInt32ToInt32Field().remove(1);
b2.removeInt32ToInt32Field(1);
m2 = b2.build();
assertFalse(m1.equals(m2));
assertFalse(m2.equals(m1));
@ -661,20 +665,19 @@ public class MapTest extends TestCase {
public void testNestedBuilderOnChangeEventPropagation() {
TestOnChangeEventPropagation.Builder parent =
TestOnChangeEventPropagation.newBuilder();
parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 2);
parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 2);
TestOnChangeEventPropagation message = parent.build();
assertEquals(2, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
// Make a change using nested builder.
parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 3);
parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 3);
// Should be able to observe the change.
message = parent.build();
assertEquals(3, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
// Make another change using mergeFrom()
TestMap.Builder other = TestMap.newBuilder();
other.getMutableInt32ToInt32Field().put(1, 4);
TestMap.Builder other = TestMap.newBuilder().putInt32ToInt32Field(1, 4);
parent.getOptionalMessageBuilder().mergeFrom(other.build());
// Should be able to observe the change.
@ -697,8 +700,7 @@ public class MapTest extends TestCase {
TestMap.Builder testMapBuilder = parentBuilder.getOptionalMessageBuilder();
// Create a map entry message.
TestMap.Builder entryBuilder = TestMap.newBuilder();
entryBuilder.getMutableInt32ToInt32Field().put(1, 1);
TestMap.Builder entryBuilder = TestMap.newBuilder().putInt32ToInt32Field(1, 1);
// Put the entry into the nested builder.
testMapBuilder.addRepeatedField(
@ -709,7 +711,7 @@ public class MapTest extends TestCase {
assertEquals(1, message.getOptionalMessage().getInt32ToInt32Field().size());
// Change the entry value.
entryBuilder.getMutableInt32ToInt32Field().put(1, 4);
entryBuilder.putInt32ToInt32Field(1, 4);
testMapBuilder = parentBuilder.getOptionalMessageBuilder();
testMapBuilder.setRepeatedField(
intMapField, 0, entryBuilder.getRepeatedField(intMapField, 0));
@ -796,13 +798,11 @@ public class MapTest extends TestCase {
public void testReflectionApi() throws Exception {
// In reflection API, map fields are just repeated message fields.
TestMap.Builder builder = TestMap.newBuilder();
builder.getMutableInt32ToInt32Field().put(1, 2);
builder.getMutableInt32ToInt32Field().put(3, 4);
builder.getMutableInt32ToMessageField().put(
11, MessageValue.newBuilder().setValue(22).build());
builder.getMutableInt32ToMessageField().put(
33, MessageValue.newBuilder().setValue(44).build());
TestMap.Builder builder = TestMap.newBuilder()
.putInt32ToInt32Field(1, 2)
.putInt32ToInt32Field(3, 4)
.putInt32ToMessageField(11, MessageValue.newBuilder().setValue(22).build())
.putInt32ToMessageField(33, MessageValue.newBuilder().setValue(44).build());
TestMap message = builder.build();
// Test getField(), getRepeatedFieldCount(), getRepeatedField().
@ -872,7 +872,7 @@ public class MapTest extends TestCase {
public void testTextFormat() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
TestMap message = builder.build();
String textData = TextFormat.printToString(message);
@ -886,7 +886,7 @@ public class MapTest extends TestCase {
public void testDynamicMessage() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
TestMap message = builder.build();
Message dynamicDefaultInstance =
@ -931,10 +931,11 @@ public class MapTest extends TestCase {
}
public void testUnknownEnumValues() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
builder.getMutableInt32ToEnumFieldValue().put(0, 0);
builder.getMutableInt32ToEnumFieldValue().put(1, 1);
builder.getMutableInt32ToEnumFieldValue().put(2, 1000); // unknown value.
TestMap.Builder builder = TestMap.newBuilder()
.putAllInt32ToEnumFieldValue(newMap(
0, 0,
1, 1,
2, 1000)); // unknown value.
TestMap message = builder.build();
assertEquals(TestMap.EnumValue.FOO,
@ -957,7 +958,7 @@ public class MapTest extends TestCase {
assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
// hashCode()/equals() should take unknown enum values into account.
builder.getMutableInt32ToEnumFieldValue().put(2, 1001);
builder.putAllInt32ToEnumFieldValue(newMap(2, 1001));
TestMap message2 = builder.build();
assertFalse(message.hashCode() == message2.hashCode());
assertFalse(message.equals(message2));
@ -971,15 +972,13 @@ public class MapTest extends TestCase {
EnumDescriptor enumDescriptor = TestMap.EnumValue.getDescriptor();
FieldDescriptor field = descriptor.findFieldByName("int32_to_enum_field");
Map<Integer, Integer> data = new HashMap<Integer, Integer>();
data.put(0, 0);
data.put(1, 1);
data.put(2, 1000); // unknown value.
Map<Integer, Integer> data = newMap(
0, 0,
1, 1,
2, 1000); // unknown value
TestMap.Builder builder = TestMap.newBuilder();
for (Map.Entry<Integer, Integer> entry : data.entrySet()) {
builder.getMutableInt32ToEnumFieldValue().put(entry.getKey(), entry.getValue());
}
TestMap.Builder builder = TestMap.newBuilder()
.putAllInt32ToEnumFieldValue(data);
// Try to read unknown enum values using reflection API.
for (int i = 0; i < builder.getRepeatedFieldCount(field); i++) {
@ -1003,7 +1002,7 @@ public class MapTest extends TestCase {
public void testIterationOrder() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
TestMap message = builder.build();
assertEquals(Arrays.asList("1", "2", "3"),
@ -1012,7 +1011,7 @@ public class MapTest extends TestCase {
public void testGetMap() {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
TestMap message = builder.build();
assertEquals(
message.getStringToInt32Field(),
@ -1033,7 +1032,7 @@ public class MapTest extends TestCase {
public void testContains() {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
assertMapContainsSetValues(builder);
assertMapContainsSetValues(builder.build());
}
@ -1074,7 +1073,7 @@ public class MapTest extends TestCase {
TestMap.Builder builder = TestMap.newBuilder();
assertMapCounts(0, builder);
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
assertMapCounts(3, builder);
TestMap message = builder.build();
@ -1269,7 +1268,7 @@ public class MapTest extends TestCase {
public void testRemove() {
TestMap.Builder builder = TestMap.newBuilder();
setMapValuesUsingMutableMap(builder);
setMapValuesUsingAccessors(builder);
assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1));
for (int times = 0; times < 2; times++) {
builder.removeInt32ToInt32Field(1);
@ -1485,4 +1484,12 @@ public class MapTest extends TestCase {
map.put(key2, value2);
return map;
}
private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2, K key3, V value3) {
Map<K, V> map = new HashMap<K, V>();
map.put(key1, value1);
map.put(key2, value2);
map.put(key3, value3);
return map;
}
}

View File

@ -46,6 +46,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import junit.framework.TestCase;
/**
@ -372,4 +373,43 @@ public class ParserTest extends TestCase {
assertEquals(3, parsingMerge.getExtensionCount(
TestParsingMergeLite.repeatedExt));
}
public void testParseDelimitedFrom_firstByteInterrupted_preservesCause() {
try {
TestUtil.getAllSet().parseDelimitedFrom(
new InputStream() {
@Override
public int read() throws IOException {
throw new InterruptedIOException();
}
});
fail("Expected InterruptedIOException");
} catch (Exception e) {
assertEquals(InterruptedIOException.class, e.getClass());
}
}
public void testParseDelimitedFrom_secondByteInterrupted_preservesCause() {
try {
TestUtil.getAllSet().parseDelimitedFrom(
new InputStream() {
private int i;
@Override
public int read() throws IOException {
switch (i++) {
case 0:
return 1;
case 1:
throw new InterruptedIOException();
default:
throw new AssertionError();
}
}
});
fail("Expected InterruptedIOException");
} catch (Exception e) {
assertEquals(InterruptedIOException.class, e.getClass());
}
}
}

View File

@ -42,7 +42,6 @@ import static com.google.protobuf.util.Timestamps.NANOS_PER_MICROSECOND;
import static com.google.protobuf.util.Timestamps.NANOS_PER_MILLISECOND;
import static com.google.protobuf.util.Timestamps.NANOS_PER_SECOND;
import com.google.common.collect.ComparisonChain;
import com.google.protobuf.Duration;
import java.text.ParseException;
import java.util.Comparator;
@ -71,11 +70,8 @@ public final class Durations {
public int compare(Duration d1, Duration d2) {
checkValid(d1);
checkValid(d2);
return ComparisonChain.start()
.compare(d1.getSeconds(), d2.getSeconds())
.compare(d1.getNanos(), d2.getNanos())
.result();
int secDiff = Long.compare(d1.getSeconds(), d2.getSeconds());
return (secDiff != 0) ? secDiff : Integer.compare(d1.getNanos(), d2.getNanos());
}
};

View File

@ -217,7 +217,12 @@ final class FieldMaskTree {
Message source,
Message.Builder destination,
FieldMaskUtil.MergeOptions options) {
assert source.getDescriptorForType() == destination.getDescriptorForType();
if (source.getDescriptorForType() != destination.getDescriptorForType()) {
throw new IllegalArgumentException(
String.format(
"source (%s) and destination (%s) descriptor must be equal",
source.getDescriptorForType(), destination.getDescriptorForType()));
}
Descriptor descriptor = source.getDescriptorForType();
for (Entry<String, Node> entry : node.children.entrySet()) {

View File

@ -67,7 +67,6 @@ import com.google.protobuf.Timestamp;
import com.google.protobuf.UInt32Value;
import com.google.protobuf.UInt64Value;
import com.google.protobuf.Value;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
@ -224,7 +223,7 @@ public class JsonFormat {
* Creates a {@link Parser} with default configuration.
*/
public static Parser parser() {
return new Parser(TypeRegistry.getEmptyTypeRegistry(), false);
return new Parser(TypeRegistry.getEmptyTypeRegistry(), false, Parser.DEFAULT_RECURSION_LIMIT);
}
/**
@ -233,10 +232,15 @@ public class JsonFormat {
public static class Parser {
private final TypeRegistry registry;
private final boolean ignoringUnknownFields;
private final int recursionLimit;
private Parser(TypeRegistry registry, boolean ignoreUnknownFields) {
// The default parsing recursion limit is aligned with the proto binary parser.
private static final int DEFAULT_RECURSION_LIMIT = 100;
private Parser(TypeRegistry registry, boolean ignoreUnknownFields, int recursionLimit) {
this.registry = registry;
this.ignoringUnknownFields = ignoreUnknownFields;
this.recursionLimit = recursionLimit;
}
/**
@ -249,16 +253,15 @@ public class JsonFormat {
if (this.registry != TypeRegistry.getEmptyTypeRegistry()) {
throw new IllegalArgumentException("Only one registry is allowed.");
}
return new Parser(registry, this.ignoringUnknownFields);
return new Parser(registry, ignoringUnknownFields, recursionLimit);
}
/**
* Creates a new {@link Parser} configured to not throw an exception
* when an unknown field is encountered. The new Parser clones all other
* configurations from this Parser.
* Creates a new {@link Parser} configured to not throw an exception when an unknown field is
* encountered. The new Parser clones all other configurations from this Parser.
*/
public Parser ignoringUnknownFields() {
return new Parser(this.registry, true);
return new Parser(this.registry, true, recursionLimit);
}
/**
@ -270,7 +273,7 @@ public class JsonFormat {
public void merge(String json, Message.Builder builder) throws InvalidProtocolBufferException {
// TODO(xiaofeng): Investigate the allocation overhead and optimize for
// mobile.
new ParserImpl(registry, ignoringUnknownFields).merge(json, builder);
new ParserImpl(registry, ignoringUnknownFields, recursionLimit).merge(json, builder);
}
/**
@ -283,7 +286,12 @@ public class JsonFormat {
public void merge(Reader json, Message.Builder builder) throws IOException {
// TODO(xiaofeng): Investigate the allocation overhead and optimize for
// mobile.
new ParserImpl(registry, ignoringUnknownFields).merge(json, builder);
new ParserImpl(registry, ignoringUnknownFields, recursionLimit).merge(json, builder);
}
// For testing only.
Parser usingRecursionLimit(int recursionLimit) {
return new Parser(registry, ignoringUnknownFields, recursionLimit);
}
}
@ -1040,11 +1048,15 @@ public class JsonFormat {
private final TypeRegistry registry;
private final JsonParser jsonParser;
private final boolean ignoringUnknownFields;
private final int recursionLimit;
private int currentDepth;
ParserImpl(TypeRegistry registry, boolean ignoreUnknownFields) {
ParserImpl(TypeRegistry registry, boolean ignoreUnknownFields, int recursionLimit) {
this.registry = registry;
this.ignoringUnknownFields = ignoreUnknownFields;
this.jsonParser = new JsonParser();
this.recursionLimit = recursionLimit;
this.currentDepth = 0;
}
void merge(Reader json, Message.Builder builder) throws IOException {
@ -1715,8 +1727,13 @@ public class JsonFormat {
case MESSAGE:
case GROUP:
if (currentDepth >= recursionLimit) {
throw new InvalidProtocolBufferException("Hit recursion limit.");
}
++currentDepth;
Message.Builder subBuilder = builder.newBuilderForField(field);
merge(json, subBuilder);
--currentDepth;
return subBuilder.build();
default:

View File

@ -37,7 +37,6 @@ import static com.google.common.math.LongMath.checkedAdd;
import static com.google.common.math.LongMath.checkedMultiply;
import static com.google.common.math.LongMath.checkedSubtract;
import com.google.common.collect.ComparisonChain;
import com.google.protobuf.Duration;
import com.google.protobuf.Timestamp;
import java.text.ParseException;
@ -101,11 +100,8 @@ public final class Timestamps {
public int compare(Timestamp t1, Timestamp t2) {
checkValid(t1);
checkValid(t2);
return ComparisonChain.start()
.compare(t1.getSeconds(), t2.getSeconds())
.compare(t1.getNanos(), t2.getNanos())
.result();
int secDiff = Long.compare(t1.getSeconds(), t2.getSeconds());
return (secDiff != 0) ? secDiff : Integer.compare(t1.getNanos(), t2.getNanos());
}
};

View File

@ -57,12 +57,15 @@ import com.google.protobuf.util.JsonTestProto.TestDuration;
import com.google.protobuf.util.JsonTestProto.TestFieldMask;
import com.google.protobuf.util.JsonTestProto.TestMap;
import com.google.protobuf.util.JsonTestProto.TestOneof;
import com.google.protobuf.util.JsonTestProto.TestRecursive;
import com.google.protobuf.util.JsonTestProto.TestStruct;
import com.google.protobuf.util.JsonTestProto.TestTimestamp;
import com.google.protobuf.util.JsonTestProto.TestWrappers;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import junit.framework.TestCase;
public class JsonFormatTest extends TestCase {
@ -216,7 +219,9 @@ public class JsonFormatTest extends TestCase {
TestMap.Builder mapBuilder = TestMap.newBuilder();
mapBuilder.putInt32ToEnumMapValue(1, 0);
mapBuilder.getMutableInt32ToEnumMapValue().put(2, 12345);
Map<Integer, Integer> mapWithInvalidValues = new HashMap<Integer, Integer>();
mapWithInvalidValues.put(2, 12345);
mapBuilder.putAllInt32ToEnumMapValue(mapWithInvalidValues);
TestMap mapMessage = mapBuilder.build();
assertEquals(
"{\n"
@ -1140,6 +1145,7 @@ public class JsonFormatTest extends TestCase {
// Expected.
}
}
public void testParserIgnoringUnknownFields() throws Exception {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
String json = "{\n" + " \"unknownField\": \"XXX\"\n" + "}";
@ -1358,4 +1364,34 @@ public class JsonFormatTest extends TestCase {
Any any = builder.build();
assertEquals(0, any.getValue().size());
}
public void testRecursionLimit() throws Exception {
String input =
"{\n"
+ " \"nested\": {\n"
+ " \"nested\": {\n"
+ " \"nested\": {\n"
+ " \"nested\": {\n"
+ " \"value\": 1234\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}\n";
JsonFormat.Parser parser = JsonFormat.parser();
TestRecursive.Builder builder = TestRecursive.newBuilder();
parser.merge(input, builder);
TestRecursive message = builder.build();
assertEquals(1234, message.getNested().getNested().getNested().getNested().getValue());
parser = JsonFormat.parser().usingRecursionLimit(3);
builder = TestRecursive.newBuilder();
try {
parser.merge(input, builder);
fail("Exception is expected.");
} catch (InvalidProtocolBufferException e) {
// Expected.
}
}
}

View File

@ -201,3 +201,8 @@ message TestAny {
message TestCustomJsonName {
int32 value = 1 [json_name = "@value"];
}
message TestRecursive {
int32 value = 1;
TestRecursive nested = 2;
}

View File

@ -33,7 +33,6 @@ docker run \
"$@" \
-e CCACHE_DIR=$CCACHE_DIR \
-e EXTERNAL_GIT_ROOT="/var/local/jenkins/protobuf" \
-e TEST_SET="$TEST_SET" \
-e THIS_IS_REALLY_NEEDED='see https://github.com/docker/docker/issues/14203 for why docker is awful' \
-v "$git_root:/var/local/jenkins/protobuf:ro" \
-v $CCACHE_DIR:$CCACHE_DIR \

View File

@ -12,5 +12,4 @@
export DOCKERFILE_DIR=jenkins/docker
export DOCKER_RUN_SCRIPT=jenkins/pull_request_in_docker.sh
export OUTPUT_DIR=testoutput
export TEST_SET="csharp java_jdk7 javanano_jdk7 java_oracle7 javanano_oracle7 python python_cpp ruby_all javascript golang php_all"
./jenkins/build_and_run_docker.sh

View File

@ -14,29 +14,25 @@ RUN echo 'deb http://ppa.launchpad.net/fkrull/deadsnakes/ubuntu trusty main' > /
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys DB82666C
# Apt source for Oracle Java.
RUN echo 'deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main' > /etc/apt/sources.list.d/webupd8team-java-trusty.list && \
run echo 'deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main' > /etc/apt/sources.list.d/webupd8team-java-trusty.list && \
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EEA14886 && \
echo "oracle-java7-installer shared/accepted-oracle-license-v1-1 select true" | debconf-set-selections
# Apt source for Mono
RUN echo "deb http://download.mono-project.com/repo/debian wheezy main" | tee /etc/apt/sources.list.d/mono-xamarin.list && \
run echo "deb http://download.mono-project.com/repo/debian wheezy main" | tee /etc/apt/sources.list.d/mono-xamarin.list && \
echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list && \
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
# Apt source for php
RUN echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu trusty main" | tee /etc/apt/sources.list.d/various-php.list && \
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F4FCBB07
# Install dotnet SDK based on https://www.microsoft.com/net/core#debian
# (Ubuntu instructions need apt to support https)
RUN apt-get update && apt-get install -y --force-yes curl libunwind8 gettext && \
curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?LinkID=809130 && \
RUN apt-get update && apt-get install -y curl libunwind8 gettext && \
curl -sSL -o dotnet.tar.gz https://go.microsoft.com/fwlink/?LinkID=809130 && \
mkdir -p /opt/dotnet && tar zxf dotnet.tar.gz -C /opt/dotnet && \
ln -s /opt/dotnet/dotnet /usr/local/bin
# Install dependencies. We start with the basic ones require to build protoc
# and the C++ build
RUN apt-get clean && apt-get update && apt-get install -y --force-yes \
RUN apt-get update && apt-get install -y \
autoconf \
autotools-dev \
build-essential \
@ -75,21 +71,6 @@ RUN apt-get clean && apt-get update && apt-get install -y --force-yes \
python3.4-dev \
# -- For Ruby --
ruby \
# -- For C++ benchmarks --
cmake \
# -- For PHP --
php5.5 \
php5.5-dev \
php5.5-xml \
php5.6 \
php5.6-dev \
php5.6-xml \
php7.0 \
php7.0-dev \
php7.0-xml \
phpunit \
valgrind \
libxml2-dev \
&& apt-get clean
##################
@ -134,41 +115,12 @@ RUN cd /tmp && \
cd protobuf && \
./autogen.sh && \
./configure && \
make -j4 && \
make -j6 && \
cd java && \
$MVN install dependency:go-offline -Dmaven.repo.local=$MAVEN_REPO && \
cd ../javanano && \
$MVN install dependency:go-offline -Dmaven.repo.local=$MAVEN_REPO
##################
# PHP dependencies.
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN php composer-setup.php
RUN mv composer.phar /usr/bin/composer
RUN php -r "unlink('composer-setup.php');"
RUN cd /tmp && \
cd protobuf && \
ln -sfn /usr/bin/php5.5 /usr/bin/php && \
ln -sfn /usr/bin/php-config5.5 /usr/bin/php-config && \
ln -sfn /usr/bin/phpize5.5 /usr/bin/phpize && \
composer install && \
mv vendor /usr/local/vendor-5.5 && \
ln -sfn /usr/bin/php5.6 /usr/bin/php && \
ln -sfn /usr/bin/php-config5.6 /usr/bin/php-config && \
ln -sfn /usr/bin/phpize5.6 /usr/bin/phpize && \
composer install && \
mv vendor /usr/local/vendor-5.6 && \
ln -sfn /usr/bin/php7.0 /usr/bin/php && \
ln -sfn /usr/bin/php-config7.0 /usr/bin/php-config && \
ln -sfn /usr/bin/phpize7.0 /usr/bin/phpize && \
composer install && \
mv vendor /usr/local/vendor-7.0
RUN wget http://am1.php.net/get/php-5.5.38.tar.bz2/from/this/mirror
RUN mv mirror php-5.5.38.tar.bz2
RUN tar -xvf php-5.5.38.tar.bz2
RUN cd php-5.5.38 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-5.5-zts && \
make && make install
##################
# Go dependencies.
RUN apt-get install -y \
@ -177,7 +129,7 @@ RUN apt-get install -y \
##################
# Javascript dependencies.
RUN apt-get install -y \
Run apt-get install -y \
# -- For javascript -- \
npm

View File

@ -45,11 +45,19 @@ TIME_CMD="/usr/bin/time -f %e -o $LOG_OUTPUT_DIR/1/cpp/build_time"
$TIME_CMD $TEST_SCRIPT cpp > >(tee $CPP_STDOUT) 2> >(tee $CPP_STDERR >&2)
# Other tests are run in parallel. TEST_SET is defined in
# buildcmds/pull_request{_32}.sh
# Other tests are run in parallel.
parallel --results $LOG_OUTPUT_DIR --joblog $OUTPUT_DIR/joblog $TEST_SCRIPT ::: \
$TEST_SET \
csharp \
java_jdk7 \
javanano_jdk7 \
java_oracle7 \
javanano_oracle7 \
python \
python_cpp \
ruby_all \
javascript \
golang \
|| true # Process test results even if tests fail.
cat $OUTPUT_DIR/joblog

View File

@ -732,6 +732,24 @@ jspb.BinaryDecoder.prototype.readZigzagVarint64 = function() {
};
/**
* Reads a signed, zigzag-encoded 64-bit varint from the binary stream and
* returns its valud as a string.
*
* Zigzag encoding is a modification of varint encoding that reduces the
* storage overhead for small negative integers - for more details on the
* format, see https://developers.google.com/protocol-buffers/docs/encoding
*
* @return {string} The decoded signed, zigzag-encoded 64-bit varint as a
* string.
*/
jspb.BinaryDecoder.prototype.readZigzagVarint64String = function() {
// TODO(haberman): write lossless 64-bit zig-zag math.
var value = this.readZigzagVarint64();
return value.toString();
};
/**
* Reads a raw unsigned 8-bit integer from the binary stream.
*
@ -790,6 +808,20 @@ jspb.BinaryDecoder.prototype.readUint64 = function() {
};
/**
* Reads a raw unsigned 64-bit integer from the binary stream. Note that since
* Javascript represents all numbers as double-precision floats, there will be
* precision lost if the absolute value of the integer is larger than 2^53.
*
* @return {string} The unsigned 64-bit integer read from the binary stream.
*/
jspb.BinaryDecoder.prototype.readUint64String = function() {
var bitsLow = this.readUint32();
var bitsHigh = this.readUint32();
return jspb.utils.joinUnsignedDecimalString(bitsLow, bitsHigh);
};
/**
* Reads a raw signed 8-bit integer from the binary stream.
*
@ -848,6 +880,20 @@ jspb.BinaryDecoder.prototype.readInt64 = function() {
};
/**
* Reads a raw signed 64-bit integer from the binary stream and returns it as a
* string.
*
* @return {string} The signed 64-bit integer read from the binary stream.
* Precision will be lost if the integer exceeds 2^53.
*/
jspb.BinaryDecoder.prototype.readInt64String = function() {
var bitsLow = this.readUint32();
var bitsHigh = this.readUint32();
return jspb.utils.joinSignedDecimalString(bitsLow, bitsHigh);
};
/**
* Reads a 32-bit floating-point number from the binary stream, using the
* temporary buffer to realign the data.

View File

@ -99,6 +99,24 @@ jspb.BinaryEncoder.prototype.writeSplitVarint64 = function(lowBits, highBits) {
};
/**
* Encodes a 64-bit integer in 32:32 split representation into its wire-format
* fixed representation and stores it in the buffer.
* @param {number} lowBits The low 32 bits of the int.
* @param {number} highBits The high 32 bits of the int.
*/
jspb.BinaryEncoder.prototype.writeSplitFixed64 = function(lowBits, highBits) {
goog.asserts.assert(lowBits == Math.floor(lowBits));
goog.asserts.assert(highBits == Math.floor(highBits));
goog.asserts.assert((lowBits >= 0) &&
(lowBits < jspb.BinaryConstants.TWO_TO_32));
goog.asserts.assert((highBits >= 0) &&
(highBits < jspb.BinaryConstants.TWO_TO_32));
this.writeUint32(lowBits);
this.writeUint32(highBits);
};
/**
* Encodes a 32-bit unsigned integer into its wire-format varint representation
* and stores it in the buffer.
@ -207,6 +225,18 @@ jspb.BinaryEncoder.prototype.writeZigzagVarint64 = function(value) {
};
/**
* Encodes a JavaScript decimal string into its wire-format, zigzag-encoded
* varint representation and stores it in the buffer. Integers not representable
* in 64 bits will be truncated.
* @param {string} value The integer to convert.
*/
jspb.BinaryEncoder.prototype.writeZigzagVarint64String = function(value) {
// TODO(haberman): write lossless 64-bit zig-zag math.
this.writeZigzagVarint64(parseInt(value, 10));
};
/**
* Writes a 8-bit unsigned integer to the buffer. Numbers outside the range
* [0,2^8) will be truncated.
@ -314,8 +344,21 @@ jspb.BinaryEncoder.prototype.writeInt64 = function(value) {
goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) &&
(value < jspb.BinaryConstants.TWO_TO_63));
jspb.utils.splitInt64(value);
this.writeUint32(jspb.utils.split64Low);
this.writeUint32(jspb.utils.split64High);
this.writeSplitFixed64(jspb.utils.split64Low, jspb.utils.split64High);
};
/**
* Writes a 64-bit integer decimal strings to the buffer. Numbers outside the
* range [-2^63,2^63) will be truncated.
* @param {string} value The value to write.
*/
jspb.BinaryEncoder.prototype.writeInt64String = function(value) {
goog.asserts.assert(value == Math.floor(value));
goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) &&
(value < jspb.BinaryConstants.TWO_TO_63));
jspb.utils.splitHash64(jspb.utils.decimalStringToHash64(value));
this.writeSplitFixed64(jspb.utils.split64Low, jspb.utils.split64High);
};

View File

@ -32,6 +32,7 @@
goog.require('goog.crypt.base64');
goog.require('goog.testing.asserts');
goog.require('jspb.BinaryWriter');
goog.require('jspb.Message');
// CommonJS-LoadFromFile: ../testbinary_pb proto.jspb.test
@ -87,6 +88,9 @@ goog.require('proto.jspb.test.extendRepeatedStringList');
goog.require('proto.jspb.test.extendRepeatedUint32List');
goog.require('proto.jspb.test.extendRepeatedUint64List');
// CommonJS-LoadFromFile: google/protobuf/any_pb proto.google.protobuf
goog.require('proto.google.protobuf.Any');
var suite = {};
@ -194,8 +198,6 @@ function bytesCompare(arr, expected) {
* @param {proto.jspb.test.TestAllTypes} copy
*/
function checkAllFields(original, copy) {
assertTrue(jspb.Message.equals(original, copy));
assertEquals(copy.getOptionalInt32(), -42);
assertEquals(copy.getOptionalInt64(), -0x7fffffff00000000);
assertEquals(copy.getOptionalUint32(), 0x80000000);
@ -270,6 +272,9 @@ function checkAllFields(original, copy) {
assertElementsEquals(copy.getPackedRepeatedFloatList(), [1.5]);
assertElementsEquals(copy.getPackedRepeatedDoubleList(), [-1.5]);
// Check last so we get more granular errors first.
assertTrue(jspb.Message.equals(original, copy));
}
@ -625,4 +630,36 @@ describe('protoBinaryTest', function() {
var decoded = proto.jspb.test.TestExtendable.deserializeBinary(encoded);
checkExtensions(decoded);
});
/**
* Tests that unknown extensions don't cause deserialization failure.
*/
it('testUnknownExtension', function() {
var msg = new proto.jspb.test.TestExtendable();
fillExtensions(msg);
var writer = new jspb.BinaryWriter();
writer.writeBool((1 << 29) - 1, true);
proto.jspb.test.TestExtendable.serializeBinaryToWriter(msg, writer);
var encoded = writer.getResultBuffer();
var decoded = proto.jspb.test.TestExtendable.deserializeBinary(encoded);
checkExtensions(decoded);
});
it('testAnyWellKnownType', function() {
var any = new proto.google.protobuf.Any();
var msg = new proto.jspb.test.TestAllTypes();
fillAllFields(msg);
any.pack(msg.serializeBinary(), 'jspb.test.TestAllTypes');
assertEquals('type.googleapis.com/jspb.test.TestAllTypes',
any.getTypeUrl());
var msg2 = any.unpack(
proto.jspb.test.TestAllTypes.deserializeBinary,
'jspb.test.TestAllTypes');
checkAllFields(msg, msg2);
});
});

View File

@ -743,6 +743,20 @@ jspb.BinaryReader.prototype.readSint64 = function() {
};
/**
* Reads a signed zigzag-encoded 64-bit integer field from the binary stream,
* or throws an error if the next field in the stream is not of the correct
* wire type.
*
* @return {string} The value of the signed 64-bit integer field as a decimal string.
*/
jspb.BinaryReader.prototype.readSint64String = function() {
goog.asserts.assert(
this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
return this.decoder_.readZigzagVarint64String();
};
/**
* Reads an unsigned 32-bit fixed-length integer fiield from the binary stream,
* or throws an error if the next field in the stream is not of the correct
@ -771,12 +785,29 @@ jspb.BinaryReader.prototype.readFixed64 = function() {
};
/**
* Reads a signed 64-bit integer field from the binary stream as a string, or
* throws an error if the next field in the stream is not of the correct wire
* type.
*
* Returns the value as a string.
*
* @return {string} The value of the unsigned 64-bit integer field as a decimal
* string.
*/
jspb.BinaryReader.prototype.readFixed64String = function() {
goog.asserts.assert(
this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
return this.decoder_.readUint64String();
};
/**
* Reads a signed 32-bit fixed-length integer fiield from the binary stream, or
* throws an error if the next field in the stream is not of the correct wire
* type.
*
* @return {number} The value of the double field.
* @return {number} The value of the signed 32-bit integer field.
*/
jspb.BinaryReader.prototype.readSfixed32 = function() {
goog.asserts.assert(
@ -785,12 +816,27 @@ jspb.BinaryReader.prototype.readSfixed32 = function() {
};
/**
* Reads a signed 32-bit fixed-length integer fiield from the binary stream, or
* throws an error if the next field in the stream is not of the correct wire
* type.
*
* @return {string} The value of the signed 32-bit integer field as a decimal
* string.
*/
jspb.BinaryReader.prototype.readSfixed32String = function() {
goog.asserts.assert(
this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32);
return this.decoder_.readInt32().toString();
};
/**
* Reads a signed 64-bit fixed-length integer fiield from the binary stream, or
* throws an error if the next field in the stream is not of the correct wire
* type.
*
* @return {number} The value of the float field.
* @return {number} The value of the sfixed64 field.
*/
jspb.BinaryReader.prototype.readSfixed64 = function() {
goog.asserts.assert(
@ -799,6 +845,22 @@ jspb.BinaryReader.prototype.readSfixed64 = function() {
};
/**
* Reads a signed 64-bit fixed-length integer fiield from the binary stream, or
* throws an error if the next field in the stream is not of the correct wire
* type.
*
* Returns the value as a string.
*
* @return {string} The value of the sfixed64 field as a decimal string.
*/
jspb.BinaryReader.prototype.readSfixed64String = function() {
goog.asserts.assert(
this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
return this.decoder_.readInt64String();
};
/**
* Reads a 32-bit floating-point field from the binary stream, or throws an
* error if the next field in the stream is not of the correct wire type.
@ -1027,6 +1089,16 @@ 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>}
*/
jspb.BinaryReader.prototype.readPackedSint64String = function() {
return this.readPackedField_(this.decoder_.readZigzagVarint64String);
};
/**
* Reads a packed fixed32 field, which consists of a length header and a list
* of unsigned 32-bit ints.
@ -1047,6 +1119,16 @@ 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>}
*/
jspb.BinaryReader.prototype.readPackedFixed64String = function() {
return this.readPackedField_(this.decoder_.readUint64String);
};
/**
* Reads a packed sfixed32 field, which consists of a length header and a list
* of 32-bit ints.
@ -1067,6 +1149,16 @@ 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>}
*/
jspb.BinaryReader.prototype.readPackedSfixed64String = function() {
return this.readPackedField_(this.decoder_.readInt64String);
};
/**
* Reads a packed float field, which consists of a length header and a list of
* floats.

View File

@ -617,6 +617,16 @@ jspb.utils.decimalStringToHash64 = function(dec) {
};
/**
* Converts a signed or unsigned decimal string into two 32-bit halves, and
* stores them in the temp variables listed above.
* @param {string} value The decimal string to convert.
*/
jspb.utils.splitDecimalString = function(value) {
jspb.utils.splitHash64(jspb.utils.decimalStringToHash64(value));
};
/**
* Converts an 8-character hash string into its hexadecimal representation.
* @param {string} hash

View File

@ -434,6 +434,20 @@ jspb.BinaryWriter.prototype.writeZigzagVarint64_ = function(field, value) {
};
/**
* Writes a zigzag varint field to the buffer without range checking.
* @param {number} field The field number.
* @param {string?} value The value to write.
* @private
*/
jspb.BinaryWriter.prototype.writeZigzagVarint64String_ = function(
field, value) {
if (value == null) return;
this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
this.encoder_.writeZigzagVarint64String(value);
};
/**
* Writes an int32 field to the buffer. Numbers outside the range [-2^31,2^31)
* will be truncated.
@ -574,6 +588,20 @@ jspb.BinaryWriter.prototype.writeSint64 = function(field, value) {
};
/**
* Writes a sint64 field to the buffer. Numbers outside the range [-2^63,2^63)
* will be truncated.
* @param {number} field The field number.
* @param {string?} value The decimal string to write.
*/
jspb.BinaryWriter.prototype.writeSint64String = function(field, value) {
if (value == null) return;
goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) &&
(value < jspb.BinaryConstants.TWO_TO_63));
this.writeZigzagVarint64String_(field, value);
};
/**
* Writes a fixed32 field to the buffer. Numbers outside the range [0,2^32)
* will be truncated.
@ -604,6 +632,19 @@ jspb.BinaryWriter.prototype.writeFixed64 = function(field, value) {
};
/**
* Writes a fixed64 field (with value as a string) to the buffer.
* @param {number} field The field number.
* @param {string?} value The value to write.
*/
jspb.BinaryWriter.prototype.writeFixed64String = function(field, value) {
if (value == null) return;
var num = jspb.arith.UInt64.fromString(value);
this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64);
this.encoder_.writeSplitFixed64(num.lo, num.hi);
};
/**
* Writes a sfixed32 field to the buffer. Numbers outside the range
* [-2^31,2^31) will be truncated.
@ -634,6 +675,20 @@ jspb.BinaryWriter.prototype.writeSfixed64 = function(field, value) {
};
/**
* Writes a sfixed64 string field to the buffer. Numbers outside the range
* [-2^63,2^63) will be truncated.
* @param {number} field The field number.
* @param {string?} value The value to write.
*/
jspb.BinaryWriter.prototype.writeSfixed64String = function(field, value) {
if (value == null) return;
var num = jspb.arith.Int64.fromString(value);
this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64);
this.encoder_.writeSplitFixed64(num.lo, num.hi);
};
/**
* Writes a single-precision floating point field to the buffer. Numbers
* requiring more than 32 bits of precision will be truncated.
@ -796,28 +851,11 @@ jspb.BinaryWriter.prototype.writeVarintHash64 = function(field, value) {
/**
* Writes an array of numbers to the buffer as a repeated varint field.
* 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.
* @private
*/
jspb.BinaryWriter.prototype.writeRepeatedUnsignedVarint32_ =
function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeUnsignedVarint32_(field, value[i]);
}
};
/**
* Writes an array of numbers to the buffer as a repeated varint field.
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
* @private
*/
jspb.BinaryWriter.prototype.writeRepeatedSignedVarint32_ =
function(field, value) {
jspb.BinaryWriter.prototype.writeRepeatedInt32 = function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeSignedVarint32_(field, value[i]);
@ -825,81 +863,13 @@ jspb.BinaryWriter.prototype.writeRepeatedSignedVarint32_ =
};
/**
* Writes an array of numbers to the buffer as a repeated varint field.
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
* @private
*/
jspb.BinaryWriter.prototype.writeRepeatedUnsignedVarint64_ =
function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeUnsignedVarint64_(field, value[i]);
}
};
/**
* Writes an array of numbers to the buffer as a repeated varint field.
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
* @private
*/
jspb.BinaryWriter.prototype.writeRepeatedSignedVarint64_ =
function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeSignedVarint64_(field, value[i]);
}
};
/**
* Writes an array of numbers to the buffer as a repeated zigzag field.
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
* @private
*/
jspb.BinaryWriter.prototype.writeRepeatedZigzag32_ = function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeZigzagVarint32_(field, value[i]);
}
};
/**
* Writes an array of numbers to the buffer as a repeated zigzag field.
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
* @private
*/
jspb.BinaryWriter.prototype.writeRepeatedZigzag_ = function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeZigzagVarint64_(field, value[i]);
}
};
/**
* 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.
*/
jspb.BinaryWriter.prototype.writeRepeatedInt32 =
jspb.BinaryWriter.prototype.writeRepeatedSignedVarint32_;
/**
* 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.
*/
jspb.BinaryWriter.prototype.writeRepeatedInt32String =
function(field, value) {
jspb.BinaryWriter.prototype.writeRepeatedInt32String = function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeInt32String(field, value[i]);
@ -912,8 +882,12 @@ jspb.BinaryWriter.prototype.writeRepeatedInt32String =
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
*/
jspb.BinaryWriter.prototype.writeRepeatedInt64 =
jspb.BinaryWriter.prototype.writeRepeatedSignedVarint64_;
jspb.BinaryWriter.prototype.writeRepeatedInt64 = function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeSignedVarint64_(field, value[i]);
}
};
/**
@ -922,8 +896,7 @@ jspb.BinaryWriter.prototype.writeRepeatedInt64 =
* @param {number} field The field number.
* @param {?Array.<string>} value The array of ints to write.
*/
jspb.BinaryWriter.prototype.writeRepeatedInt64String =
function(field, value) {
jspb.BinaryWriter.prototype.writeRepeatedInt64String = function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeInt64String(field, value[i]);
@ -937,8 +910,12 @@ jspb.BinaryWriter.prototype.writeRepeatedInt64String =
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
*/
jspb.BinaryWriter.prototype.writeRepeatedUint32 =
jspb.BinaryWriter.prototype.writeRepeatedUnsignedVarint32_;
jspb.BinaryWriter.prototype.writeRepeatedUint32 = function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeUnsignedVarint32_(field, value[i]);
}
};
/**
@ -947,8 +924,7 @@ jspb.BinaryWriter.prototype.writeRepeatedUint32 =
* @param {number} field The field number.
* @param {?Array.<string>} value The array of ints to write.
*/
jspb.BinaryWriter.prototype.writeRepeatedUint32String =
function(field, value) {
jspb.BinaryWriter.prototype.writeRepeatedUint32String = function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeUint32String(field, value[i]);
@ -962,8 +938,12 @@ jspb.BinaryWriter.prototype.writeRepeatedUint32String =
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
*/
jspb.BinaryWriter.prototype.writeRepeatedUint64 =
jspb.BinaryWriter.prototype.writeRepeatedUnsignedVarint64_;
jspb.BinaryWriter.prototype.writeRepeatedUint64 = function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeUnsignedVarint64_(field, value[i]);
}
};
/**
@ -972,8 +952,7 @@ jspb.BinaryWriter.prototype.writeRepeatedUint64 =
* @param {number} field The field number.
* @param {?Array.<string>} value The array of ints to write.
*/
jspb.BinaryWriter.prototype.writeRepeatedUint64String =
function(field, value) {
jspb.BinaryWriter.prototype.writeRepeatedUint64String = function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeUint64String(field, value[i]);
@ -986,8 +965,12 @@ jspb.BinaryWriter.prototype.writeRepeatedUint64String =
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
*/
jspb.BinaryWriter.prototype.writeRepeatedSint32 =
jspb.BinaryWriter.prototype.writeRepeatedZigzag32_;
jspb.BinaryWriter.prototype.writeRepeatedSint32 = function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeZigzagVarint32_(field, value[i]);
}
};
/**
@ -995,8 +978,25 @@ jspb.BinaryWriter.prototype.writeRepeatedSint32 =
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
*/
jspb.BinaryWriter.prototype.writeRepeatedSint64 =
jspb.BinaryWriter.prototype.writeRepeatedZigzag_;
jspb.BinaryWriter.prototype.writeRepeatedSint64 = function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeZigzagVarint64_(field, value[i]);
}
};
/**
* 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.
*/
jspb.BinaryWriter.prototype.writeRepeatedSint64String = function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeZigzagVarint64String_(field, value[i]);
}
};
/**
@ -1027,6 +1027,21 @@ 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.
*/
jspb.BinaryWriter.prototype.writeRepeatedFixed64String = function(
field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeFixed64String(field, value[i]);
}
};
/**
* Writes an array of numbers to the buffer as a repeated sfixed32 field.
* @param {number} field The field number.
@ -1053,6 +1068,20 @@ 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.
*/
jspb.BinaryWriter.prototype.writeRepeatedSfixed64String = function(field, value) {
if (value == null) return;
for (var i = 0; i < value.length; i++) {
this.writeSfixed64String(field, value[i]);
}
};
/**
* Writes an array of numbers to the buffer as a repeated float field.
* @param {number} field The field number.
@ -1203,30 +1232,11 @@ jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 =
/**
* Writes an array of numbers to the buffer as a packed varint field.
* 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.
* @private
*/
jspb.BinaryWriter.prototype.writePackedUnsignedVarint32_ = function(
field, value) {
if (value == null || !value.length) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
this.encoder_.writeUnsignedVarint32(value[i]);
}
this.endDelimited_(bookmark);
};
/**
* Writes an array of numbers to the buffer as a packed varint field.
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
* @private
*/
jspb.BinaryWriter.prototype.writePackedSignedVarint32_ = function(
field, value) {
jspb.BinaryWriter.prototype.writePackedInt32 = function(field, value) {
if (value == null || !value.length) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
@ -1236,81 +1246,6 @@ jspb.BinaryWriter.prototype.writePackedSignedVarint32_ = function(
};
/**
* Writes an array of numbers to the buffer as a packed varint field.
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
* @private
*/
jspb.BinaryWriter.prototype.writePackedUnsignedVarint64_ = function(
field, value) {
if (value == null || !value.length) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
this.encoder_.writeUnsignedVarint64(value[i]);
}
this.endDelimited_(bookmark);
};
/**
* Writes an array of numbers to the buffer as a packed varint field.
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
* @private
*/
jspb.BinaryWriter.prototype.writePackedSignedVarint64_ = function(
field, value) {
if (value == null || !value.length) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
this.encoder_.writeSignedVarint64(value[i]);
}
this.endDelimited_(bookmark);
};
/**
* Writes an array of numbers to the buffer as a packed zigzag field.
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
* @private
*/
jspb.BinaryWriter.prototype.writePackedZigzag32_ = function(field, value) {
if (value == null || !value.length) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
this.encoder_.writeZigzagVarint32(value[i]);
}
this.endDelimited_(bookmark);
};
/**
* Writes an array of numbers to the buffer as a packed zigzag field.
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
* @private
*/
jspb.BinaryWriter.prototype.writePackedZigzag64_ = function(field, value) {
if (value == null || !value.length) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
this.encoder_.writeZigzagVarint64(value[i]);
}
this.endDelimited_(bookmark);
};
/**
* 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.
*/
jspb.BinaryWriter.prototype.writePackedInt32 =
jspb.BinaryWriter.prototype.writePackedSignedVarint32_;
/**
* Writes an array of numbers represented as strings to the buffer as a packed
* 32-bit int field.
@ -1332,8 +1267,14 @@ jspb.BinaryWriter.prototype.writePackedInt32String = function(field, value) {
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
*/
jspb.BinaryWriter.prototype.writePackedInt64 =
jspb.BinaryWriter.prototype.writePackedSignedVarint64_;
jspb.BinaryWriter.prototype.writePackedInt64 = function(field, value) {
if (value == null || !value.length) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
this.encoder_.writeSignedVarint64(value[i]);
}
this.endDelimited_(bookmark);
};
/**
@ -1342,8 +1283,7 @@ jspb.BinaryWriter.prototype.writePackedInt64 =
* @param {number} field
* @param {?Array.<string>} value
*/
jspb.BinaryWriter.prototype.writePackedInt64String =
function(field, value) {
jspb.BinaryWriter.prototype.writePackedInt64String = function(field, value) {
if (value == null || !value.length) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
@ -1359,8 +1299,14 @@ jspb.BinaryWriter.prototype.writePackedInt64String =
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
*/
jspb.BinaryWriter.prototype.writePackedUint32 =
jspb.BinaryWriter.prototype.writePackedUnsignedVarint32_;
jspb.BinaryWriter.prototype.writePackedUint32 = function(field, value) {
if (value == null || !value.length) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
this.encoder_.writeUnsignedVarint32(value[i]);
}
this.endDelimited_(bookmark);
};
/**
@ -1385,8 +1331,14 @@ jspb.BinaryWriter.prototype.writePackedUint32String =
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
*/
jspb.BinaryWriter.prototype.writePackedUint64 =
jspb.BinaryWriter.prototype.writePackedUnsignedVarint64_;
jspb.BinaryWriter.prototype.writePackedUint64 = function(field, value) {
if (value == null || !value.length) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
this.encoder_.writeUnsignedVarint64(value[i]);
}
this.endDelimited_(bookmark);
};
/**
@ -1412,17 +1364,46 @@ jspb.BinaryWriter.prototype.writePackedUint64String =
* @param {number} field The field number.
* @param {?Array.<number>} value The array of ints to write.
*/
jspb.BinaryWriter.prototype.writePackedSint32 =
jspb.BinaryWriter.prototype.writePackedZigzag32_;
jspb.BinaryWriter.prototype.writePackedSint32 = function(field, value) {
if (value == null || !value.length) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
this.encoder_.writeZigzagVarint32(value[i]);
}
this.endDelimited_(bookmark);
};
/**
* Writes an array numbers to the buffer as a packed signed 64-bit int field.
* 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.
*/
jspb.BinaryWriter.prototype.writePackedSint64 =
jspb.BinaryWriter.prototype.writePackedZigzag64_;
jspb.BinaryWriter.prototype.writePackedSint64 = function(field, value) {
if (value == null || !value.length) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
this.encoder_.writeZigzagVarint64(value[i]);
}
this.endDelimited_(bookmark);
};
/**
* 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.
*/
jspb.BinaryWriter.prototype.writePackedSint64String = function(field, value) {
if (value == null || !value.length) return;
var bookmark = this.beginDelimited_(field);
for (var i = 0; i < value.length; i++) {
// TODO(haberman): make lossless
this.encoder_.writeZigzagVarint64(parseInt(value[i], 10));
}
this.endDelimited_(bookmark);
};
/**
@ -1455,6 +1436,23 @@ 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.
*/
jspb.BinaryWriter.prototype.writePackedFixed64String = function(field, value) {
if (value == null || !value.length) return;
this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
this.encoder_.writeUnsignedVarint32(value.length * 8);
for (var i = 0; i < value.length; i++) {
var num = jspb.arith.UInt64.fromString(value[i]);
this.encoder_.writeSplitFixed64(num.lo, num.hi);
}
};
/**
* Writes an array of numbers to the buffer as a packed sfixed32 field.
* @param {number} field The field number.
@ -1485,6 +1483,21 @@ 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.
*/
jspb.BinaryWriter.prototype.writePackedSfixed64String = function(field, value) {
if (value == null || !value.length) return;
this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
this.encoder_.writeUnsignedVarint32(value.length * 8);
for (var i = 0; i < value.length; i++) {
this.encoder_.writeInt64String(value[i]);
}
};
/**
* Writes an array of numbers to the buffer as a packed float field.
* @param {number} field The field number.

View File

@ -130,6 +130,58 @@ jspb.Map.prototype.toArray = function() {
};
/**
* Returns the map formatted as an array of key-value pairs, suitable for the
* toObject() form of a message.
*
* @param {boolean=} includeInstance Whether to include the JSPB instance for
* transitional soy proto support: http://goto/soy-param-migration
* @param {!function((boolean|undefined),!V):!Object=} valueToObject
* The static toObject() method, if V is a message type.
* @return {!Array<!Array<!Object>>}
*/
jspb.Map.prototype.toObject = function(includeInstance, valueToObject) {
var rawArray = this.toArray();
var entries = [];
for (var i = 0; i < rawArray.length; i++) {
var entry = this.map_[rawArray[i][0].toString()];
this.wrapEntry_(entry);
var valueWrapper = /** @type {!V|undefined} */ (entry.valueWrapper);
if (valueWrapper) {
goog.asserts.assert(valueToObject);
entries.push([entry.key, valueToObject(includeInstance, valueWrapper)]);
} else {
entries.push([entry.key, entry.value]);
}
}
return entries;
};
/**
* Returns a Map from the given array of key-value pairs when the values are of
* message type. The values in the array must match the format returned by their
* message type's toObject() method.
*
* @template K, V
* @param {!Array<!Array<!Object>>} entries
* @param {!function(new:V)|function(new:V,?)} valueCtor
* The constructor for type V.
* @param {!function(!Object):V} valueFromObject
* The fromObject function for type V.
* @return {!jspb.Map<K, V>}
*/
jspb.Map.fromObject = function(entries, valueCtor, valueFromObject) {
var result = new jspb.Map([], valueCtor);
for (var i = 0; i < entries.length; i++) {
var key = entries[i][0];
var value = valueFromObject(entries[i][1]);
result.set(key, value);
}
return result;
};
/**
* Helper: return an iterator over an array.
* @template T
@ -193,7 +245,7 @@ jspb.Map.prototype.del = function(key) {
* to help out Angular 1.x users. Still evaluating whether this is the best
* option.
*
* @return {!Array<K|V>}
* @return {!Array<!Array<K|V>>}
*/
jspb.Map.prototype.getEntryList = function() {
var entries = [];

View File

@ -262,6 +262,7 @@ function makeTests(msgInfo, submessageCtor, suffix) {
});
}
/**
* Exercises the lazy map<->underlying array sync.
*/
@ -290,12 +291,16 @@ function makeTests(msgInfo, submessageCtor, suffix) {
}
describe('mapsTest', function() {
makeTests({
constructor: proto.jspb.test.TestMapFields,
deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary
}, proto.jspb.test.MapValueMessage, "_Binary");
makeTests({
constructor: proto.jspb.test.TestMapFieldsNoBinary,
deserializeBinary: null
}, proto.jspb.test.MapValueMessageNoBinary, "_NoBinary");
makeTests(
{
constructor: proto.jspb.test.TestMapFields,
deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary
},
proto.jspb.test.MapValueMessage, '_Binary');
makeTests(
{
constructor: proto.jspb.test.TestMapFieldsNoBinary,
deserializeBinary: null
},
proto.jspb.test.MapValueMessageNoBinary, '_NoBinary');
});

View File

@ -550,11 +550,11 @@ jspb.Message.serializeBinaryExtensions = function(proto, writer, extensions,
jspb.Message.readBinaryExtension = function(msg, reader, extensions,
getExtensionFn, setExtensionFn) {
var binaryFieldInfo = extensions[reader.getFieldNumber()];
var fieldInfo = binaryFieldInfo.fieldInfo;
if (!binaryFieldInfo) {
reader.skipField();
return;
}
var fieldInfo = binaryFieldInfo.fieldInfo;
if (!binaryFieldInfo.binaryReaderFn) {
throw new Error('Deserializing extension whose generated code does not ' +
'support binary format');
@ -972,7 +972,8 @@ jspb.Message.wrapRepeatedField_ = function(msg, ctor, fieldNumber) {
* Sets a proto field and syncs it to the backing array.
* @param {!jspb.Message} msg A jspb proto.
* @param {number} fieldNumber The field number.
* @param {jspb.Message|undefined} value A new value for this proto field.
* @param {?jspb.Message|?jspb.Map|undefined} value A new value for this proto
* field.
* @protected
*/
jspb.Message.setWrapperField = function(msg, fieldNumber, value) {

View File

@ -73,10 +73,12 @@ goog.require('proto.jspb.test.TestGroup1');
goog.require('proto.jspb.test.TestMessageWithOneof');
goog.require('proto.jspb.test.TestReservedNames');
goog.require('proto.jspb.test.TestReservedNamesExtension');
goog.require('proto.jspb.test.Deeply.Nested.Message');
// CommonJS-LoadFromFile: test2_pb proto.jspb.test
goog.require('proto.jspb.test.ExtensionMessage');
goog.require('proto.jspb.test.TestExtensionsMessage');
goog.require('proto.jspb.test.ForeignNestedFieldMessage');
@ -1050,8 +1052,10 @@ describe('Message test suite', function() {
// After a serialization-deserialization round trip we should get back the
// same data we started with.
var serialized = msg.serializeBinary();
var deserialized = proto.jspb.test.ForeignNestedFieldMessage.deserializeBinary(serialized);
var serialized = msg.toObject();
var deserialized =
proto.jspb.test.ForeignNestedFieldMessage.fromObject(serialized);
assertEquals(5, deserialized.getDeeplyNestedMessage().getCount());
});
});

View File

@ -38,6 +38,12 @@ goog.require('proto.jspb.test.ForeignMessage');
goog.require('proto.jspb.test.Proto3Enum');
goog.require('proto.jspb.test.TestProto3');
// CommonJS-LoadFromFile: google/protobuf/timestamp_pb proto.google.protobuf
goog.require('proto.google.protobuf.Timestamp');
// CommonJS-LoadFromFile: google/protobuf/struct_pb proto.google.protobuf
goog.require('proto.google.protobuf.Struct');
var BYTES = new Uint8Array([1, 2, 8, 9]);
var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES);
@ -326,4 +332,36 @@ describe('proto3Test', function() {
assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
});
it('testTimestampWellKnownType', function() {
var msg = new proto.google.protobuf.Timestamp();
msg.fromDate(new Date(123456789));
assertEquals(123456, msg.getSeconds());
assertEquals(789000000, msg.getNanos());
var date = msg.toDate();
assertEquals(123456789, date.getTime());
});
it('testStructWellKnownType', function() {
var jsObj = {
abc: "def",
number: 12345.678,
nullKey: null,
boolKey: true,
listKey: [1, null, true, false, "abc"],
structKey: {foo: "bar", somenum: 123},
complicatedKey: [{xyz: {abc: [3, 4, null, false]}}, "zzz"]
};
var struct = proto.google.protobuf.Struct.fromJavaScript(jsObj);
var jsObj2 = struct.toJavaScript();
assertEquals("def", jsObj2.abc);
assertEquals(12345.678, jsObj2.number);
assertEquals(null, jsObj2.nullKey);
assertEquals(true, jsObj2.boolKey);
assertEquals("abc", jsObj2.listKey[4]);
assertEquals("bar", jsObj2.structKey.foo);
assertEquals(4, jsObj2.complicatedKey[0].xyz.abc[1]);
});
});

View File

@ -234,7 +234,9 @@ message TestEndsWithBytes {
optional bytes data = 2;
}
message TestMapFieldsNoBinary {
map<string, string> map_string_string = 1;
map<string, int32> map_string_int32 = 2;
map<string, int64> map_string_int64 = 3;
@ -252,12 +254,13 @@ message TestMapFieldsNoBinary {
}
enum MapValueEnumNoBinary {
MAP_VALUE_FOO_NOBINARY = 0;
MAP_VALUE_BAR_NOBINARY = 1;
MAP_VALUE_BAZ_NOBINARY = 2;
MAP_VALUE_FOO = 0;
MAP_VALUE_BAR = 1;
MAP_VALUE_BAZ = 2;
}
message MapValueMessageNoBinary {
optional int32 foo = 1;
}

View File

@ -1,5 +1,3 @@
# -*- mode: python; -*- PYTHON-PREPROCESSING-REQUIRED
def _GetPath(ctx, path):
if ctx.label.workspace_root:
return ctx.label.workspace_root + '/' + path
@ -230,7 +228,6 @@ def cc_proto_library(
includes=includes,
**kargs)
def internal_gen_well_known_protos_java(srcs):
"""Bazel rule to generate the gen_well_known_protos_java genrule
@ -254,7 +251,6 @@ def internal_gen_well_known_protos_java(srcs):
tools = [":protoc"],
)
def internal_copied_filegroup(name, srcs, strip_prefix, dest, **kwargs):
"""Macro to copy files to a different directory and then create a filegroup.
@ -284,7 +280,6 @@ def internal_copied_filegroup(name, srcs, strip_prefix, dest, **kwargs):
srcs = outs,
**kwargs)
def py_proto_library(
name,
srcs=[],

View File

@ -57,6 +57,8 @@ directly instead of this class.
__author__ = 'matthewtoia@google.com (Matt Toia)'
import collections
from google.protobuf import descriptor
from google.protobuf import descriptor_database
from google.protobuf import text_encoding
@ -88,6 +90,14 @@ def _OptionsOrNone(descriptor_proto):
return None
def _IsMessageSetExtension(field):
return (field.is_extension and
field.containing_type.has_options and
field.containing_type.GetOptions().message_set_wire_format and
field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and
field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL)
class DescriptorPool(object):
"""A collection of protobufs dynamically constructed by descriptor protos."""
@ -115,6 +125,12 @@ class DescriptorPool(object):
self._descriptors = {}
self._enum_descriptors = {}
self._file_descriptors = {}
self._toplevel_extensions = {}
# We store extensions in two two-level mappings: The first key is the
# descriptor of the message being extended, the second key is the extension
# full name or its tag number.
self._extensions_by_name = collections.defaultdict(dict)
self._extensions_by_number = collections.defaultdict(dict)
def Add(self, file_desc_proto):
"""Adds the FileDescriptorProto and its types to this pool.
@ -170,6 +186,48 @@ class DescriptorPool(object):
self._enum_descriptors[enum_desc.full_name] = enum_desc
self.AddFileDescriptor(enum_desc.file)
def AddExtensionDescriptor(self, extension):
"""Adds a FieldDescriptor describing an extension to the pool.
Args:
extension: A FieldDescriptor.
Raises:
AssertionError: when another extension with the same number extends the
same message.
TypeError: when the specified extension is not a
descriptor.FieldDescriptor.
"""
if not (isinstance(extension, descriptor.FieldDescriptor) and
extension.is_extension):
raise TypeError('Expected an extension descriptor.')
if extension.extension_scope is None:
self._toplevel_extensions[extension.full_name] = extension
try:
existing_desc = self._extensions_by_number[
extension.containing_type][extension.number]
except KeyError:
pass
else:
if extension is not existing_desc:
raise AssertionError(
'Extensions "%s" and "%s" both try to extend message type "%s" '
'with field number %d.' %
(extension.full_name, existing_desc.full_name,
extension.containing_type.full_name, extension.number))
self._extensions_by_number[extension.containing_type][
extension.number] = extension
self._extensions_by_name[extension.containing_type][
extension.full_name] = extension
# Also register MessageSet extensions with the type name.
if _IsMessageSetExtension(extension):
self._extensions_by_name[extension.containing_type][
extension.message_type.full_name] = extension
def AddFileDescriptor(self, file_desc):
"""Adds a FileDescriptor to the pool, non-recursively.
@ -302,6 +360,14 @@ class DescriptorPool(object):
A FieldDescriptor, describing the named extension.
"""
full_name = _NormalizeFullyQualifiedName(full_name)
try:
# The proto compiler does not give any link between the FileDescriptor
# and top-level extensions unless the FileDescriptorProto is added to
# the DescriptorDatabase, but this can impact memory usage.
# So we registered these extensions by name explicitly.
return self._toplevel_extensions[full_name]
except KeyError:
pass
message_name, _, extension_name = full_name.rpartition('.')
try:
# Most extensions are nested inside a message.
@ -311,6 +377,39 @@ class DescriptorPool(object):
scope = self.FindFileContainingSymbol(full_name)
return scope.extensions_by_name[extension_name]
def FindExtensionByNumber(self, message_descriptor, number):
"""Gets the extension of the specified message with the specified number.
Extensions have to be registered to this pool by calling
AddExtensionDescriptor.
Args:
message_descriptor: descriptor of the extended message.
number: integer, number of the extension field.
Returns:
A FieldDescriptor describing the extension.
Raise:
KeyError: when no extension with the given number is known for the
specified message.
"""
return self._extensions_by_number[message_descriptor][number]
def FindAllExtensions(self, message_descriptor):
"""Gets all the known extension of a given message.
Extensions have to be registered to this pool by calling
AddExtensionDescriptor.
Args:
message_descriptor: descriptor of the extended message.
Returns:
A list of FieldDescriptor describing the extensions.
"""
return self._extensions_by_number[message_descriptor].values()
def _ConvertFileProtoToFileDescriptor(self, file_proto):
"""Creates a FileDescriptor from a proto or returns a cached copy.

View File

@ -642,10 +642,10 @@ def MessageDecoder(field_number, is_repeated, is_packed, key, new_default):
MESSAGE_SET_ITEM_TAG = encoder.TagBytes(1, wire_format.WIRETYPE_START_GROUP)
def MessageSetItemDecoder(extensions_by_number):
def MessageSetItemDecoder(descriptor):
"""Returns a decoder for a MessageSet item.
The parameter is the _extensions_by_number map for the message class.
The parameter is the message Descriptor.
The message set message looks like this:
message MessageSet {
@ -694,7 +694,7 @@ def MessageSetItemDecoder(extensions_by_number):
if message_start == -1:
raise _DecodeError('MessageSet item missing message.')
extension = extensions_by_number.get(type_id)
extension = message.Extensions._FindExtensionByNumber(type_id)
if extension is not None:
value = field_dict.get(extension)
if value is None:

View File

@ -254,6 +254,53 @@ class DescriptorPoolTest(unittest.TestCase):
with self.assertRaises(KeyError):
self.pool.FindFieldByName('Does not exist')
def testFindAllExtensions(self):
factory1_message = self.pool.FindMessageTypeByName(
'google.protobuf.python.internal.Factory1Message')
factory2_message = self.pool.FindMessageTypeByName(
'google.protobuf.python.internal.Factory2Message')
# An extension defined in a message.
one_more_field = factory2_message.extensions_by_name['one_more_field']
self.pool.AddExtensionDescriptor(one_more_field)
# An extension defined at file scope.
factory_test2 = self.pool.FindFileByName(
'google/protobuf/internal/factory_test2.proto')
another_field = factory_test2.extensions_by_name['another_field']
self.pool.AddExtensionDescriptor(another_field)
extensions = self.pool.FindAllExtensions(factory1_message)
expected_extension_numbers = {one_more_field, another_field}
self.assertEqual(expected_extension_numbers, set(extensions))
# Verify that mutating the returned list does not affect the pool.
extensions.append('unexpected_element')
# Get the extensions again, the returned value does not contain the
# 'unexpected_element'.
extensions = self.pool.FindAllExtensions(factory1_message)
self.assertEqual(expected_extension_numbers, set(extensions))
def testFindExtensionByNumber(self):
factory1_message = self.pool.FindMessageTypeByName(
'google.protobuf.python.internal.Factory1Message')
factory2_message = self.pool.FindMessageTypeByName(
'google.protobuf.python.internal.Factory2Message')
# An extension defined in a message.
one_more_field = factory2_message.extensions_by_name['one_more_field']
self.pool.AddExtensionDescriptor(one_more_field)
# An extension defined at file scope.
factory_test2 = self.pool.FindFileByName(
'google/protobuf/internal/factory_test2.proto')
another_field = factory_test2.extensions_by_name['another_field']
self.pool.AddExtensionDescriptor(another_field)
# An extension defined in a message.
extension = self.pool.FindExtensionByNumber(factory1_message, 1001)
self.assertEqual(extension.name, 'one_more_field')
# An extension defined at file scope.
extension = self.pool.FindExtensionByNumber(factory1_message, 1002)
self.assertEqual(extension.name, 'another_field')
with self.assertRaises(KeyError):
extension = self.pool.FindExtensionByNumber(factory1_message, 1234567)
def testExtensionsAreNotFields(self):
with self.assertRaises(KeyError):
self.pool.FindFieldByName('google.protobuf.python.internal.another_field')

View File

@ -114,18 +114,18 @@ class MessageFactoryTest(unittest.TestCase):
).issubset(set(messages.keys())))
self._ExerciseDynamicClass(
messages['google.protobuf.python.internal.Factory2Message'])
self.assertTrue(
set(['google.protobuf.python.internal.Factory2Message.one_more_field',
'google.protobuf.python.internal.another_field'],
).issubset(
set(messages['google.protobuf.python.internal.Factory1Message']
._extensions_by_name.keys())))
factory_msg1 = messages['google.protobuf.python.internal.Factory1Message']
self.assertTrue(set(
['google.protobuf.python.internal.Factory2Message.one_more_field',
'google.protobuf.python.internal.another_field'],).issubset(set(
ext.full_name
for ext in factory_msg1.DESCRIPTOR.file.pool.FindAllExtensions(
factory_msg1.DESCRIPTOR))))
msg1 = messages['google.protobuf.python.internal.Factory1Message']()
ext1 = factory_msg1._extensions_by_name[
'google.protobuf.python.internal.Factory2Message.one_more_field']
ext2 = factory_msg1._extensions_by_name[
'google.protobuf.python.internal.another_field']
ext1 = msg1.Extensions._FindExtensionByName(
'google.protobuf.python.internal.Factory2Message.one_more_field')
ext2 = msg1.Extensions._FindExtensionByName(
'google.protobuf.python.internal.another_field')
msg1.Extensions[ext1] = 'test1'
msg1.Extensions[ext2] = 'test2'
self.assertEqual('test1', msg1.Extensions[ext1])

View File

@ -51,8 +51,8 @@ this file*.
__author__ = 'robinson@google.com (Will Robinson)'
from io import BytesIO
import sys
import struct
import sys
import weakref
import six
@ -162,12 +162,10 @@ class GeneratedProtocolMessageType(type):
"""
descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
cls._decoders_by_tag = {}
cls._extensions_by_name = {}
cls._extensions_by_number = {}
if (descriptor.has_options and
descriptor.GetOptions().message_set_wire_format):
cls._decoders_by_tag[decoder.MESSAGE_SET_ITEM_TAG] = (
decoder.MessageSetItemDecoder(cls._extensions_by_number), None)
decoder.MessageSetItemDecoder(descriptor), None)
# Attach stuff to each FieldDescriptor for quick lookup later on.
for field in descriptor.fields:
@ -747,32 +745,21 @@ def _AddPropertiesForExtensions(descriptor, cls):
constant_name = extension_name.upper() + "_FIELD_NUMBER"
setattr(cls, constant_name, extension_field.number)
# TODO(amauryfa): Migrate all users of these attributes to functions like
# pool.FindExtensionByNumber(descriptor).
if descriptor.file is not None:
# TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
pool = descriptor.file.pool
cls._extensions_by_number = pool._extensions_by_number[descriptor]
cls._extensions_by_name = pool._extensions_by_name[descriptor]
def _AddStaticMethods(cls):
# TODO(robinson): This probably needs to be thread-safe(?)
def RegisterExtension(extension_handle):
extension_handle.containing_type = cls.DESCRIPTOR
# TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available.
cls.DESCRIPTOR.file.pool.AddExtensionDescriptor(extension_handle)
_AttachFieldHelpers(cls, extension_handle)
# Try to insert our extension, failing if an extension with the same number
# already exists.
actual_handle = cls._extensions_by_number.setdefault(
extension_handle.number, extension_handle)
if actual_handle is not extension_handle:
raise AssertionError(
'Extensions "%s" and "%s" both try to extend message type "%s" with '
'field number %d.' %
(extension_handle.full_name, actual_handle.full_name,
cls.DESCRIPTOR.full_name, extension_handle.number))
cls._extensions_by_name[extension_handle.full_name] = extension_handle
handle = extension_handle # avoid line wrapping
if _IsMessageSetExtension(handle):
# MessageSet extension. Also register under type name.
cls._extensions_by_name[
extension_handle.message_type.full_name] = extension_handle
cls.RegisterExtension = staticmethod(RegisterExtension)
def FromString(s):
@ -1230,7 +1217,7 @@ def _AddMergeFromMethod(cls):
if not isinstance(msg, cls):
raise TypeError(
"Parameter to MergeFrom() must be instance of same class: "
"expected %s got %s." % (cls.__name__, type(msg).__name__))
'expected %s got %s.' % (cls.__name__, msg.__class__.__name__))
assert msg is not self
self._Modified()

View File

@ -99,12 +99,12 @@ class _MiniDecoder(object):
return wire_format.UnpackTag(self.ReadVarint())
def ReadFloat(self):
result = struct.unpack("<f", self._bytes[self._pos:self._pos+4])[0]
result = struct.unpack('<f', self._bytes[self._pos:self._pos+4])[0]
self._pos += 4
return result
def ReadDouble(self):
result = struct.unpack("<d", self._bytes[self._pos:self._pos+8])[0]
result = struct.unpack('<d', self._bytes[self._pos:self._pos+8])[0]
self._pos += 8
return result
@ -621,9 +621,15 @@ class ReflectionTest(BaseTestCase):
self.assertRaises(TypeError, setattr, proto, 'optional_string', 10)
self.assertRaises(TypeError, setattr, proto, 'optional_bytes', 10)
def testIntegerTypes(self):
def assertIntegerTypes(self, integer_fn):
"""Verifies setting of scalar integers.
Args:
integer_fn: A function to wrap the integers that will be assigned.
"""
def TestGetAndDeserialize(field_name, value, expected_type):
proto = unittest_pb2.TestAllTypes()
value = integer_fn(value)
setattr(proto, field_name, value)
self.assertIsInstance(getattr(proto, field_name), expected_type)
proto2 = unittest_pb2.TestAllTypes()
@ -635,7 +641,7 @@ class ReflectionTest(BaseTestCase):
TestGetAndDeserialize('optional_uint32', 1 << 30, int)
try:
integer_64 = long
except NameError: # Python3
except NameError: # Python3
integer_64 = int
if struct.calcsize('L') == 4:
# Python only has signed ints, so 32-bit python can't fit an uint32
@ -649,9 +655,33 @@ class ReflectionTest(BaseTestCase):
TestGetAndDeserialize('optional_uint64', 1 << 30, integer_64)
TestGetAndDeserialize('optional_uint64', 1 << 60, integer_64)
def testSingleScalarBoundsChecking(self):
def testIntegerTypes(self):
self.assertIntegerTypes(lambda x: x)
def testNonStandardIntegerTypes(self):
self.assertIntegerTypes(test_util.NonStandardInteger)
def testIllegalValuesForIntegers(self):
pb = unittest_pb2.TestAllTypes()
# Strings are illegal, even when the represent an integer.
with self.assertRaises(TypeError):
pb.optional_uint64 = '2'
# The exact error should propagate with a poorly written custom integer.
with self.assertRaisesRegexp(RuntimeError, 'my_error'):
pb.optional_uint64 = test_util.NonStandardInteger(5, 'my_error')
def assetIntegerBoundsChecking(self, integer_fn):
"""Verifies bounds checking for scalar integer fields.
Args:
integer_fn: A function to wrap the integers that will be assigned.
"""
def TestMinAndMaxIntegers(field_name, expected_min, expected_max):
pb = unittest_pb2.TestAllTypes()
expected_min = integer_fn(expected_min)
expected_max = integer_fn(expected_max)
setattr(pb, field_name, expected_min)
self.assertEqual(expected_min, getattr(pb, field_name))
setattr(pb, field_name, expected_max)
@ -663,11 +693,22 @@ class ReflectionTest(BaseTestCase):
TestMinAndMaxIntegers('optional_uint32', 0, 0xffffffff)
TestMinAndMaxIntegers('optional_int64', -(1 << 63), (1 << 63) - 1)
TestMinAndMaxIntegers('optional_uint64', 0, 0xffffffffffffffff)
# A bit of white-box testing since -1 is an int and not a long in C++ and
# so goes down a different path.
pb = unittest_pb2.TestAllTypes()
with self.assertRaises(ValueError):
pb.optional_uint64 = integer_fn(-(1 << 63))
pb = unittest_pb2.TestAllTypes()
pb.optional_nested_enum = 1
pb.optional_nested_enum = integer_fn(1)
self.assertEqual(1, pb.optional_nested_enum)
def testSingleScalarBoundsChecking(self):
self.assetIntegerBoundsChecking(lambda x: x)
def testNonStandardSingleScalarBoundsChecking(self):
self.assetIntegerBoundsChecking(test_util.NonStandardInteger)
def testRepeatedScalarTypeSafety(self):
proto = unittest_pb2.TestAllTypes()
self.assertRaises(TypeError, proto.repeated_int32.append, 1.1)
@ -1187,12 +1228,18 @@ class ReflectionTest(BaseTestCase):
self.assertTrue(not extendee_proto.HasExtension(extension))
def testRegisteredExtensions(self):
self.assertTrue('protobuf_unittest.optional_int32_extension' in
unittest_pb2.TestAllExtensions._extensions_by_name)
self.assertTrue(1 in unittest_pb2.TestAllExtensions._extensions_by_number)
pool = unittest_pb2.DESCRIPTOR.pool
self.assertTrue(
pool.FindExtensionByNumber(
unittest_pb2.TestAllExtensions.DESCRIPTOR, 1))
self.assertIs(
pool.FindExtensionByName(
'protobuf_unittest.optional_int32_extension').containing_type,
unittest_pb2.TestAllExtensions.DESCRIPTOR)
# Make sure extensions haven't been registered into types that shouldn't
# have any.
self.assertEqual(0, len(unittest_pb2.TestAllTypes._extensions_by_name))
self.assertEqual(0, len(
pool.FindAllExtensions(unittest_pb2.TestAllTypes.DESCRIPTOR)))
# If message A directly contains message B, and
# a.HasField('b') is currently False, then mutating any

View File

@ -36,8 +36,9 @@ This is intentionally modeled on C++ code in
__author__ = 'robinson@google.com (Will Robinson)'
import numbers
import operator
import os.path
import sys
from google.protobuf import unittest_import_pb2
@ -694,3 +695,154 @@ def SetAllUnpackedFields(message):
message.unpacked_bool.extend([True, False])
message.unpacked_enum.extend([unittest_pb2.FOREIGN_BAR,
unittest_pb2.FOREIGN_BAZ])
class NonStandardInteger(numbers.Integral):
"""An integer object that does not subclass int.
This is used to verify that both C++ and regular proto systems can handle
integer others than int and long and that they handle them in predictable
ways.
NonStandardInteger is the minimal legal specification for a custom Integral.
As such, it does not support 0 < x < 5 and it is not hashable.
Note: This is added here instead of relying on numpy or a similar library with
custom integers to limit dependencies.
"""
def __init__(self, val, error_string_on_conversion=None):
assert isinstance(val, numbers.Integral)
if isinstance(val, NonStandardInteger):
val = val.val
self.val = val
self.error_string_on_conversion = error_string_on_conversion
def __long__(self):
if self.error_string_on_conversion:
raise RuntimeError(self.error_string_on_conversion)
return long(self.val)
def __abs__(self):
return NonStandardInteger(operator.abs(self.val))
def __add__(self, y):
return NonStandardInteger(operator.add(self.val, y))
def __div__(self, y):
return NonStandardInteger(operator.div(self.val, y))
def __eq__(self, y):
return operator.eq(self.val, y)
def __floordiv__(self, y):
return NonStandardInteger(operator.floordiv(self.val, y))
def __truediv__(self, y):
return NonStandardInteger(operator.truediv(self.val, y))
def __invert__(self):
return NonStandardInteger(operator.invert(self.val))
def __mod__(self, y):
return NonStandardInteger(operator.mod(self.val, y))
def __mul__(self, y):
return NonStandardInteger(operator.mul(self.val, y))
def __neg__(self):
return NonStandardInteger(operator.neg(self.val))
def __pos__(self):
return NonStandardInteger(operator.pos(self.val))
def __pow__(self, y):
return NonStandardInteger(operator.pow(self.val, y))
def __trunc__(self):
return int(self.val)
def __radd__(self, y):
return NonStandardInteger(operator.add(y, self.val))
def __rdiv__(self, y):
return NonStandardInteger(operator.div(y, self.val))
def __rmod__(self, y):
return NonStandardInteger(operator.mod(y, self.val))
def __rmul__(self, y):
return NonStandardInteger(operator.mul(y, self.val))
def __rpow__(self, y):
return NonStandardInteger(operator.pow(y, self.val))
def __rfloordiv__(self, y):
return NonStandardInteger(operator.floordiv(y, self.val))
def __rtruediv__(self, y):
return NonStandardInteger(operator.truediv(y, self.val))
def __lshift__(self, y):
return NonStandardInteger(operator.lshift(self.val, y))
def __rshift__(self, y):
return NonStandardInteger(operator.rshift(self.val, y))
def __rlshift__(self, y):
return NonStandardInteger(operator.lshift(y, self.val))
def __rrshift__(self, y):
return NonStandardInteger(operator.rshift(y, self.val))
def __le__(self, y):
if isinstance(y, NonStandardInteger):
y = y.val
return operator.le(self.val, y)
def __lt__(self, y):
if isinstance(y, NonStandardInteger):
y = y.val
return operator.lt(self.val, y)
def __and__(self, y):
return NonStandardInteger(operator.and_(self.val, y))
def __or__(self, y):
return NonStandardInteger(operator.or_(self.val, y))
def __xor__(self, y):
return NonStandardInteger(operator.xor(self.val, y))
def __rand__(self, y):
return NonStandardInteger(operator.and_(y, self.val))
def __ror__(self, y):
return NonStandardInteger(operator.or_(y, self.val))
def __rxor__(self, y):
return NonStandardInteger(operator.xor(y, self.val))
def __bool__(self):
return self.val
def __nonzero__(self):
return self.val
def __ceil__(self):
return self
def __floor__(self):
return self
def __int__(self):
if self.error_string_on_conversion:
raise RuntimeError(self.error_string_on_conversion)
return int(self.val)
def __round__(self):
return self
def __repr__(self):
return 'NonStandardInteger(%s)' % self.val

View File

@ -124,5 +124,3 @@ else:
def Same(func):
return func
return Same

View File

@ -582,22 +582,20 @@ class OnlyWorksWithProto2RightNowTests(TextFormatBase):
% (letter,) for letter in string.ascii_uppercase))
self.CompareToGoldenText(text_format.MessageToString(message), golden)
def testMapOrderSemantics(self):
golden_lines = self.ReadGolden('map_test_data.txt')
# The C++ implementation emits defaulted-value fields, while the Python
# implementation does not. Adjusting for this is awkward, but it is
# valuable to test against a common golden file.
line_blacklist = (' key: 0\n', ' value: 0\n', ' key: false\n',
' value: false\n')
golden_lines = [line for line in golden_lines if line not in line_blacklist]
# TODO(teboring): In c/137553523, not serializing default value for map entry
# message has been fixed. This test needs to be disabled in order to submit
# that cl. Add this back when c/137553523 has been submitted.
# def testMapOrderSemantics(self):
# golden_lines = self.ReadGolden('map_test_data.txt')
message = map_unittest_pb2.TestMap()
text_format.ParseLines(golden_lines, message)
candidate = text_format.MessageToString(message)
# The Python implementation emits "1.0" for the double value that the C++
# implementation emits as "1".
candidate = candidate.replace('1.0', '1', 2)
self.assertMultiLineEqual(candidate, ''.join(golden_lines))
# message = map_unittest_pb2.TestMap()
# text_format.ParseLines(golden_lines, message)
# candidate = text_format.MessageToString(message)
# # The Python implementation emits "1.0" for the double value that the C++
# # implementation emits as "1".
# candidate = candidate.replace('1.0', '1', 2)
# candidate = candidate.replace('0.0', '0', 2)
# self.assertMultiLineEqual(candidate, ''.join(golden_lines))
# Tests of proto2-only features (MessageSet, extensions, etc.).

View File

@ -45,6 +45,7 @@ TYPE_TO_DESERIALIZE_METHOD: A dictionary with field types and deserialization
__author__ = 'robinson@google.com (Will Robinson)'
import numbers
import six
if six.PY3:
@ -126,11 +127,11 @@ class IntValueChecker(object):
"""Checker used for integer fields. Performs type-check and range check."""
def CheckValue(self, proposed_value):
if not isinstance(proposed_value, six.integer_types):
if not isinstance(proposed_value, numbers.Integral):
message = ('%.1024r has type %s, but expected one of: %s' %
(proposed_value, type(proposed_value), six.integer_types))
raise TypeError(message)
if not self._MIN <= proposed_value <= self._MAX:
if not self._MIN <= int(proposed_value) <= self._MAX:
raise ValueError('Value out of range: %d' % proposed_value)
# We force 32-bit values to int and 64-bit values to long to make
# alternate implementations where the distinction is more significant
@ -150,11 +151,11 @@ class EnumValueChecker(object):
self._enum_type = enum_type
def CheckValue(self, proposed_value):
if not isinstance(proposed_value, six.integer_types):
if not isinstance(proposed_value, numbers.Integral):
message = ('%.1024r has type %s, but expected one of: %s' %
(proposed_value, type(proposed_value), six.integer_types))
raise TypeError(message)
if proposed_value not in self._enum_type.values_by_number:
if int(proposed_value) not in self._enum_type.values_by_number:
raise ValueError('Unknown enum value: %d' % proposed_value)
return proposed_value
@ -223,11 +224,11 @@ _VALUE_CHECKERS = {
_FieldDescriptor.CPPTYPE_UINT32: Uint32ValueChecker(),
_FieldDescriptor.CPPTYPE_UINT64: Uint64ValueChecker(),
_FieldDescriptor.CPPTYPE_DOUBLE: TypeCheckerWithDefault(
0.0, float, int, long),
0.0, numbers.Real),
_FieldDescriptor.CPPTYPE_FLOAT: TypeCheckerWithDefault(
0.0, float, int, long),
0.0, numbers.Real),
_FieldDescriptor.CPPTYPE_BOOL: TypeCheckerWithDefault(
False, bool, int),
False, bool, numbers.Integral),
_FieldDescriptor.CPPTYPE_STRING: TypeCheckerWithDefault(b'', bytes),
}

View File

@ -43,9 +43,9 @@ Simple usage example:
__author__ = 'jieluo@google.com (Jie Luo)'
try:
from collections import OrderedDict
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict #PY26
from ordereddict import OrderedDict #PY26
import base64
import json
import math

View File

@ -319,6 +319,51 @@ PyObject* FindFileContainingSymbol(PyDescriptorPool* self, PyObject* arg) {
return PyFileDescriptor_FromDescriptor(file_descriptor);
}
PyObject* FindExtensionByNumber(PyDescriptorPool* self, PyObject* args) {
PyObject* message_descriptor;
int number;
if (!PyArg_ParseTuple(args, "Oi", &message_descriptor, &number)) {
return NULL;
}
const Descriptor* descriptor = PyMessageDescriptor_AsDescriptor(
message_descriptor);
if (descriptor == NULL) {
return NULL;
}
const FieldDescriptor* extension_descriptor =
self->pool->FindExtensionByNumber(descriptor, number);
if (extension_descriptor == NULL) {
PyErr_Format(PyExc_KeyError, "Couldn't find extension %d", number);
return NULL;
}
return PyFieldDescriptor_FromDescriptor(extension_descriptor);
}
PyObject* FindAllExtensions(PyDescriptorPool* self, PyObject* arg) {
const Descriptor* descriptor = PyMessageDescriptor_AsDescriptor(arg);
if (descriptor == NULL) {
return NULL;
}
std::vector<const FieldDescriptor*> extensions;
self->pool->FindAllExtensions(descriptor, &extensions);
ScopedPyObjectPtr result(PyList_New(extensions.size()));
if (result == NULL) {
return NULL;
}
for (int i = 0; i < extensions.size(); i++) {
PyObject* extension = PyFieldDescriptor_FromDescriptor(extensions[i]);
if (extension == NULL) {
return NULL;
}
PyList_SET_ITEM(result.get(), i, extension); // Steals the reference.
}
return result.release();
}
// These functions should not exist -- the only valid way to create
// descriptors is to call Add() or AddSerializedFile().
// But these AddDescriptor() functions were created in Python and some people
@ -376,6 +421,22 @@ PyObject* AddEnumDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
Py_RETURN_NONE;
}
PyObject* AddExtensionDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
const FieldDescriptor* extension_descriptor =
PyFieldDescriptor_AsDescriptor(descriptor);
if (!extension_descriptor) {
return NULL;
}
if (extension_descriptor !=
self->pool->FindExtensionByName(extension_descriptor->full_name())) {
PyErr_Format(PyExc_ValueError,
"The extension descriptor %s does not belong to this pool",
extension_descriptor->full_name().c_str());
return NULL;
}
Py_RETURN_NONE;
}
// The code below loads new Descriptors from a serialized FileDescriptorProto.
@ -475,6 +536,8 @@ static PyMethodDef Methods[] = {
"No-op. Add() must have been called before." },
{ "AddEnumDescriptor", (PyCFunction)AddEnumDescriptor, METH_O,
"No-op. Add() must have been called before." },
{ "AddExtensionDescriptor", (PyCFunction)AddExtensionDescriptor, METH_O,
"No-op. Add() must have been called before." },
{ "FindFileByName", (PyCFunction)FindFileByName, METH_O,
"Searches for a file descriptor by its .proto name." },
@ -495,6 +558,10 @@ static PyMethodDef Methods[] = {
{ "FindFileContainingSymbol", (PyCFunction)FindFileContainingSymbol, METH_O,
"Gets the FileDescriptor containing the specified symbol." },
{ "FindExtensionByNumber", (PyCFunction)FindExtensionByNumber, METH_VARARGS,
"Gets the extension descriptor for the given number." },
{ "FindAllExtensions", (PyCFunction)FindAllExtensions, METH_O,
"Gets all known extensions of the given message descriptor." },
{NULL}
};

View File

@ -38,6 +38,7 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/pyext/descriptor.h>
#include <google/protobuf/pyext/message.h>
#include <google/protobuf/pyext/message_factory.h>
@ -46,6 +47,16 @@
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
#include <google/protobuf/stubs/shared_ptr.h>
#if PY_MAJOR_VERSION >= 3
#if PY_VERSION_HEX < 0x03030000
#error "Python 3.0 - 3.2 are not supported."
#endif
#define PyString_AsStringAndSize(ob, charpp, sizep) \
(PyUnicode_Check(ob)? \
((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
#endif
namespace google {
namespace protobuf {
namespace python {
@ -90,6 +101,7 @@ PyObject* subscript(ExtensionDict* self, PyObject* key) {
if (descriptor->label() != FieldDescriptor::LABEL_REPEATED &&
descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
// TODO(plabatut): consider building the class on the fly!
PyObject* sub_message = cmessage::InternalGetSubMessage(
self->parent, descriptor);
if (sub_message == NULL) {
@ -101,7 +113,17 @@ PyObject* subscript(ExtensionDict* self, PyObject* key) {
if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
CMessageClass* message_class = message_factory::GetMessageClass(
// On the fly message class creation is needed to support the following
// situation:
// 1- add FileDescriptor to the pool that contains extensions of a message
// defined by another proto file. Do not create any message classes.
// 2- instantiate an extended message, and access the extension using
// the field descriptor.
// 3- the extension submessage fails to be returned, because no class has
// been created.
// It happens when deserializing text proto format, or when enumerating
// fields of a deserialized message.
CMessageClass* message_class = message_factory::GetOrCreateMessageClass(
cmessage::GetFactoryForMessage(self->parent),
descriptor->message_type());
if (message_class == NULL) {
@ -154,34 +176,51 @@ int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value) {
return 0;
}
PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* name) {
ScopedPyObjectPtr extensions_by_name(PyObject_GetAttrString(
reinterpret_cast<PyObject*>(self->parent), "_extensions_by_name"));
if (extensions_by_name == NULL) {
PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* arg) {
char* name;
Py_ssize_t name_size;
if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
return NULL;
}
PyObject* result = PyDict_GetItem(extensions_by_name.get(), name);
if (result == NULL) {
Py_RETURN_NONE;
} else {
Py_INCREF(result);
return result;
PyDescriptorPool* pool = cmessage::GetFactoryForMessage(self->parent)->pool;
const FieldDescriptor* message_extension =
pool->pool->FindExtensionByName(string(name, name_size));
if (message_extension == NULL) {
// Is is the name of a message set extension?
const Descriptor* message_descriptor = pool->pool->FindMessageTypeByName(
string(name, name_size));
if (message_descriptor && message_descriptor->extension_count() > 0) {
const FieldDescriptor* extension = message_descriptor->extension(0);
if (extension->is_extension() &&
extension->containing_type()->options().message_set_wire_format() &&
extension->type() == FieldDescriptor::TYPE_MESSAGE &&
extension->label() == FieldDescriptor::LABEL_OPTIONAL) {
message_extension = extension;
}
}
}
if (message_extension == NULL) {
Py_RETURN_NONE;
}
return PyFieldDescriptor_FromDescriptor(message_extension);
}
PyObject* _FindExtensionByNumber(ExtensionDict* self, PyObject* number) {
ScopedPyObjectPtr extensions_by_number(PyObject_GetAttrString(
reinterpret_cast<PyObject*>(self->parent), "_extensions_by_number"));
if (extensions_by_number == NULL) {
PyObject* _FindExtensionByNumber(ExtensionDict* self, PyObject* arg) {
int64 number = PyLong_AsLong(arg);
if (number == -1 && PyErr_Occurred()) {
return NULL;
}
PyObject* result = PyDict_GetItem(extensions_by_number.get(), number);
if (result == NULL) {
PyDescriptorPool* pool = cmessage::GetFactoryForMessage(self->parent)->pool;
const FieldDescriptor* message_extension = pool->pool->FindExtensionByNumber(
self->parent->message->GetDescriptor(), number);
if (message_extension == NULL) {
Py_RETURN_NONE;
} else {
Py_INCREF(result);
return result;
}
return PyFieldDescriptor_FromDescriptor(message_extension);
}
ExtensionDict* NewExtensionDict(CMessage *parent) {

View File

@ -374,7 +374,7 @@ static int InitializeAndCopyToParentContainer(MapContainer* from,
// A somewhat roundabout way of copying just one field from old_message to
// new_message. This is the best we can do with what Reflection gives us.
Message* mutable_old = from->GetMutableMessage();
vector<const FieldDescriptor*> fields;
std::vector<const FieldDescriptor*> fields;
fields.push_back(from->parent_field_descriptor);
// Move the map field into the new message.

View File

@ -64,11 +64,11 @@
#include <google/protobuf/pyext/repeated_scalar_container.h>
#include <google/protobuf/pyext/map_container.h>
#include <google/protobuf/pyext/message_factory.h>
#include <google/protobuf/pyext/safe_numerics.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
#include <google/protobuf/stubs/strutil.h>
#if PY_MAJOR_VERSION >= 3
#define PyInt_Check PyLong_Check
#define PyInt_AsLong PyLong_AsLong
#define PyInt_FromLong PyLong_FromLong
#define PyInt_FromSize_t PyLong_FromSize_t
@ -92,8 +92,6 @@ namespace protobuf {
namespace python {
static PyObject* kDESCRIPTOR;
static PyObject* k_extensions_by_name;
static PyObject* k_extensions_by_number;
PyObject* EnumTypeWrapper_class;
static PyObject* PythonMessage_class;
static PyObject* kEmptyWeakref;
@ -128,19 +126,6 @@ static bool AddFieldNumberToClass(
// Finalize the creation of the Message class.
static int AddDescriptors(PyObject* cls, const Descriptor* descriptor) {
// If there are extension_ranges, the message is "extendable", and extension
// classes will register themselves in this class.
if (descriptor->extension_range_count() > 0) {
ScopedPyObjectPtr by_name(PyDict_New());
if (PyObject_SetAttr(cls, k_extensions_by_name, by_name.get()) < 0) {
return -1;
}
ScopedPyObjectPtr by_number(PyDict_New());
if (PyObject_SetAttr(cls, k_extensions_by_number, by_number.get()) < 0) {
return -1;
}
}
// For each field set: cls.<field>_FIELD_NUMBER = <number>
for (int i = 0; i < descriptor->field_count(); ++i) {
if (!AddFieldNumberToClass(cls, descriptor->field(i))) {
@ -357,6 +342,61 @@ static int InsertEmptyWeakref(PyTypeObject *base_type) {
#endif // PY_MAJOR_VERSION >= 3
}
// The _extensions_by_name dictionary is built on every access.
// TODO(amauryfa): Migrate all users to pool.FindAllExtensions()
static PyObject* GetExtensionsByName(CMessageClass *self, void *closure) {
const PyDescriptorPool* pool = self->py_message_factory->pool;
std::vector<const FieldDescriptor*> extensions;
pool->pool->FindAllExtensions(self->message_descriptor, &extensions);
ScopedPyObjectPtr result(PyDict_New());
for (int i = 0; i < extensions.size(); i++) {
ScopedPyObjectPtr extension(
PyFieldDescriptor_FromDescriptor(extensions[i]));
if (extension == NULL) {
return NULL;
}
if (PyDict_SetItemString(result.get(), extensions[i]->full_name().c_str(),
extension.get()) < 0) {
return NULL;
}
}
return result.release();
}
// The _extensions_by_number dictionary is built on every access.
// TODO(amauryfa): Migrate all users to pool.FindExtensionByNumber()
static PyObject* GetExtensionsByNumber(CMessageClass *self, void *closure) {
const PyDescriptorPool* pool = self->py_message_factory->pool;
std::vector<const FieldDescriptor*> extensions;
pool->pool->FindAllExtensions(self->message_descriptor, &extensions);
ScopedPyObjectPtr result(PyDict_New());
for (int i = 0; i < extensions.size(); i++) {
ScopedPyObjectPtr extension(
PyFieldDescriptor_FromDescriptor(extensions[i]));
if (extension == NULL) {
return NULL;
}
ScopedPyObjectPtr number(PyInt_FromLong(extensions[i]->number()));
if (number == NULL) {
return NULL;
}
if (PyDict_SetItem(result.get(), number.get(), extension.get()) < 0) {
return NULL;
}
}
return result.release();
}
static PyGetSetDef Getters[] = {
{"_extensions_by_name", (getter)GetExtensionsByName, NULL},
{"_extensions_by_number", (getter)GetExtensionsByNumber, NULL},
{NULL}
};
} // namespace message_meta
PyTypeObject CMessageClass_Type = {
@ -389,7 +429,7 @@ PyTypeObject CMessageClass_Type = {
0, // tp_iternext
0, // tp_methods
0, // tp_members
0, // tp_getset
message_meta::Getters, // tp_getset
0, // tp_base
0, // tp_dict
0, // tp_descr_get
@ -525,23 +565,10 @@ int ForEachCompositeField(CMessage* self, Visitor visitor) {
// ---------------------------------------------------------------------
// Constants used for integer type range checking.
PyObject* kPythonZero;
PyObject* kint32min_py;
PyObject* kint32max_py;
PyObject* kuint32max_py;
PyObject* kint64min_py;
PyObject* kint64max_py;
PyObject* kuint64max_py;
PyObject* EncodeError_class;
PyObject* DecodeError_class;
PyObject* PickleError_class;
// Constant PyString values used for GetAttr/GetItem.
static PyObject* k_cdescriptor;
static PyObject* kfull_name;
/* Is 64bit */
void FormatTypeError(PyObject* arg, char* expected_types) {
PyObject* repr = PyObject_Repr(arg);
@ -555,68 +582,126 @@ void FormatTypeError(PyObject* arg, char* expected_types) {
}
}
void OutOfRangeError(PyObject* arg) {
PyObject *s = PyObject_Str(arg);
if (s) {
PyErr_Format(PyExc_ValueError,
"Value out of range: %s",
PyString_AsString(s));
Py_DECREF(s);
}
}
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(!IsValidNumericCast<RangeType>(value)) {
OutOfRangeError(arg);
return false;
}
return true;
}
template<class T>
bool CheckAndGetInteger(
PyObject* arg, T* value, PyObject* min, PyObject* max) {
bool is_long = PyLong_Check(arg);
bool CheckAndGetInteger(PyObject* arg, T* value) {
// The fast path.
#if PY_MAJOR_VERSION < 3
if (!PyInt_Check(arg) && !is_long) {
// 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;
}
}
#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)) {
FormatTypeError(arg, "int, long");
return false;
}
if (PyObject_Compare(min, arg) > 0 || PyObject_Compare(max, arg) < 0) {
#else
if (!is_long) {
FormatTypeError(arg, "int");
return false;
}
if (PyObject_RichCompareBool(min, arg, Py_LE) != 1 ||
PyObject_RichCompareBool(max, arg, Py_GE) != 1) {
#endif
if (!PyErr_Occurred()) {
PyObject *s = PyObject_Str(arg);
if (s) {
PyErr_Format(PyExc_ValueError,
"Value out of range: %s",
PyString_AsString(s));
Py_DECREF(s);
}
}
return false;
}
#if PY_MAJOR_VERSION < 3
if (!is_long) {
*value = static_cast<T>(PyInt_AsLong(arg));
} else // NOLINT
#endif
{
if (min == kPythonZero) {
*value = static_cast<T>(PyLong_AsUnsignedLongLong(arg));
// Now we have an integral number so we can safely use PyLong_ functions.
// We need to treat the signed and unsigned cases differently in case arg is
// holding a value above the maximum for signed longs.
if (std::numeric_limits<T>::min() == 0) {
// Unsigned case.
unsigned PY_LONG_LONG ulong_result;
if (PyLong_Check(arg)) {
ulong_result = PyLong_AsUnsignedLongLong(arg);
} else {
*value = static_cast<T>(PyLong_AsLongLong(arg));
// 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;
}
ulong_result = PyLong_AsUnsignedLongLong(casted);
Py_DECREF(casted);
}
if (VerifyIntegerCastAndRange<T, unsigned PY_LONG_LONG>(arg,
ulong_result)) {
*value = static_cast<T>(ulong_result);
} else {
return false;
}
} else {
// Signed case.
PY_LONG_LONG long_result;
PyNumberMethods *nb;
if ((nb = arg->ob_type->tp_as_number) != NULL && nb->nb_int != NULL) {
// PyLong_AsLongLong requires it to be a long or to have an __int__()
// method.
long_result = PyLong_AsLongLong(arg);
} else {
// 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;
}
long_result = PyLong_AsLongLong(casted);
Py_DECREF(casted);
}
if (VerifyIntegerCastAndRange<T, PY_LONG_LONG>(arg, long_result)) {
*value = static_cast<T>(long_result);
} else {
return false;
}
}
return true;
}
// These are referenced by repeated_scalar_container, and must
// be explicitly instantiated.
template bool CheckAndGetInteger<int32>(
PyObject*, int32*, PyObject*, PyObject*);
template bool CheckAndGetInteger<int64>(
PyObject*, int64*, PyObject*, PyObject*);
template bool CheckAndGetInteger<uint32>(
PyObject*, uint32*, PyObject*, PyObject*);
template bool CheckAndGetInteger<uint64>(
PyObject*, uint64*, PyObject*, PyObject*);
template bool CheckAndGetInteger<int32>(PyObject*, int32*);
template bool CheckAndGetInteger<int64>(PyObject*, int64*);
template bool CheckAndGetInteger<uint32>(PyObject*, uint32*);
template bool CheckAndGetInteger<uint64>(PyObject*, uint64*);
bool CheckAndGetDouble(PyObject* arg, double* value) {
if (!PyInt_Check(arg) && !PyLong_Check(arg) &&
!PyFloat_Check(arg)) {
*value = PyFloat_AsDouble(arg);
if GOOGLE_PREDICT_FALSE(*value == -1 && PyErr_Occurred()) {
FormatTypeError(arg, "int, long, float");
return false;
}
*value = PyFloat_AsDouble(arg);
return true;
}
@ -630,11 +715,13 @@ bool CheckAndGetFloat(PyObject* arg, float* value) {
}
bool CheckAndGetBool(PyObject* arg, bool* value) {
if (!PyInt_Check(arg) && !PyBool_Check(arg) && !PyLong_Check(arg)) {
long long_value = PyInt_AsLong(arg);
if (long_value == -1 && PyErr_Occurred()) {
FormatTypeError(arg, "int, long, bool");
return false;
}
*value = static_cast<bool>(PyInt_AsLong(arg));
*value = static_cast<bool>(long_value);
return true;
}
@ -966,20 +1053,7 @@ int InternalDeleteRepeatedField(
int min, max;
length = reflection->FieldSize(*message, field_descriptor);
if (PyInt_Check(slice) || PyLong_Check(slice)) {
from = to = PyLong_AsLong(slice);
if (from < 0) {
from = to = length + from;
}
step = 1;
min = max = from;
// Range check.
if (from < 0 || from >= length) {
PyErr_Format(PyExc_IndexError, "list assignment index out of range");
return -1;
}
} else if (PySlice_Check(slice)) {
if (PySlice_Check(slice)) {
from = to = step = slice_length = 0;
PySlice_GetIndicesEx(
#if PY_MAJOR_VERSION < 3
@ -996,8 +1070,23 @@ int InternalDeleteRepeatedField(
max = from;
}
} else {
PyErr_SetString(PyExc_TypeError, "list indices must be integers");
return -1;
from = to = PyLong_AsLong(slice);
if (from == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "list indices must be integers");
return -1;
}
if (from < 0) {
from = to = length + from;
}
step = 1;
min = max = from;
// Range check.
if (from < 0 || from >= length) {
PyErr_Format(PyExc_IndexError, "list assignment index out of range");
return -1;
}
}
Py_ssize_t i = from;
@ -1958,99 +2047,29 @@ static PyObject* ByteSize(CMessage* self, PyObject* args) {
return PyLong_FromLong(self->message->ByteSize());
}
static PyObject* RegisterExtension(PyObject* cls,
PyObject* extension_handle) {
PyObject* RegisterExtension(PyObject* cls, PyObject* extension_handle) {
const FieldDescriptor* descriptor =
GetExtensionDescriptor(extension_handle);
if (descriptor == NULL) {
return NULL;
}
ScopedPyObjectPtr extensions_by_name(
PyObject_GetAttr(cls, k_extensions_by_name));
if (extensions_by_name == NULL) {
PyErr_SetString(PyExc_TypeError, "no extensions_by_name on class");
if (!PyObject_TypeCheck(cls, &CMessageClass_Type)) {
PyErr_Format(PyExc_TypeError, "Expected a message class, got %s",
cls->ob_type->tp_name);
return NULL;
}
ScopedPyObjectPtr full_name(PyObject_GetAttr(extension_handle, kfull_name));
if (full_name == NULL) {
CMessageClass *message_class = reinterpret_cast<CMessageClass*>(cls);
if (message_class == NULL) {
return NULL;
}
// If the extension was already registered, check that it is the same.
PyObject* existing_extension =
PyDict_GetItem(extensions_by_name.get(), full_name.get());
if (existing_extension != NULL) {
const FieldDescriptor* existing_extension_descriptor =
GetExtensionDescriptor(existing_extension);
if (existing_extension_descriptor != descriptor) {
PyErr_SetString(PyExc_ValueError, "Double registration of Extensions");
return NULL;
}
// Nothing else to do.
Py_RETURN_NONE;
}
if (PyDict_SetItem(extensions_by_name.get(), full_name.get(),
extension_handle) < 0) {
const FieldDescriptor* existing_extension =
message_class->py_message_factory->pool->pool->FindExtensionByNumber(
descriptor->containing_type(), descriptor->number());
if (existing_extension != NULL && existing_extension != descriptor) {
PyErr_SetString(PyExc_ValueError, "Double registration of Extensions");
return NULL;
}
// Also store a mapping from extension number to implementing class.
ScopedPyObjectPtr extensions_by_number(
PyObject_GetAttr(cls, k_extensions_by_number));
if (extensions_by_number == NULL) {
PyErr_SetString(PyExc_TypeError, "no extensions_by_number on class");
return NULL;
}
ScopedPyObjectPtr number(PyObject_GetAttrString(extension_handle, "number"));
if (number == NULL) {
return NULL;
}
// If the extension was already registered by number, check that it is the
// same.
existing_extension = PyDict_GetItem(extensions_by_number.get(), number.get());
if (existing_extension != NULL) {
const FieldDescriptor* existing_extension_descriptor =
GetExtensionDescriptor(existing_extension);
if (existing_extension_descriptor != descriptor) {
const Descriptor* msg_desc = GetMessageDescriptor(
reinterpret_cast<PyTypeObject*>(cls));
PyErr_Format(
PyExc_ValueError,
"Extensions \"%s\" and \"%s\" both try to extend message type "
"\"%s\" with field number %ld.",
existing_extension_descriptor->full_name().c_str(),
descriptor->full_name().c_str(),
msg_desc->full_name().c_str(),
PyInt_AsLong(number.get()));
return NULL;
}
// Nothing else to do.
Py_RETURN_NONE;
}
if (PyDict_SetItem(extensions_by_number.get(), number.get(),
extension_handle) < 0) {
return NULL;
}
// Check if it's a message set
if (descriptor->is_extension() &&
descriptor->containing_type()->options().message_set_wire_format() &&
descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
descriptor->label() == FieldDescriptor::LABEL_OPTIONAL) {
ScopedPyObjectPtr message_name(PyString_FromStringAndSize(
descriptor->message_type()->full_name().c_str(),
descriptor->message_type()->full_name().size()));
if (message_name == NULL) {
return NULL;
}
PyDict_SetItem(extensions_by_name.get(), message_name.get(),
extension_handle);
}
Py_RETURN_NONE;
}
@ -2087,7 +2106,7 @@ static PyObject* WhichOneof(CMessage* self, PyObject* arg) {
static PyObject* GetExtensionDict(CMessage* self, void *closure);
static PyObject* ListFields(CMessage* self) {
vector<const FieldDescriptor*> fields;
std::vector<const FieldDescriptor*> fields;
self->message->GetReflection()->ListFields(*self->message, &fields);
// Normally, the list will be exactly the size of the fields.
@ -2178,7 +2197,7 @@ static PyObject* DiscardUnknownFields(CMessage* self) {
PyObject* FindInitializationErrors(CMessage* self) {
Message* message = self->message;
vector<string> errors;
std::vector<string> errors;
message->FindInitializationErrors(&errors);
PyObject* error_list = PyList_New(errors.size());
@ -2570,11 +2589,24 @@ static PyObject* GetExtensionDict(CMessage* self, void *closure) {
return NULL;
}
static PyObject* GetExtensionsByName(CMessage *self, void *closure) {
return message_meta::GetExtensionsByName(
reinterpret_cast<CMessageClass*>(Py_TYPE(self)), closure);
}
static PyObject* GetExtensionsByNumber(CMessage *self, void *closure) {
return message_meta::GetExtensionsByNumber(
reinterpret_cast<CMessageClass*>(Py_TYPE(self)), closure);
}
static PyGetSetDef Getters[] = {
{"Extensions", (getter)GetExtensionDict, NULL, "Extension dict"},
{"_extensions_by_name", (getter)GetExtensionsByName, NULL},
{"_extensions_by_number", (getter)GetExtensionsByNumber, NULL},
{NULL}
};
static PyMethodDef Methods[] = {
{ "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
"Makes a deep copy of the class." },
@ -2835,19 +2867,7 @@ void InitGlobals() {
// TODO(gps): Check all return values in this function for NULL and propagate
// the error (MemoryError) on up to result in an import failure. These should
// also be freed and reset to NULL during finalization.
kPythonZero = PyInt_FromLong(0);
kint32min_py = PyInt_FromLong(kint32min);
kint32max_py = PyInt_FromLong(kint32max);
kuint32max_py = PyLong_FromLongLong(kuint32max);
kint64min_py = PyLong_FromLongLong(kint64min);
kint64max_py = PyLong_FromLongLong(kint64max);
kuint64max_py = PyLong_FromUnsignedLongLong(kuint64max);
kDESCRIPTOR = PyString_FromString("DESCRIPTOR");
k_cdescriptor = PyString_FromString("_cdescriptor");
kfull_name = PyString_FromString("full_name");
k_extensions_by_name = PyString_FromString("_extensions_by_name");
k_extensions_by_number = PyString_FromString("_extensions_by_number");
PyObject *dummy_obj = PySet_New(NULL);
kEmptyWeakref = PyWeakref_NewRef(dummy_obj, NULL);
@ -2887,25 +2907,6 @@ bool InitProto2MessageModule(PyObject *m) {
// DESCRIPTOR is set on each protocol buffer message class elsewhere, but set
// it here as well to document that subclasses need to set it.
PyDict_SetItem(CMessage_Type.tp_dict, kDESCRIPTOR, Py_None);
// Subclasses with message extensions will override _extensions_by_name and
// _extensions_by_number with fresh mutable dictionaries in AddDescriptors.
// All other classes can share this same immutable mapping.
ScopedPyObjectPtr empty_dict(PyDict_New());
if (empty_dict == NULL) {
return false;
}
ScopedPyObjectPtr immutable_dict(PyDictProxy_New(empty_dict.get()));
if (immutable_dict == NULL) {
return false;
}
if (PyDict_SetItem(CMessage_Type.tp_dict,
k_extensions_by_name, immutable_dict.get()) < 0) {
return false;
}
if (PyDict_SetItem(CMessage_Type.tp_dict,
k_extensions_by_number, immutable_dict.get()) < 0) {
return false;
}
PyModule_AddObject(m, "Message", reinterpret_cast<PyObject*>(&CMessage_Type));

View File

@ -117,6 +117,7 @@ typedef struct CMessage {
PyObject* weakreflist;
} CMessage;
extern PyTypeObject CMessageClass_Type;
extern PyTypeObject CMessage_Type;
@ -235,6 +236,10 @@ int InitAttributes(CMessage* self, PyObject* args, PyObject* kwargs);
PyObject* MergeFrom(CMessage* self, PyObject* arg);
// This method does not do anything beyond checking that no other extension
// 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.
//
@ -275,25 +280,25 @@ PyObject* SetAllowOversizeProtos(PyObject* m, PyObject* arg);
#define GOOGLE_CHECK_GET_INT32(arg, value, err) \
int32 value; \
if (!CheckAndGetInteger(arg, &value, kint32min_py, kint32max_py)) { \
if (!CheckAndGetInteger(arg, &value)) { \
return err; \
}
#define GOOGLE_CHECK_GET_INT64(arg, value, err) \
int64 value; \
if (!CheckAndGetInteger(arg, &value, kint64min_py, kint64max_py)) { \
if (!CheckAndGetInteger(arg, &value)) { \
return err; \
}
#define GOOGLE_CHECK_GET_UINT32(arg, value, err) \
uint32 value; \
if (!CheckAndGetInteger(arg, &value, kPythonZero, kuint32max_py)) { \
if (!CheckAndGetInteger(arg, &value)) { \
return err; \
}
#define GOOGLE_CHECK_GET_UINT64(arg, value, err) \
uint64 value; \
if (!CheckAndGetInteger(arg, &value, kPythonZero, kuint64max_py)) { \
if (!CheckAndGetInteger(arg, &value)) { \
return err; \
}
@ -316,20 +321,11 @@ PyObject* SetAllowOversizeProtos(PyObject* m, PyObject* arg);
}
extern PyObject* kPythonZero;
extern PyObject* kint32min_py;
extern PyObject* kint32max_py;
extern PyObject* kuint32max_py;
extern PyObject* kint64min_py;
extern PyObject* kint64max_py;
extern PyObject* kuint64max_py;
#define FULL_MODULE_NAME "google.protobuf.pyext._message"
void FormatTypeError(PyObject* arg, char* expected_types);
template<class T>
bool CheckAndGetInteger(
PyObject* arg, T* value, PyObject* min, PyObject* max);
bool CheckAndGetInteger(PyObject* arg, T* value);
bool CheckAndGetDouble(PyObject* arg, double* value);
bool CheckAndGetFloat(PyObject* arg, float* value);
bool CheckAndGetBool(PyObject* arg, bool* value);

View File

@ -130,6 +130,72 @@ int RegisterMessageClass(PyMessageFactory* self,
return 0;
}
CMessageClass* GetOrCreateMessageClass(PyMessageFactory* self,
const Descriptor* descriptor) {
// This is the same implementation as MessageFactory.GetPrototype().
ScopedPyObjectPtr py_descriptor(
PyMessageDescriptor_FromDescriptor(descriptor));
if (py_descriptor == NULL) {
return NULL;
}
// Do not create a MessageClass that already exists.
hash_map<const Descriptor*, CMessageClass*>::iterator it =
self->classes_by_descriptor->find(descriptor);
if (it != self->classes_by_descriptor->end()) {
Py_INCREF(it->second);
return it->second;
}
// Create a new message class.
ScopedPyObjectPtr args(Py_BuildValue(
"s(){sOsOsO}", descriptor->name().c_str(),
"DESCRIPTOR", py_descriptor.get(),
"__module__", Py_None,
"message_factory", self));
if (args == NULL) {
return NULL;
}
ScopedPyObjectPtr message_class(PyObject_CallObject(
reinterpret_cast<PyObject*>(&CMessageClass_Type), args.get()));
if (message_class == NULL) {
return NULL;
}
// Create messages class for the messages used by the fields, and registers
// all extensions for these messages during the recursion.
for (int field_idx = 0; field_idx < descriptor->field_count(); field_idx++) {
const Descriptor* sub_descriptor =
descriptor->field(field_idx)->message_type();
// It is NULL if the field type is not a message.
if (sub_descriptor != NULL) {
CMessageClass* result = GetOrCreateMessageClass(self, sub_descriptor);
if (result == NULL) {
return NULL;
}
Py_DECREF(result);
}
}
// Register extensions defined in this message.
for (int ext_idx = 0 ; ext_idx < descriptor->extension_count() ; ext_idx++) {
const FieldDescriptor* extension = descriptor->extension(ext_idx);
ScopedPyObjectPtr py_extended_class(
GetOrCreateMessageClass(self, extension->containing_type())
->AsPyObject());
if (py_extended_class == NULL) {
return NULL;
}
ScopedPyObjectPtr py_extension(PyFieldDescriptor_FromDescriptor(extension));
if (py_extension == NULL) {
return NULL;
}
ScopedPyObjectPtr result(cmessage::RegisterExtension(
py_extended_class.get(), py_extension.get()));
if (result == NULL) {
return NULL;
}
}
return reinterpret_cast<CMessageClass*>(message_class.release());
}
// Retrieve the message class added to our database.
CMessageClass* GetMessageClass(PyMessageFactory* self,
const Descriptor* message_descriptor) {

View File

@ -82,14 +82,14 @@ PyMessageFactory* NewMessageFactory(PyTypeObject* type, PyDescriptorPool* pool);
int RegisterMessageClass(PyMessageFactory* self,
const Descriptor* message_descriptor,
CMessageClass* message_class);
// Retrieves the Python class registered with the given message descriptor.
//
// Returns a *borrowed* reference if found, otherwise returns NULL with an
// exception set.
// Retrieves the Python class registered with the given message descriptor, or
// fail with a TypeError. Returns a *borrowed* reference.
CMessageClass* GetMessageClass(PyMessageFactory* self,
const Descriptor* message_descriptor);
// Retrieves the Python class registered with the given message descriptor.
// The class is created if not done yet. Returns a *new* reference.
CMessageClass* GetOrCreateMessageClass(PyMessageFactory* self,
const Descriptor* message_descriptor);
} // namespace message_factory
// Initialize objects used by this module.

View File

@ -0,0 +1,164 @@
// 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.
#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_SAFE_NUMERICS_H__
#define GOOGLE_PROTOBUF_PYTHON_CPP_SAFE_NUMERICS_H__
// Copied from chromium with only changes to the namespace.
#include <limits>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
namespace google {
namespace protobuf {
namespace python {
template <bool SameSize, bool DestLarger,
bool DestIsSigned, bool SourceIsSigned>
struct IsValidNumericCastImpl;
#define BASE_NUMERIC_CAST_CASE_SPECIALIZATION(A, B, C, D, Code) \
template <> struct IsValidNumericCastImpl<A, B, C, D> { \
template <class Source, class DestBounds> static inline bool Test( \
Source source, DestBounds min, DestBounds max) { \
return Code; \
} \
}
#define BASE_NUMERIC_CAST_CASE_SAME_SIZE(DestSigned, SourceSigned, Code) \
BASE_NUMERIC_CAST_CASE_SPECIALIZATION( \
true, true, DestSigned, SourceSigned, Code); \
BASE_NUMERIC_CAST_CASE_SPECIALIZATION( \
true, false, DestSigned, SourceSigned, Code)
#define BASE_NUMERIC_CAST_CASE_SOURCE_LARGER(DestSigned, SourceSigned, Code) \
BASE_NUMERIC_CAST_CASE_SPECIALIZATION( \
false, false, DestSigned, SourceSigned, Code); \
#define BASE_NUMERIC_CAST_CASE_DEST_LARGER(DestSigned, SourceSigned, Code) \
BASE_NUMERIC_CAST_CASE_SPECIALIZATION( \
false, true, DestSigned, SourceSigned, Code); \
// The three top level cases are:
// - Same size
// - Source larger
// - Dest larger
// And for each of those three cases, we handle the 4 different possibilities
// of signed and unsigned. This gives 12 cases to handle, which we enumerate
// below.
//
// The last argument in each of the macros is the actual comparison code. It
// has three arguments available, source (the value), and min/max which are
// the ranges of the destination.
// These are the cases where both types have the same size.
// Both signed.
BASE_NUMERIC_CAST_CASE_SAME_SIZE(true, true, true);
// Both unsigned.
BASE_NUMERIC_CAST_CASE_SAME_SIZE(false, false, true);
// Dest unsigned, Source signed.
BASE_NUMERIC_CAST_CASE_SAME_SIZE(false, true, source >= 0);
// Dest signed, Source unsigned.
// This cast is OK because Dest's max must be less than Source's.
BASE_NUMERIC_CAST_CASE_SAME_SIZE(true, false,
source <= static_cast<Source>(max));
// These are the cases where Source is larger.
// Both unsigned.
BASE_NUMERIC_CAST_CASE_SOURCE_LARGER(false, false, source <= max);
// Both signed.
BASE_NUMERIC_CAST_CASE_SOURCE_LARGER(true, true,
source >= min && source <= max);
// Dest is unsigned, Source is signed.
BASE_NUMERIC_CAST_CASE_SOURCE_LARGER(false, true,
source >= 0 && source <= max);
// Dest is signed, Source is unsigned.
// This cast is OK because Dest's max must be less than Source's.
BASE_NUMERIC_CAST_CASE_SOURCE_LARGER(true, false,
source <= static_cast<Source>(max));
// These are the cases where Dest is larger.
// Both unsigned.
BASE_NUMERIC_CAST_CASE_DEST_LARGER(false, false, true);
// Both signed.
BASE_NUMERIC_CAST_CASE_DEST_LARGER(true, true, true);
// Dest is unsigned, Source is signed.
BASE_NUMERIC_CAST_CASE_DEST_LARGER(false, true, source >= 0);
// Dest is signed, Source is unsigned.
BASE_NUMERIC_CAST_CASE_DEST_LARGER(true, false, true);
#undef BASE_NUMERIC_CAST_CASE_SPECIALIZATION
#undef BASE_NUMERIC_CAST_CASE_SAME_SIZE
#undef BASE_NUMERIC_CAST_CASE_SOURCE_LARGER
#undef BASE_NUMERIC_CAST_CASE_DEST_LARGER
// The main test for whether the conversion will under or overflow.
template <class Dest, class Source>
inline bool IsValidNumericCast(Source source) {
typedef std::numeric_limits<Source> SourceLimits;
typedef std::numeric_limits<Dest> DestLimits;
GOOGLE_COMPILE_ASSERT(SourceLimits::is_specialized, argument_must_be_numeric);
GOOGLE_COMPILE_ASSERT(SourceLimits::is_integer, argument_must_be_integral);
GOOGLE_COMPILE_ASSERT(DestLimits::is_specialized, result_must_be_numeric);
GOOGLE_COMPILE_ASSERT(DestLimits::is_integer, result_must_be_integral);
return IsValidNumericCastImpl<
sizeof(Dest) == sizeof(Source),
(sizeof(Dest) > sizeof(Source)),
DestLimits::is_signed,
SourceLimits::is_signed>::Test(
source,
DestLimits::min(),
DestLimits::max());
}
// checked_numeric_cast<> is analogous to static_cast<> for numeric types,
// except that it CHECKs that the specified numeric conversion will not
// overflow or underflow. Floating point arguments are not currently allowed
// (this is COMPILE_ASSERTd), though this could be supported if necessary.
template <class Dest, class Source>
inline Dest checked_numeric_cast(Source source) {
GOOGLE_CHECK(IsValidNumericCast<Dest>(source));
return static_cast<Dest>(source);
}
} // namespace python
} // namespace protobuf
} // namespace google
#endif // GOOGLE_PROTOBUF_PYTHON_CPP_SAFE_NUMERICS_H__

View File

@ -161,6 +161,7 @@ nobase_include_HEADERS = \
google/protobuf/compiler/java/java_names.h \
google/protobuf/compiler/javanano/javanano_generator.h \
google/protobuf/compiler/js/js_generator.h \
google/protobuf/compiler/js/well_known_types_embed.h \
google/protobuf/compiler/objectivec/objectivec_generator.h \
google/protobuf/compiler/objectivec/objectivec_helpers.h \
google/protobuf/compiler/php/php_generator.h \
@ -399,6 +400,7 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/java/java_doc_comment.cc \
google/protobuf/compiler/java/java_doc_comment.h \
google/protobuf/compiler/js/js_generator.cc \
google/protobuf/compiler/js/well_known_types_embed.cc \
google/protobuf/compiler/javanano/javanano_enum.cc \
google/protobuf/compiler/javanano/javanano_enum.h \
google/protobuf/compiler/javanano/javanano_enum_field.cc \

View File

@ -30,6 +30,8 @@
#include <google/protobuf/any.h>
#include <google/protobuf/generated_message_util.h>
namespace google {
namespace protobuf {
namespace internal {
@ -70,13 +72,11 @@ bool AnyMetadata::UnpackTo(Message* message) const {
if (!InternalIs(message->GetDescriptor())) {
return false;
}
return message->ParseFromString(
value_->GetNoArena(&::google::protobuf::internal::GetEmptyString()));
return message->ParseFromString(value_->GetNoArena());
}
bool AnyMetadata::InternalIs(const Descriptor* descriptor) const {
const string type_url = type_url_->GetNoArena(
&::google::protobuf::internal::GetEmptyString());
const string type_url = type_url_->GetNoArena();
string full_name;
if (!ParseAnyTypeUrl(type_url, &full_name)) {
return false;

View File

@ -19,86 +19,88 @@
namespace google {
namespace protobuf {
class AnyDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Any> {};
AnyDefaultTypeInternal _Any_default_instance_;
namespace {
const ::google::protobuf::Descriptor* Any_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
Any_reflection_ = NULL;
::google::protobuf::Metadata file_level_metadata[1];
} // namespace
void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto() GOOGLE_ATTRIBUTE_COLD;
void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto() {
protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
const ::google::protobuf::FileDescriptor* file =
::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
"google/protobuf/any.proto");
GOOGLE_CHECK(file != NULL);
Any_descriptor_ = file->message_type(0);
static const int Any_offsets_[2] = {
const ::google::protobuf::uint32* protobuf_Offsets_google_2fprotobuf_2fany_2eproto() GOOGLE_ATTRIBUTE_COLD;
const ::google::protobuf::uint32* protobuf_Offsets_google_2fprotobuf_2fany_2eproto() {
static const ::google::protobuf::uint32 offsets[] = {
~0u, // no _has_bits_
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, _internal_metadata_),
~0u, // no _extensions_
~0u, // no _oneof_case_
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, type_url_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, value_),
};
Any_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
Any_descriptor_,
Any::internal_default_instance(),
Any_offsets_,
-1,
-1,
-1,
sizeof(Any),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, _internal_metadata_));
return offsets;
}
static const ::google::protobuf::internal::MigrationSchema schemas[] = {
{ 0, -1, sizeof(Any)},
};
static const ::google::protobuf::internal::DefaultInstanceData file_default_instances[] = {
{reinterpret_cast<const ::google::protobuf::Message*>(&_Any_default_instance_), NULL},
};
namespace {
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
void protobuf_AssignDescriptors() {
protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
::google::protobuf::MessageFactory* factory = NULL;
AssignDescriptors(
"google/protobuf/any.proto", schemas, file_default_instances, protobuf_Offsets_google_2fprotobuf_2fany_2eproto(), factory,
file_level_metadata, NULL, NULL);
}
void protobuf_AssignDescriptorsOnce() {
::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
&protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto);
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
}
void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
Any_descriptor_, Any::internal_default_instance());
::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1);
}
} // namespace
void protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto() {
Any_default_instance_.Shutdown();
delete Any_reflection_;
_Any_default_instance_.Shutdown();
delete file_level_metadata[0].reflection;
}
void protobuf_InitDefaults_google_2fprotobuf_2fany_2eproto_impl() {
GOOGLE_PROTOBUF_VERIFY_VERSION;
::google::protobuf::internal::GetEmptyString();
Any_default_instance_.DefaultConstruct();
Any_default_instance_.get_mutable()->InitAsDefaultInstance();
::google::protobuf::internal::InitProtobufDefaults();
_Any_default_instance_.DefaultConstruct();
}
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_InitDefaults_google_2fprotobuf_2fany_2eproto_once_);
void protobuf_InitDefaults_google_2fprotobuf_2fany_2eproto() {
::google::protobuf::GoogleOnceInit(&protobuf_InitDefaults_google_2fprotobuf_2fany_2eproto_once_,
&protobuf_InitDefaults_google_2fprotobuf_2fany_2eproto_impl);
static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
::google::protobuf::GoogleOnceInit(&once, &protobuf_InitDefaults_google_2fprotobuf_2fany_2eproto_impl);
}
void protobuf_AddDesc_google_2fprotobuf_2fany_2eproto_impl() {
GOOGLE_PROTOBUF_VERIFY_VERSION;
protobuf_InitDefaults_google_2fprotobuf_2fany_2eproto();
static const char descriptor[] = {
"\n\031google/protobuf/any.proto\022\017google.prot"
"obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002"
" \001(\014Bo\n\023com.google.protobufB\010AnyProtoP\001Z"
"%github.com/golang/protobuf/ptypes/any\242\002"
"\003GPB\252\002\036Google.Protobuf.WellKnownTypesb\006p"
"roto3"
};
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n\031google/protobuf/any.proto\022\017google.prot"
"obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002"
" \001(\014Bo\n\023com.google.protobufB\010AnyProtoP\001Z"
"%github.com/golang/protobuf/ptypes/any\242\002"
"\003GPB\252\002\036Google.Protobuf.WellKnownTypesb\006p"
"roto3", 205);
descriptor, 205);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/any.proto", &protobuf_RegisterTypes);
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto);
@ -116,16 +118,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fany_2eproto {
}
} static_descriptor_initializer_google_2fprotobuf_2fany_2eproto_;
namespace {
static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD GOOGLE_ATTRIBUTE_NORETURN;
static void MergeFromFail(int line) {
::google::protobuf::internal::MergeFromFail(__FILE__, line);
}
} // namespace
// ===================================================================
void Any::PackFrom(const ::google::protobuf::Message& message) {
@ -148,20 +140,26 @@ const int Any::kValueFieldNumber;
Any::Any()
: ::google::protobuf::Message(), _internal_metadata_(NULL), _any_metadata_(&type_url_, &value_) {
if (this != internal_default_instance()) protobuf_InitDefaults_google_2fprotobuf_2fany_2eproto();
if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
protobuf_InitDefaults_google_2fprotobuf_2fany_2eproto();
}
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Any)
}
void Any::InitAsDefaultInstance() {
}
Any::Any(const Any& from)
: ::google::protobuf::Message(),
_internal_metadata_(NULL),
_any_metadata_(&type_url_, &value_) {
SharedCtor();
UnsafeMergeFrom(from);
_internal_metadata_(NULL),
_cached_size_(0),
_any_metadata_(&type_url_, &value_) {
_internal_metadata_.MergeFrom(from._internal_metadata_);
type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (from.type_url().size() > 0) {
type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_);
}
value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (from.value().size() > 0) {
value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.value_);
}
// @@protoc_insertion_point(copy_constructor:google.protobuf.Any)
}
@ -188,7 +186,7 @@ void Any::SetCachedSize(int size) const {
}
const ::google::protobuf::Descriptor* Any::descriptor() {
protobuf_AssignDescriptorsOnce();
return Any_descriptor_;
return file_level_metadata[0].descriptor;
}
const Any& Any::default_instance() {
@ -196,8 +194,6 @@ const Any& Any::default_instance() {
return *internal_default_instance();
}
::google::protobuf::internal::ExplicitlyConstructed<Any> Any_default_instance_;
Any* Any::New(::google::protobuf::Arena* arena) const {
Any* n = new Any;
if (arena != NULL) {
@ -218,11 +214,11 @@ bool Any::MergePartialFromCodedStream(
::google::protobuf::uint32 tag;
// @@protoc_insertion_point(parse_start:google.protobuf.Any)
for (;;) {
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127);
tag = p.first;
if (!p.second) goto handle_unusual;
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// optional string type_url = 1;
// string type_url = 1;
case 1: {
if (tag == 10) {
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
@ -234,20 +230,17 @@ bool Any::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
if (input->ExpectTag(18)) goto parse_value;
break;
}
// optional bytes value = 2;
// bytes value = 2;
case 2: {
if (tag == 18) {
parse_value:
DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
input, this->mutable_value()));
} else {
goto handle_unusual;
}
if (input->ExpectAtEnd()) goto success;
break;
}
@ -275,7 +268,7 @@ failure:
void Any::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
// @@protoc_insertion_point(serialize_start:google.protobuf.Any)
// optional string type_url = 1;
// string type_url = 1;
if (this->type_url().size() > 0) {
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->type_url().data(), this->type_url().length(),
@ -285,7 +278,7 @@ void Any::SerializeWithCachedSizes(
1, this->type_url(), output);
}
// optional bytes value = 2;
// bytes value = 2;
if (this->value().size() > 0) {
::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
2, this->value(), output);
@ -298,7 +291,7 @@ void Any::SerializeWithCachedSizes(
bool deterministic, ::google::protobuf::uint8* target) const {
(void)deterministic; // Unused
// @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any)
// optional string type_url = 1;
// string type_url = 1;
if (this->type_url().size() > 0) {
::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
this->type_url().data(), this->type_url().length(),
@ -309,7 +302,7 @@ void Any::SerializeWithCachedSizes(
1, this->type_url(), target);
}
// optional bytes value = 2;
// bytes value = 2;
if (this->value().size() > 0) {
target =
::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
@ -324,14 +317,14 @@ size_t Any::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any)
size_t total_size = 0;
// optional string type_url = 1;
// string type_url = 1;
if (this->type_url().size() > 0) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::StringSize(
this->type_url());
}
// optional bytes value = 2;
// bytes value = 2;
if (this->value().size() > 0) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::BytesSize(
@ -347,7 +340,7 @@ size_t Any::ByteSizeLong() const {
void Any::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Any)
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
GOOGLE_DCHECK_NE(&from, this);
const Any* source =
::google::protobuf::internal::DynamicCastToGenerated<const Any>(
&from);
@ -356,21 +349,14 @@ void Any::MergeFrom(const ::google::protobuf::Message& from) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
// @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Any)
UnsafeMergeFrom(*source);
MergeFrom(*source);
}
}
void Any::MergeFrom(const Any& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any)
if (GOOGLE_PREDICT_TRUE(&from != this)) {
UnsafeMergeFrom(from);
} else {
MergeFromFail(__LINE__);
}
}
void Any::UnsafeMergeFrom(const Any& from) {
GOOGLE_DCHECK(&from != this);
GOOGLE_DCHECK_NE(&from, this);
_internal_metadata_.MergeFrom(from._internal_metadata_);
if (from.type_url().size() > 0) {
type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_);
@ -392,11 +378,10 @@ void Any::CopyFrom(const Any& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Any)
if (&from == this) return;
Clear();
UnsafeMergeFrom(from);
MergeFrom(from);
}
bool Any::IsInitialized() const {
return true;
}
@ -407,28 +392,24 @@ void Any::Swap(Any* other) {
void Any::InternalSwap(Any* other) {
type_url_.Swap(&other->type_url_);
value_.Swap(&other->value_);
_internal_metadata_.Swap(&other->_internal_metadata_);
std::swap(_cached_size_, other->_cached_size_);
}
::google::protobuf::Metadata Any::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
::google::protobuf::Metadata metadata;
metadata.descriptor = Any_descriptor_;
metadata.reflection = Any_reflection_;
return metadata;
return file_level_metadata[0];
}
#if PROTOBUF_INLINE_NOT_IN_HEADERS
// Any
// optional string type_url = 1;
// string type_url = 1;
void Any::clear_type_url() {
type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& Any::type_url() const {
// @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
return type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return type_url_.GetNoArena();
}
void Any::set_type_url(const ::std::string& value) {
@ -466,13 +447,13 @@ void Any::set_allocated_type_url(::std::string* type_url) {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
}
// optional bytes value = 2;
// bytes value = 2;
void Any::clear_value() {
value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& Any::value() const {
// @@protoc_insertion_point(field_get:google.protobuf.Any.value)
return value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return value_.GetNoArena();
}
void Any::set_value(const ::std::string& value) {
@ -510,9 +491,6 @@ void Any::set_allocated_value(::std::string* value) {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
}
inline const Any* Any::internal_default_instance() {
return &Any_default_instance_.get();
}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// @@protoc_insertion_point(namespace_scope)

View File

@ -24,11 +24,18 @@
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/metadata.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
#include <google/protobuf/extension_set.h> // IWYU pragma: export
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/any.h>
// @@protoc_insertion_point(includes)
namespace google {
namespace protobuf {
class Any;
class AnyDefaultTypeInternal;
extern AnyDefaultTypeInternal _Any_default_instance_;
} // namespace protobuf
} // namespace google
namespace google {
namespace protobuf {
@ -36,10 +43,6 @@ namespace protobuf {
// Internal implementation detail -- do not call these.
void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
void LIBPROTOBUF_EXPORT protobuf_InitDefaults_google_2fprotobuf_2fany_2eproto();
void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto();
void protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto();
class Any;
// ===================================================================
@ -58,7 +61,10 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_in
static const ::google::protobuf::Descriptor* descriptor();
static const Any& default_instance();
static const Any* internal_default_instance();
static inline const Any* internal_default_instance() {
return reinterpret_cast<const Any*>(
&_Any_default_instance_);
}
// implements Any -----------------------------------------------
@ -74,49 +80,49 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_in
// implements Message ----------------------------------------------
inline Any* New() const { return New(NULL); }
inline Any* New() const PROTOBUF_FINAL { return New(NULL); }
Any* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
Any* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void CopyFrom(const Any& from);
void MergeFrom(const Any& from);
void Clear();
bool IsInitialized() const;
void Clear() PROTOBUF_FINAL;
bool IsInitialized() const PROTOBUF_FINAL;
size_t ByteSizeLong() const;
size_t ByteSizeLong() const PROTOBUF_FINAL;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
bool deterministic, ::google::protobuf::uint8* output) const;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output)
const PROTOBUF_FINAL {
return InternalSerializeWithCachedSizesToArray(false, output);
}
int GetCachedSize() const { return _cached_size_; }
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
void SetCachedSize(int size) const PROTOBUF_FINAL;
void InternalSwap(Any* other);
void UnsafeMergeFrom(const Any& from);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return _internal_metadata_.arena();
return NULL;
}
inline void* MaybeArenaPtr() const {
return _internal_metadata_.raw_arena_ptr();
return NULL;
}
public:
::google::protobuf::Metadata GetMetadata() const;
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// optional string type_url = 1;
// string type_url = 1;
void clear_type_url();
static const int kTypeUrlFieldNumber = 1;
const ::std::string& type_url() const;
@ -127,7 +133,7 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_in
::std::string* release_type_url();
void set_allocated_type_url(::std::string* type_url);
// optional bytes value = 2;
// bytes value = 2;
void clear_value();
static const int kValueFieldNumber = 2;
const ::std::string& value() const;
@ -148,13 +154,10 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message /* @@protoc_in
::google::protobuf::internal::AnyMetadata _any_metadata_;
friend void LIBPROTOBUF_EXPORT protobuf_InitDefaults_google_2fprotobuf_2fany_2eproto_impl();
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fany_2eproto_impl();
friend void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto();
friend const ::google::protobuf::uint32* protobuf_Offsets_google_2fprotobuf_2fany_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto();
void InitAsDefaultInstance();
};
extern ::google::protobuf::internal::ExplicitlyConstructed<Any> Any_default_instance_;
// ===================================================================
@ -163,13 +166,13 @@ extern ::google::protobuf::internal::ExplicitlyConstructed<Any> Any_default_inst
#if !PROTOBUF_INLINE_NOT_IN_HEADERS
// Any
// optional string type_url = 1;
// string type_url = 1;
inline void Any::clear_type_url() {
type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Any::type_url() const {
// @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
return type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return type_url_.GetNoArena();
}
inline void Any::set_type_url(const ::std::string& value) {
@ -207,13 +210,13 @@ inline void Any::set_allocated_type_url(::std::string* type_url) {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.type_url)
}
// optional bytes value = 2;
// bytes value = 2;
inline void Any::clear_value() {
value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Any::value() const {
// @@protoc_insertion_point(field_get:google.protobuf.Any.value)
return value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return value_.GetNoArena();
}
inline void Any::set_value(const ::std::string& value) {
@ -251,13 +254,11 @@ inline void Any::set_allocated_value(::std::string* value) {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
}
inline const Any* Any::internal_default_instance() {
return &Any_default_instance_.get();
}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
// @@protoc_insertion_point(namespace_scope)
} // namespace protobuf
} // namespace google

File diff suppressed because it is too large Load Diff

View File

@ -24,12 +24,43 @@
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/metadata.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/repeated_field.h> // IWYU pragma: export
#include <google/protobuf/extension_set.h> // IWYU pragma: export
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/source_context.pb.h>
#include <google/protobuf/type.pb.h>
// @@protoc_insertion_point(includes)
namespace google {
namespace protobuf {
class Api;
class ApiDefaultTypeInternal;
extern ApiDefaultTypeInternal _Api_default_instance_;
class Enum;
class EnumDefaultTypeInternal;
extern EnumDefaultTypeInternal _Enum_default_instance_;
class EnumValue;
class EnumValueDefaultTypeInternal;
extern EnumValueDefaultTypeInternal _EnumValue_default_instance_;
class Field;
class FieldDefaultTypeInternal;
extern FieldDefaultTypeInternal _Field_default_instance_;
class Method;
class MethodDefaultTypeInternal;
extern MethodDefaultTypeInternal _Method_default_instance_;
class Mixin;
class MixinDefaultTypeInternal;
extern MixinDefaultTypeInternal _Mixin_default_instance_;
class Option;
class OptionDefaultTypeInternal;
extern OptionDefaultTypeInternal _Option_default_instance_;
class SourceContext;
class SourceContextDefaultTypeInternal;
extern SourceContextDefaultTypeInternal _SourceContext_default_instance_;
class Type;
class TypeDefaultTypeInternal;
extern TypeDefaultTypeInternal _Type_default_instance_;
} // namespace protobuf
} // namespace google
namespace google {
namespace protobuf {
@ -37,12 +68,6 @@ namespace protobuf {
// Internal implementation detail -- do not call these.
void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto();
void LIBPROTOBUF_EXPORT protobuf_InitDefaults_google_2fprotobuf_2fapi_2eproto();
void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto();
void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto();
class Api;
class Method;
class Mixin;
// ===================================================================
@ -61,55 +86,58 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_in
static const ::google::protobuf::Descriptor* descriptor();
static const Api& default_instance();
static const Api* internal_default_instance();
static inline const Api* internal_default_instance() {
return reinterpret_cast<const Api*>(
&_Api_default_instance_);
}
void Swap(Api* other);
// implements Message ----------------------------------------------
inline Api* New() const { return New(NULL); }
inline Api* New() const PROTOBUF_FINAL { return New(NULL); }
Api* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
Api* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void CopyFrom(const Api& from);
void MergeFrom(const Api& from);
void Clear();
bool IsInitialized() const;
void Clear() PROTOBUF_FINAL;
bool IsInitialized() const PROTOBUF_FINAL;
size_t ByteSizeLong() const;
size_t ByteSizeLong() const PROTOBUF_FINAL;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
bool deterministic, ::google::protobuf::uint8* output) const;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output)
const PROTOBUF_FINAL {
return InternalSerializeWithCachedSizesToArray(false, output);
}
int GetCachedSize() const { return _cached_size_; }
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
void SetCachedSize(int size) const PROTOBUF_FINAL;
void InternalSwap(Api* other);
void UnsafeMergeFrom(const Api& from);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return _internal_metadata_.arena();
return NULL;
}
inline void* MaybeArenaPtr() const {
return _internal_metadata_.raw_arena_ptr();
return NULL;
}
public:
::google::protobuf::Metadata GetMetadata() const;
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// optional string name = 1;
// string name = 1;
void clear_name();
static const int kNameFieldNumber = 1;
const ::std::string& name() const;
@ -144,7 +172,7 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_in
const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
options() const;
// optional string version = 4;
// string version = 4;
void clear_version();
static const int kVersionFieldNumber = 4;
const ::std::string& version() const;
@ -155,7 +183,7 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_in
::std::string* release_version();
void set_allocated_version(::std::string* version);
// optional .google.protobuf.SourceContext source_context = 5;
// .google.protobuf.SourceContext source_context = 5;
bool has_source_context() const;
void clear_source_context();
static const int kSourceContextFieldNumber = 5;
@ -176,7 +204,7 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_in
const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Mixin >&
mixins() const;
// optional .google.protobuf.Syntax syntax = 7;
// .google.protobuf.Syntax syntax = 7;
void clear_syntax();
static const int kSyntaxFieldNumber = 7;
::google::protobuf::Syntax syntax() const;
@ -196,13 +224,10 @@ class LIBPROTOBUF_EXPORT Api : public ::google::protobuf::Message /* @@protoc_in
mutable int _cached_size_;
friend void LIBPROTOBUF_EXPORT protobuf_InitDefaults_google_2fprotobuf_2fapi_2eproto_impl();
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto_impl();
friend void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto();
friend const ::google::protobuf::uint32* protobuf_Offsets_google_2fprotobuf_2fapi_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto();
void InitAsDefaultInstance();
};
extern ::google::protobuf::internal::ExplicitlyConstructed<Api> Api_default_instance_;
// -------------------------------------------------------------------
class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Method) */ {
@ -220,55 +245,58 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc
static const ::google::protobuf::Descriptor* descriptor();
static const Method& default_instance();
static const Method* internal_default_instance();
static inline const Method* internal_default_instance() {
return reinterpret_cast<const Method*>(
&_Method_default_instance_);
}
void Swap(Method* other);
// implements Message ----------------------------------------------
inline Method* New() const { return New(NULL); }
inline Method* New() const PROTOBUF_FINAL { return New(NULL); }
Method* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
Method* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void CopyFrom(const Method& from);
void MergeFrom(const Method& from);
void Clear();
bool IsInitialized() const;
void Clear() PROTOBUF_FINAL;
bool IsInitialized() const PROTOBUF_FINAL;
size_t ByteSizeLong() const;
size_t ByteSizeLong() const PROTOBUF_FINAL;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
bool deterministic, ::google::protobuf::uint8* output) const;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output)
const PROTOBUF_FINAL {
return InternalSerializeWithCachedSizesToArray(false, output);
}
int GetCachedSize() const { return _cached_size_; }
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
void SetCachedSize(int size) const PROTOBUF_FINAL;
void InternalSwap(Method* other);
void UnsafeMergeFrom(const Method& from);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return _internal_metadata_.arena();
return NULL;
}
inline void* MaybeArenaPtr() const {
return _internal_metadata_.raw_arena_ptr();
return NULL;
}
public:
::google::protobuf::Metadata GetMetadata() const;
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// optional string name = 1;
// string name = 1;
void clear_name();
static const int kNameFieldNumber = 1;
const ::std::string& name() const;
@ -279,7 +307,7 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc
::std::string* release_name();
void set_allocated_name(::std::string* name);
// optional string request_type_url = 2;
// string request_type_url = 2;
void clear_request_type_url();
static const int kRequestTypeUrlFieldNumber = 2;
const ::std::string& request_type_url() const;
@ -290,13 +318,13 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc
::std::string* release_request_type_url();
void set_allocated_request_type_url(::std::string* request_type_url);
// optional bool request_streaming = 3;
// bool request_streaming = 3;
void clear_request_streaming();
static const int kRequestStreamingFieldNumber = 3;
bool request_streaming() const;
void set_request_streaming(bool value);
// optional string response_type_url = 4;
// string response_type_url = 4;
void clear_response_type_url();
static const int kResponseTypeUrlFieldNumber = 4;
const ::std::string& response_type_url() const;
@ -307,7 +335,7 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc
::std::string* release_response_type_url();
void set_allocated_response_type_url(::std::string* response_type_url);
// optional bool response_streaming = 5;
// bool response_streaming = 5;
void clear_response_streaming();
static const int kResponseStreamingFieldNumber = 5;
bool response_streaming() const;
@ -325,7 +353,7 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc
const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option >&
options() const;
// optional .google.protobuf.Syntax syntax = 7;
// .google.protobuf.Syntax syntax = 7;
void clear_syntax();
static const int kSyntaxFieldNumber = 7;
::google::protobuf::Syntax syntax() const;
@ -345,13 +373,10 @@ class LIBPROTOBUF_EXPORT Method : public ::google::protobuf::Message /* @@protoc
mutable int _cached_size_;
friend void LIBPROTOBUF_EXPORT protobuf_InitDefaults_google_2fprotobuf_2fapi_2eproto_impl();
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto_impl();
friend void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto();
friend const ::google::protobuf::uint32* protobuf_Offsets_google_2fprotobuf_2fapi_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto();
void InitAsDefaultInstance();
};
extern ::google::protobuf::internal::ExplicitlyConstructed<Method> Method_default_instance_;
// -------------------------------------------------------------------
class LIBPROTOBUF_EXPORT Mixin : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Mixin) */ {
@ -369,55 +394,58 @@ class LIBPROTOBUF_EXPORT Mixin : public ::google::protobuf::Message /* @@protoc_
static const ::google::protobuf::Descriptor* descriptor();
static const Mixin& default_instance();
static const Mixin* internal_default_instance();
static inline const Mixin* internal_default_instance() {
return reinterpret_cast<const Mixin*>(
&_Mixin_default_instance_);
}
void Swap(Mixin* other);
// implements Message ----------------------------------------------
inline Mixin* New() const { return New(NULL); }
inline Mixin* New() const PROTOBUF_FINAL { return New(NULL); }
Mixin* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
Mixin* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
void CopyFrom(const Mixin& from);
void MergeFrom(const Mixin& from);
void Clear();
bool IsInitialized() const;
void Clear() PROTOBUF_FINAL;
bool IsInitialized() const PROTOBUF_FINAL;
size_t ByteSizeLong() const;
size_t ByteSizeLong() const PROTOBUF_FINAL;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
bool deterministic, ::google::protobuf::uint8* output) const;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output)
const PROTOBUF_FINAL {
return InternalSerializeWithCachedSizesToArray(false, output);
}
int GetCachedSize() const { return _cached_size_; }
int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
void SetCachedSize(int size) const PROTOBUF_FINAL;
void InternalSwap(Mixin* other);
void UnsafeMergeFrom(const Mixin& from);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return _internal_metadata_.arena();
return NULL;
}
inline void* MaybeArenaPtr() const {
return _internal_metadata_.raw_arena_ptr();
return NULL;
}
public:
::google::protobuf::Metadata GetMetadata() const;
::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// optional string name = 1;
// string name = 1;
void clear_name();
static const int kNameFieldNumber = 1;
const ::std::string& name() const;
@ -428,7 +456,7 @@ class LIBPROTOBUF_EXPORT Mixin : public ::google::protobuf::Message /* @@protoc_
::std::string* release_name();
void set_allocated_name(::std::string* name);
// optional string root = 2;
// string root = 2;
void clear_root();
static const int kRootFieldNumber = 2;
const ::std::string& root() const;
@ -448,13 +476,10 @@ class LIBPROTOBUF_EXPORT Mixin : public ::google::protobuf::Message /* @@protoc_
mutable int _cached_size_;
friend void LIBPROTOBUF_EXPORT protobuf_InitDefaults_google_2fprotobuf_2fapi_2eproto_impl();
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto_impl();
friend void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto();
friend const ::google::protobuf::uint32* protobuf_Offsets_google_2fprotobuf_2fapi_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto();
void InitAsDefaultInstance();
};
extern ::google::protobuf::internal::ExplicitlyConstructed<Mixin> Mixin_default_instance_;
// ===================================================================
@ -463,13 +488,13 @@ extern ::google::protobuf::internal::ExplicitlyConstructed<Mixin> Mixin_default_
#if !PROTOBUF_INLINE_NOT_IN_HEADERS
// Api
// optional string name = 1;
// string name = 1;
inline void Api::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Api::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.Api.name)
return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return name_.GetNoArena();
}
inline void Api::set_name(const ::std::string& value) {
@ -567,13 +592,13 @@ Api::options() const {
return options_;
}
// optional string version = 4;
// string version = 4;
inline void Api::clear_version() {
version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Api::version() const {
// @@protoc_insertion_point(field_get:google.protobuf.Api.version)
return version_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return version_.GetNoArena();
}
inline void Api::set_version(const ::std::string& value) {
@ -611,7 +636,7 @@ inline void Api::set_allocated_version(::std::string* version) {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.version)
}
// optional .google.protobuf.SourceContext source_context = 5;
// .google.protobuf.SourceContext source_context = 5;
inline bool Api::has_source_context() const {
return this != internal_default_instance() && source_context_ != NULL;
}
@ -680,7 +705,7 @@ Api::mixins() const {
return mixins_;
}
// optional .google.protobuf.Syntax syntax = 7;
// .google.protobuf.Syntax syntax = 7;
inline void Api::clear_syntax() {
syntax_ = 0;
}
@ -694,20 +719,17 @@ inline void Api::set_syntax(::google::protobuf::Syntax value) {
// @@protoc_insertion_point(field_set:google.protobuf.Api.syntax)
}
inline const Api* Api::internal_default_instance() {
return &Api_default_instance_.get();
}
// -------------------------------------------------------------------
// Method
// optional string name = 1;
// string name = 1;
inline void Method::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Method::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.Method.name)
return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return name_.GetNoArena();
}
inline void Method::set_name(const ::std::string& value) {
@ -745,13 +767,13 @@ inline void Method::set_allocated_name(::std::string* name) {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.name)
}
// optional string request_type_url = 2;
// string request_type_url = 2;
inline void Method::clear_request_type_url() {
request_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Method::request_type_url() const {
// @@protoc_insertion_point(field_get:google.protobuf.Method.request_type_url)
return request_type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return request_type_url_.GetNoArena();
}
inline void Method::set_request_type_url(const ::std::string& value) {
@ -789,7 +811,7 @@ inline void Method::set_allocated_request_type_url(::std::string* request_type_u
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.request_type_url)
}
// optional bool request_streaming = 3;
// bool request_streaming = 3;
inline void Method::clear_request_streaming() {
request_streaming_ = false;
}
@ -803,13 +825,13 @@ inline void Method::set_request_streaming(bool value) {
// @@protoc_insertion_point(field_set:google.protobuf.Method.request_streaming)
}
// optional string response_type_url = 4;
// string response_type_url = 4;
inline void Method::clear_response_type_url() {
response_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Method::response_type_url() const {
// @@protoc_insertion_point(field_get:google.protobuf.Method.response_type_url)
return response_type_url_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return response_type_url_.GetNoArena();
}
inline void Method::set_response_type_url(const ::std::string& value) {
@ -847,7 +869,7 @@ inline void Method::set_allocated_response_type_url(::std::string* response_type
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Method.response_type_url)
}
// optional bool response_streaming = 5;
// bool response_streaming = 5;
inline void Method::clear_response_streaming() {
response_streaming_ = false;
}
@ -891,7 +913,7 @@ Method::options() const {
return options_;
}
// optional .google.protobuf.Syntax syntax = 7;
// .google.protobuf.Syntax syntax = 7;
inline void Method::clear_syntax() {
syntax_ = 0;
}
@ -905,20 +927,17 @@ inline void Method::set_syntax(::google::protobuf::Syntax value) {
// @@protoc_insertion_point(field_set:google.protobuf.Method.syntax)
}
inline const Method* Method::internal_default_instance() {
return &Method_default_instance_.get();
}
// -------------------------------------------------------------------
// Mixin
// optional string name = 1;
// string name = 1;
inline void Mixin::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Mixin::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.Mixin.name)
return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return name_.GetNoArena();
}
inline void Mixin::set_name(const ::std::string& value) {
@ -956,13 +975,13 @@ inline void Mixin::set_allocated_name(::std::string* name) {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.name)
}
// optional string root = 2;
// string root = 2;
inline void Mixin::clear_root() {
root_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Mixin::root() const {
// @@protoc_insertion_point(field_get:google.protobuf.Mixin.root)
return root_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
return root_.GetNoArena();
}
inline void Mixin::set_root(const ::std::string& value) {
@ -1000,9 +1019,6 @@ inline void Mixin::set_allocated_root(::std::string* root) {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.root)
}
inline const Mixin* Mixin::internal_default_instance() {
return &Mixin_default_instance_.get();
}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
// -------------------------------------------------------------------
@ -1011,6 +1027,7 @@ inline const Mixin* Mixin::internal_default_instance() {
// @@protoc_insertion_point(namespace_scope)
} // namespace protobuf
} // namespace google

View File

@ -40,6 +40,7 @@ option java_package = "com.google.protobuf";
option java_outer_classname = "ApiProto";
option java_multiple_files = true;
option objc_class_prefix = "GPB";
option go_package = "google.golang.org/genproto/protobuf/api;api";
// Api is a light-weight descriptor for a protocol buffer service.
message Api {

View File

@ -36,7 +36,7 @@
#ifdef ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#endif
#endif // ADDRESS_SANITIZER
namespace google {
namespace protobuf {
@ -141,7 +141,7 @@ Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n,
// 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
#endif // ADDRESS_SANITIZER
return b;
}
@ -205,7 +205,7 @@ void* Arena::AllocFromBlock(Block* b, size_t n) {
b->pos = p + n;
#ifdef ADDRESS_SANITIZER
ASAN_UNPOISON_MEMORY_REGION(reinterpret_cast<char*>(b) + p, n);
#endif
#endif // ADDRESS_SANITIZER
return reinterpret_cast<char*>(b) + p;
}
@ -244,7 +244,7 @@ uint64 Arena::SpaceUsed() const {
return space_used;
}
pair<uint64, uint64> Arena::SpaceAllocatedAndUsed() const {
std::pair<uint64, uint64> Arena::SpaceAllocatedAndUsed() const {
uint64 allocated = 0;
uint64 used = 0;
@ -265,9 +265,19 @@ uint64 Arena::FreeBlocks() {
space_allocated += (b->size);
Block* next = b->next;
if (next != NULL) {
#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);
#endif // ADDRESS_SANITIZER
options_.block_dealloc(b, b->size);
} else {
if (owns_first_block_) {
#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);
#endif // ADDRESS_SANITIZER
options_.block_dealloc(b, b->size);
} else {
// User passed in the first block, skip free'ing the memory.

View File

@ -31,9 +31,40 @@
#ifndef GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
#define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/arena.h>
namespace google {
namespace protobuf {
template <typename T, bool use_arena>
void TestParseCorruptedString(const T& message) {
int success_count = 0;
string s = message.SerializeAsString();
const int kMaxIters = 900;
const int stride = s.size() <= kMaxIters ? 1 : s.size() / kMaxIters;
const int start = stride == 1 || use_arena ? 0 : (stride + 1) / 2;
for (int i = start; i < s.size(); i += stride) {
for (int c = 1 + (i % 17); c < 256; c += 2 * c + (i & 3)) {
s[i] ^= c;
google::protobuf::Arena arena;
T* message =
google::protobuf::Arena::CreateMessage<T>(use_arena ? &arena : NULL);
if (message->ParseFromString(s)) {
++success_count;
}
if (!use_arena) {
delete message;
}
s[i] ^= c; // Restore s to its original state.
}
}
// This next line is a low bar. But getting through the test without crashing
// due to use-after-free or other bugs is a big part of what we're checking.
GOOGLE_CHECK_GT(success_count, 0);
}
namespace internal {
class NoHeapChecker {

View File

@ -249,7 +249,7 @@ TEST(ArenaTest, Parsing) {
arena_message->ParseFromString(original.SerializeAsString());
TestUtil::ExpectAllFieldsSet(*arena_message);
// Test that string fields have null terminator bytes (earlier bug).
// Test that string fields have nul terminator bytes (earlier bug).
EXPECT_EQ(strlen(original.optional_string().c_str()),
strlen(arena_message->optional_string().c_str()));
}
@ -1154,6 +1154,13 @@ TEST(ArenaTest, NoHeapAllocationsTest) {
arena.Reset();
}
TEST(ArenaTest, ParseCorruptedString) {
TestAllTypes message;
TestUtil::SetAllFields(&message);
TestParseCorruptedString<TestAllTypes, true>(message);
TestParseCorruptedString<TestAllTypes, false>(message);
}
#ifndef GOOGLE_PROTOBUF_NO_RTTI
// Test construction on an arena via generic MessageLite interface. We should be
// able to successfully deserialize on the arena without incurring heap

View File

@ -44,7 +44,7 @@ void ArenaStringPtr::AssignWithDefault(const ::std::string* default_value,
const ::std::string* other = *value.UnsafeRawStringPointer();
// If the pointers are the same then do nothing.
if (me != other) {
SetNoArena(default_value, value.GetNoArena(default_value));
SetNoArena(default_value, value.GetNoArena());
}
}

View File

@ -37,7 +37,6 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/fastmem.h>
#include <google/protobuf/arena.h>
#include <google/protobuf/generated_message_util.h>
@ -64,9 +63,7 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
}
// Basic accessors.
inline const ::std::string& Get(const ::std::string* /* default_value */) const {
return *ptr_;
}
inline const ::std::string& Get() const { return *ptr_; }
inline ::std::string* Mutable(const ::std::string* default_value,
::google::protobuf::Arena* arena) {
@ -150,13 +147,12 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
std::swap(ptr_, other->ptr_);
}
// Frees storage (if not on an arena) and sets field to default value.
// Frees storage (if not on an arena).
inline void Destroy(const ::std::string* default_value,
::google::protobuf::Arena* arena) {
if (arena == NULL && ptr_ != default_value) {
delete ptr_;
}
ptr_ = const_cast< ::std::string* >(default_value);
}
// Clears content, but keeps allocated string if arena != NULL, to avoid the
@ -216,9 +212,7 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
void AssignWithDefault(const ::std::string* default_value, ArenaStringPtr value);
inline const ::std::string& GetNoArena(const ::std::string* /* default_value */) const {
return *ptr_;
}
inline const ::std::string& GetNoArena() const { return *ptr_; }
inline ::std::string* MutableNoArena(const ::std::string* default_value) {
if (ptr_ == default_value) {
@ -253,7 +247,6 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
if (ptr_ != default_value) {
delete ptr_;
}
ptr_ = NULL;
}
inline void ClearToEmptyNoArena(const ::std::string* default_value) {
@ -281,6 +274,10 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
return &ptr_;
}
inline bool IsDefault(const ::std::string* default_value) const {
return ptr_ == default_value;
}
private:
::std::string* ptr_;

View File

@ -59,11 +59,11 @@ TEST(ArenaStringPtrTest, ArenaStringPtrOnHeap) {
ArenaStringPtr field;
::std::string default_value = "default";
field.UnsafeSetDefault(&default_value);
EXPECT_EQ(string("default"), field.Get(&default_value));
EXPECT_EQ(string("default"), field.Get());
field.Set(&default_value, WrapString("Test short"), NULL);
EXPECT_EQ(string("Test short"), field.Get(&default_value));
EXPECT_EQ(string("Test short"), field.Get());
field.Set(&default_value, WrapString("Test long long long long value"), NULL);
EXPECT_EQ(string("Test long long long long value"), field.Get(&default_value));
EXPECT_EQ(string("Test long long long long value"), field.Get());
field.Set(&default_value, string(""), NULL);
field.Destroy(&default_value, NULL);
@ -71,11 +71,11 @@ TEST(ArenaStringPtrTest, ArenaStringPtrOnHeap) {
field2.UnsafeSetDefault(&default_value);
::std::string* mut = field2.Mutable(&default_value, NULL);
EXPECT_EQ(mut, field2.Mutable(&default_value, NULL));
EXPECT_EQ(mut, &field2.Get(&default_value));
EXPECT_EQ(mut, &field2.Get());
EXPECT_NE(&default_value, mut);
EXPECT_EQ(string("default"), *mut);
*mut = "Test long long long long value"; // ensure string allocates storage
EXPECT_EQ(string("Test long long long long value"), field2.Get(&default_value));
EXPECT_EQ(string("Test long long long long value"), field2.Get());
field2.Destroy(&default_value, NULL);
}
@ -84,12 +84,11 @@ TEST(ArenaStringPtrTest, ArenaStringPtrOnArena) {
ArenaStringPtr field;
::std::string default_value = "default";
field.UnsafeSetDefault(&default_value);
EXPECT_EQ(string("default"), field.Get(&default_value));
EXPECT_EQ(string("default"), field.Get());
field.Set(&default_value, WrapString("Test short"), &arena);
EXPECT_EQ(string("Test short"), field.Get(&default_value));
EXPECT_EQ(string("Test short"), field.Get());
field.Set(&default_value, WrapString("Test long long long long value"), &arena);
EXPECT_EQ(string("Test long long long long value"),
field.Get(&default_value));
EXPECT_EQ(string("Test long long long long value"), field.Get());
field.Set(&default_value, string(""), &arena);
field.Destroy(&default_value, &arena);
@ -97,12 +96,11 @@ TEST(ArenaStringPtrTest, ArenaStringPtrOnArena) {
field2.UnsafeSetDefault(&default_value);
::std::string* mut = field2.Mutable(&default_value, &arena);
EXPECT_EQ(mut, field2.Mutable(&default_value, &arena));
EXPECT_EQ(mut, &field2.Get(&default_value));
EXPECT_EQ(mut, &field2.Get());
EXPECT_NE(&default_value, mut);
EXPECT_EQ(string("default"), *mut);
*mut = "Test long long long long value"; // ensure string allocates storage
EXPECT_EQ(string("Test long long long long value"),
field2.Get(&default_value));
EXPECT_EQ(string("Test long long long long value"), field2.Get());
field2.Destroy(&default_value, &arena);
}

View File

@ -46,7 +46,7 @@ namespace compiler {
CodeGenerator::~CodeGenerator() {}
bool CodeGenerator::GenerateAll(
const vector<const FileDescriptor*>& files,
const std::vector<const FileDescriptor*>& files,
const string& parameter,
GeneratorContext* generator_context,
string* error) const {
@ -85,18 +85,18 @@ io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert(
}
void GeneratorContext::ListParsedFiles(
vector<const FileDescriptor*>* output) {
std::vector<const FileDescriptor*>* output) {
GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles";
}
// Parses a set of comma-delimited name/value pairs.
void ParseGeneratorParameter(const string& text,
vector<pair<string, string> >* output) {
vector<string> parts = Split(text, ",", true);
std::vector<std::pair<string, string> >* output) {
std::vector<string> parts = Split(text, ",", true);
for (int i = 0; i < parts.size(); i++) {
string::size_type equals_pos = parts[i].find_first_of('=');
pair<string, string> value;
std::pair<string, string> value;
if (equals_pos == string::npos) {
value.first = parts[i];
value.second = "";

View File

@ -90,7 +90,7 @@ class LIBPROTOC_EXPORT CodeGenerator {
//
// Returns true if successful. Otherwise, sets *error to a description of
// the problem (e.g. "invalid parameter") and returns false.
virtual bool GenerateAll(const vector<const FileDescriptor*>& files,
virtual bool GenerateAll(const std::vector<const FileDescriptor*>& files,
const string& parameter,
GeneratorContext* generator_context,
string* error) const;
@ -141,7 +141,7 @@ class LIBPROTOC_EXPORT GeneratorContext {
// Returns a vector of FileDescriptors for all the files being compiled
// in this run. Useful for languages, such as Go, that treat files
// differently when compiled as a set rather than individually.
virtual void ListParsedFiles(vector<const FileDescriptor*>* output);
virtual void ListParsedFiles(std::vector<const FileDescriptor*>* output);
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext);
@ -158,7 +158,7 @@ typedef GeneratorContext OutputDirectory;
// parses to the pairs:
// ("foo", "bar"), ("baz", ""), ("qux", "corge")
extern void ParseGeneratorParameter(const string&,
vector<pair<string, string> >*);
std::vector<std::pair<string, string> >*);
} // namespace compiler
} // namespace protobuf

View File

@ -173,7 +173,8 @@ bool VerifyDirectoryExists(const string& path) {
// directories listed in |filename|.
bool TryCreateParentDirectory(const string& prefix, const string& filename) {
// Recursively create parent directories to the output file.
vector<string> parts = Split(filename, "/", true);
std::vector<string> parts =
Split(filename, "/", true);
string path_so_far = prefix;
for (int i = 0; i < parts.size() - 1; i++) {
path_so_far += parts[i];
@ -338,7 +339,7 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
// them all to disk on demand.
class CommandLineInterface::GeneratorContextImpl : public GeneratorContext {
public:
GeneratorContextImpl(const vector<const FileDescriptor*>& parsed_files);
GeneratorContextImpl(const std::vector<const FileDescriptor*>& parsed_files);
~GeneratorContextImpl();
// Write all files in the directory to disk at the given output location,
@ -354,14 +355,14 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext {
void AddJarManifest();
// Get name of all output files.
void GetOutputFilenames(vector<string>* output_filenames);
void GetOutputFilenames(std::vector<string>* output_filenames);
// implements GeneratorContext --------------------------------------
io::ZeroCopyOutputStream* Open(const string& filename);
io::ZeroCopyOutputStream* OpenForAppend(const string& filename);
io::ZeroCopyOutputStream* OpenForInsert(
const string& filename, const string& insertion_point);
void ListParsedFiles(vector<const FileDescriptor*>* output) {
void ListParsedFiles(std::vector<const FileDescriptor*>* output) {
*output = parsed_files_;
}
@ -370,8 +371,8 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext {
// map instead of hash_map so that files are written in order (good when
// writing zips).
map<string, string*> files_;
const vector<const FileDescriptor*>& parsed_files_;
std::map<string, string*> files_;
const std::vector<const FileDescriptor*>& parsed_files_;
bool had_error_;
};
@ -408,7 +409,7 @@ class CommandLineInterface::MemoryOutputStream
// -------------------------------------------------------------------
CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl(
const vector<const FileDescriptor*>& parsed_files)
const std::vector<const FileDescriptor*>& parsed_files)
: parsed_files_(parsed_files),
had_error_(false) {
}
@ -427,7 +428,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk(
return false;
}
for (map<string, string*>::const_iterator iter = files_.begin();
for (std::map<string, string*>::const_iterator iter = files_.begin();
iter != files_.end(); ++iter) {
const string& relative_filename = iter->first;
const char* data = iter->second->data();
@ -515,7 +516,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip(
io::FileOutputStream stream(file_descriptor);
ZipWriter zip_writer(&stream);
for (map<string, string*>::const_iterator iter = files_.begin();
for (std::map<string, string*>::const_iterator iter = files_.begin();
iter != files_.end(); ++iter) {
zip_writer.Write(iter->first, *iter->second);
}
@ -544,8 +545,8 @@ void CommandLineInterface::GeneratorContextImpl::AddJarManifest() {
}
void CommandLineInterface::GeneratorContextImpl::GetOutputFilenames(
vector<string>* output_filenames) {
for (map<string, string*>::iterator iter = files_.begin();
std::vector<string>* output_filenames) {
for (std::map<string, string*>::iterator iter = files_.begin();
iter != files_.end(); ++iter) {
output_filenames->push_back(iter->first);
}
@ -768,7 +769,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
ErrorPrinter error_collector(error_format_, &source_tree);
Importer importer(&source_tree, &error_collector);
vector<const FileDescriptor*> parsed_files;
std::vector<const FileDescriptor*> parsed_files;
// Parse each file.
for (int i = 0; i < input_files_.size(); i++) {
@ -978,7 +979,7 @@ CommandLineInterface::ParseArgumentStatus
CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
executable_name_ = argv[0];
vector<string> arguments;
std::vector<string> arguments;
for (int i = 1; i < argc; ++i) {
arguments.push_back(argv[i]);
}
@ -1012,7 +1013,7 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
// Don't use make_pair as the old/default standard library on Solaris
// doesn't support it without explicit template parameters, which are
// incompatible with C++0x's make_pair.
proto_path_.push_back(pair<string, string>("", "."));
proto_path_.push_back(std::pair<string, string>("", "."));
}
// Check some errror cases.
@ -1135,7 +1136,7 @@ CommandLineInterface::InterpretArgument(const string& name,
// Java's -classpath (and some other languages) delimits path components
// with colons. Let's accept that syntax too just to make things more
// intuitive.
vector<string> parts = Split(
std::vector<string> parts = Split(
value, kPathSeparator, true);
for (int i = 0; i < parts.size(); i++) {
@ -1172,19 +1173,21 @@ CommandLineInterface::InterpretArgument(const string& name,
// Don't use make_pair as the old/default standard library on Solaris
// doesn't support it without explicit template parameters, which are
// incompatible with C++0x's make_pair.
proto_path_.push_back(pair<string, string>(virtual_path, disk_path));
proto_path_.push_back(std::pair<string, string>(virtual_path, disk_path));
}
} else if (name == "--direct_dependencies") {
if (direct_dependencies_explicitly_set_) {
std::cerr << name << " may only be passed once. To specify multiple "
"direct dependencies, pass them all as a single "
"parameter separated by ':'." << std::endl;
"parameter separated by ':'."
<< std::endl;
return PARSE_ARGUMENT_FAIL;
}
direct_dependencies_explicitly_set_ = true;
vector<string> direct = Split(value, ":", true);
std::vector<string> direct = Split(
value, ":", true);
GOOGLE_DCHECK(direct_dependencies_.empty());
direct_dependencies_.insert(direct.begin(), direct.end());
@ -1451,7 +1454,7 @@ void CommandLineInterface::PrintHelpText() {
}
bool CommandLineInterface::GenerateOutput(
const vector<const FileDescriptor*>& parsed_files,
const std::vector<const FileDescriptor*>& parsed_files,
const OutputDirective& output_directive,
GeneratorContext* generator_context) {
// Call the generator.
@ -1493,12 +1496,12 @@ bool CommandLineInterface::GenerateOutput(
}
bool CommandLineInterface::GenerateDependencyManifestFile(
const vector<const FileDescriptor*>& parsed_files,
const std::vector<const FileDescriptor*>& parsed_files,
const GeneratorContextMap& output_directories,
DiskSourceTree* source_tree) {
FileDescriptorSet file_set;
set<const FileDescriptor*> already_seen;
std::set<const FileDescriptor*> already_seen;
for (int i = 0; i < parsed_files.size(); i++) {
GetTransitiveDependencies(parsed_files[i],
false,
@ -1507,12 +1510,12 @@ bool CommandLineInterface::GenerateDependencyManifestFile(
file_set.mutable_file());
}
vector<string> output_filenames;
std::vector<string> output_filenames;
for (GeneratorContextMap::const_iterator iter = output_directories.begin();
iter != output_directories.end(); ++iter) {
const string& location = iter->first;
GeneratorContextImpl* directory = iter->second;
vector<string> relative_output_filenames;
std::vector<string> relative_output_filenames;
directory->GetOutputFilenames(&relative_output_filenames);
for (int i = 0; i < relative_output_filenames.size(); i++) {
string output_filename = location + relative_output_filenames[i];
@ -1565,7 +1568,7 @@ bool CommandLineInterface::GenerateDependencyManifestFile(
}
bool CommandLineInterface::GeneratePluginOutput(
const vector<const FileDescriptor*>& parsed_files,
const std::vector<const FileDescriptor*>& parsed_files,
const string& plugin_name,
const string& parameter,
GeneratorContext* generator_context,
@ -1578,7 +1581,7 @@ bool CommandLineInterface::GeneratePluginOutput(
request.set_parameter(parameter);
}
set<const FileDescriptor*> already_seen;
std::set<const FileDescriptor*> already_seen;
for (int i = 0; i < parsed_files.size(); i++) {
request.add_file_to_generate(parsed_files[i]->name());
GetTransitiveDependencies(parsed_files[i],
@ -1708,11 +1711,11 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
}
bool CommandLineInterface::WriteDescriptorSet(
const vector<const FileDescriptor*> parsed_files) {
const std::vector<const FileDescriptor*> parsed_files) {
FileDescriptorSet file_set;
if (imports_in_descriptor_set_) {
set<const FileDescriptor*> already_seen;
std::set<const FileDescriptor*> already_seen;
for (int i = 0; i < parsed_files.size(); i++) {
GetTransitiveDependencies(parsed_files[i],
true, // Include json_name
@ -1720,7 +1723,7 @@ bool CommandLineInterface::WriteDescriptorSet(
&already_seen, file_set.mutable_file());
}
} else {
set<const FileDescriptor*> already_seen;
std::set<const FileDescriptor*> already_seen;
for (int i = 0; i < parsed_files.size(); i++) {
if (!already_seen.insert(parsed_files[i]).second) {
continue;
@ -1765,7 +1768,7 @@ void CommandLineInterface::GetTransitiveDependencies(
const FileDescriptor* file,
bool include_json_name,
bool include_source_code_info,
set<const FileDescriptor*>* already_seen,
std::set<const FileDescriptor*>* already_seen,
RepeatedPtrField<FileDescriptorProto>* output) {
if (!already_seen->insert(file).second) {
// Already saw this file. Skip.
@ -1824,11 +1827,11 @@ namespace {
// parameter will contain the direct children (when groups are ignored in the
// tree) of the given descriptor for the caller to traverse. The declaration
// order of the nested messages is also preserved.
typedef pair<int, int> FieldRange;
void GatherOccupiedFieldRanges(const Descriptor* descriptor,
set<FieldRange>* ranges,
vector<const Descriptor*>* nested_messages) {
set<const Descriptor*> groups;
typedef std::pair<int, int> FieldRange;
void GatherOccupiedFieldRanges(
const Descriptor* descriptor, std::set<FieldRange>* ranges,
std::vector<const Descriptor*>* nested_messages) {
std::set<const Descriptor*> groups;
for (int i = 0; i < descriptor->field_count(); ++i) {
const FieldDescriptor* fd = descriptor->field(i);
ranges->insert(FieldRange(fd->number(), fd->number() + 1));
@ -1860,11 +1863,11 @@ void GatherOccupiedFieldRanges(const Descriptor* descriptor,
// Actually prints the formatted free field numbers for given message name and
// occupied ranges.
void FormatFreeFieldNumbers(const string& name,
const set<FieldRange>& ranges) {
const std::set<FieldRange>& ranges) {
string output;
StringAppendF(&output, "%-35s free:", name.c_str());
int next_free_number = 1;
for (set<FieldRange>::const_iterator i = ranges.begin();
for (std::set<FieldRange>::const_iterator i = ranges.begin();
i != ranges.end(); ++i) {
// This happens when groups re-use parent field numbers, in which
// case we skip the FieldRange entirely.
@ -1891,8 +1894,8 @@ void FormatFreeFieldNumbers(const string& name,
void CommandLineInterface::PrintFreeFieldNumbers(
const Descriptor* descriptor) {
set<FieldRange> ranges;
vector<const Descriptor*> nested_messages;
std::set<FieldRange> ranges;
std::vector<const Descriptor*> nested_messages;
GatherOccupiedFieldRanges(descriptor, &ranges, &nested_messages);
for (int i = 0; i < nested_messages.size(); ++i) {

View File

@ -56,9 +56,7 @@ class FileDescriptorProto; // descriptor.pb.h
template<typename T> class RepeatedPtrField; // repeated_field.h
} // namespace protobuf
} // namespace google
namespace google {
namespace protobuf {
namespace compiler {
@ -240,24 +238,24 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// Generate the given output file from the given input.
struct OutputDirective; // see below
bool GenerateOutput(const vector<const FileDescriptor*>& parsed_files,
bool GenerateOutput(const std::vector<const FileDescriptor*>& parsed_files,
const OutputDirective& output_directive,
GeneratorContext* generator_context);
bool GeneratePluginOutput(const vector<const FileDescriptor*>& parsed_files,
const string& plugin_name,
const string& parameter,
GeneratorContext* generator_context,
string* error);
bool GeneratePluginOutput(
const std::vector<const FileDescriptor*>& parsed_files,
const string& plugin_name, const string& parameter,
GeneratorContext* generator_context, string* error);
// Implements --encode and --decode.
bool EncodeOrDecode(const DescriptorPool* pool);
// Implements the --descriptor_set_out option.
bool WriteDescriptorSet(const vector<const FileDescriptor*> parsed_files);
bool WriteDescriptorSet(
const std::vector<const FileDescriptor*> parsed_files);
// Implements the --dependency_out option
bool GenerateDependencyManifestFile(
const vector<const FileDescriptor*>& parsed_files,
const std::vector<const FileDescriptor*>& parsed_files,
const GeneratorContextMap& output_directories,
DiskSourceTree* source_tree);
@ -274,7 +272,7 @@ class LIBPROTOC_EXPORT CommandLineInterface {
const FileDescriptor* file,
bool include_json_name,
bool include_source_code_info,
set<const FileDescriptor*>* already_seen,
std::set<const FileDescriptor*>* already_seen,
RepeatedPtrField<FileDescriptorProto>* output);
// Implements the --print_free_field_numbers. This function prints free field
@ -308,14 +306,14 @@ class LIBPROTOC_EXPORT CommandLineInterface {
CodeGenerator* generator;
string help_text;
};
typedef map<string, GeneratorInfo> GeneratorMap;
typedef std::map<string, GeneratorInfo> GeneratorMap;
GeneratorMap generators_by_flag_name_;
GeneratorMap generators_by_option_name_;
// A map from generator names to the parameters specified using the option
// flag. For example, if the user invokes the compiler with:
// protoc --foo_out=outputdir --foo_opt=enable_bar ...
// Then there will be an entry ("--foo_out", "enable_bar") in this map.
map<string, string> generator_parameters_;
std::map<string, string> generator_parameters_;
// See AllowPlugins(). If this is empty, plugins aren't allowed.
string plugin_prefix_;
@ -323,7 +321,7 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// Maps specific plugin names to files. When executing a plugin, this map
// is searched first to find the plugin executable. If not found here, the
// PATH (or other OS-specific search strategy) is searched.
map<string, string> plugins_;
std::map<string, string> plugins_;
// Stuff parsed from command line.
enum Mode {
@ -349,12 +347,13 @@ class LIBPROTOC_EXPORT CommandLineInterface {
ErrorFormat error_format_;
vector<pair<string, string> > proto_path_; // Search path for proto files.
vector<string> input_files_; // Names of the input proto files.
std::vector<std::pair<string, string> >
proto_path_; // Search path for proto files.
std::vector<string> input_files_; // Names of the input proto files.
// Names of proto files which are allowed to be imported. Used by build
// systems to enforce depend-on-what-you-import.
set<string> direct_dependencies_;
std::set<string> direct_dependencies_;
bool direct_dependencies_explicitly_set_;
// output_directives_ lists all the files we are supposed to output and what
@ -365,7 +364,7 @@ class LIBPROTOC_EXPORT CommandLineInterface {
string parameter;
string output_location;
};
vector<OutputDirective> output_directives_;
std::vector<OutputDirective> output_directives_;
// When using --encode or --decode, this names the type we are encoding or
// decoding. (Empty string indicates --decode_raw.)

View File

@ -217,7 +217,7 @@ class CommandLineInterfaceTest : public testing::Test {
string captured_stdout_;
// Pointers which need to be deleted later.
vector<CodeGenerator*> mock_generators_to_delete_;
std::vector<CodeGenerator*> mock_generators_to_delete_;
NullCodeGenerator* null_generator_;
};
@ -291,7 +291,7 @@ void CommandLineInterfaceTest::TearDown() {
}
void CommandLineInterfaceTest::Run(const string& command) {
vector<string> args = Split(command, " ", true);
std::vector<string> args = Split(command, " ", true);
if (!disallow_plugins_) {
cli_.AllowPlugins("prefix-");
@ -721,7 +721,7 @@ TEST_F(CommandLineInterfaceTest, TrailingBackslash) {
TEST_F(CommandLineInterfaceTest, Win32ErrorMessage) {
EXPECT_EQ("The system cannot find the file specified.\r\n",
Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND));
Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND));
}
#endif // defined(_WIN32) || defined(__CYGWIN__)
@ -1818,7 +1818,7 @@ class EncodeDecodeTest : public testing::Test {
enum ReturnCode { SUCCESS, ERROR };
bool Run(const string& command) {
vector<string> args;
std::vector<string> args;
args.push_back("protoc");
SplitStringUsing(command, " ", &args);
args.push_back("--proto_path=" + TestSourceDir());

View File

@ -114,7 +114,7 @@ class MockGeneratorContext : public GeneratorContext {
}
private:
map<string, string*> files_;
std::map<string, string*> files_;
};
TEST(BootstrapTest, GeneratedDescriptorMatches) {

View File

@ -70,7 +70,7 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
EnumGenerator::~EnumGenerator() {}
void EnumGenerator::FillForwardDeclaration(
map<string, const EnumDescriptor*>* enum_names) {
std::map<string, const EnumDescriptor*>* enum_names) {
if (!options_.proto_h) {
return;
}
@ -78,7 +78,7 @@ void EnumGenerator::FillForwardDeclaration(
}
void EnumGenerator::GenerateDefinition(io::Printer* printer) {
map<string, string> vars;
std::map<string, string> vars;
vars["classname"] = classname_;
vars["short_name"] = descriptor_->name();
vars["enumbase"] = classname_ + (options_.proto_h ? " : int" : "");
@ -180,7 +180,7 @@ GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
}
void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
map<string, string> vars;
std::map<string, string> vars;
vars["nested_name"] = descriptor_->name();
vars["classname"] = classname_;
vars["constexpr"] = options_.proto_h ? "constexpr " : "";
@ -229,33 +229,36 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
}
}
void EnumGenerator::GenerateDescriptorInitializer(
io::Printer* printer, int index) {
map<string, string> vars;
vars["classname"] = classname_;
vars["index"] = SimpleItoa(index);
void EnumGenerator::GenerateDescriptorInitializer(io::Printer* printer) {
std::map<string, string> vars;
vars["index"] = SimpleItoa(descriptor_->index());
vars["index_in_metadata"] = SimpleItoa(index_in_metadata_);
if (descriptor_->containing_type() == NULL) {
printer->Print(vars,
"$classname$_descriptor_ = file->enum_type($index$);\n");
"file_level_enum_descriptors[$index_in_metadata$] = "
"file->enum_type($index$);\n");
} else {
vars["parent"] = ClassName(descriptor_->containing_type(), false);
printer->Print(vars,
"$classname$_descriptor_ = $parent$_descriptor_->enum_type($index$);\n");
"file_level_enum_descriptors[$index_in_metadata$] = "
"$parent$_descriptor->enum_type($index$);\n");
}
}
void EnumGenerator::GenerateMethods(io::Printer* printer) {
map<string, string> vars;
std::map<string, string> vars;
vars["classname"] = classname_;
vars["index_in_metadata"] = SimpleItoa(index_in_metadata_);
vars["constexpr"] = options_.proto_h ? "constexpr " : "";
if (HasDescriptorMethods(descriptor_->file(), options_)) {
printer->Print(vars,
"const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
" protobuf_AssignDescriptorsOnce();\n"
" return $classname$_descriptor_;\n"
"}\n");
printer->Print(
vars,
"const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n"
" protobuf_AssignDescriptorsOnce();\n"
" return file_level_enum_descriptors[$index_in_metadata$];\n"
"}\n");
}
printer->Print(vars,
@ -266,13 +269,13 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) {
// each number once by first constructing a set containing all valid
// numbers, then printing a case statement for each element.
set<int> numbers;
std::set<int> numbers;
for (int j = 0; j < descriptor_->value_count(); j++) {
const EnumValueDescriptor* value = descriptor_->value(j);
numbers.insert(value->number());
}
for (set<int>::iterator iter = numbers.begin();
for (std::set<int>::iterator iter = numbers.begin();
iter != numbers.end(); ++iter) {
printer->Print(
" case $number$:\n",

View File

@ -66,7 +66,8 @@ class EnumGenerator {
// enums. A given key in enum_names will map from an enum class name to the
// EnumDescriptor that was responsible for its inclusion in the map. This can
// be used to associate the descriptor with the code generated for it.
void FillForwardDeclaration(map<string, const EnumDescriptor*>* enum_names);
void FillForwardDeclaration(
std::map<string, const EnumDescriptor*>* enum_names);
// Generate header code defining the enum. This code should be placed
// within the enum's package namespace, but NOT within any class, even for
@ -87,7 +88,7 @@ class EnumGenerator {
// Generate code that initializes the global variable storing the enum's
// descriptor.
void GenerateDescriptorInitializer(io::Printer* printer, int index);
void GenerateDescriptorInitializer(io::Printer* printer);
// Generate non-inline methods related to the enum, such as IsValidValue().
// Goes in the .cc file.
@ -100,6 +101,9 @@ class EnumGenerator {
// whether to generate the *_ARRAYSIZE constant.
const bool generate_array_size_;
int index_in_metadata_;
friend class FileGenerator;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
};

View File

@ -46,7 +46,7 @@ namespace cpp {
namespace {
void SetEnumVariables(const FieldDescriptor* descriptor,
map<string, string>* variables,
std::map<string, string>* variables,
const Options& options) {
SetCommonFieldVariables(descriptor, variables, options);
const EnumValueDescriptor* default_value = descriptor->default_value_enum();
@ -82,7 +82,7 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
void EnumFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
std::map<string, string> variables(variables_);
variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
"$inline$$type$ $classname$::$name$() const {\n"
@ -121,6 +121,11 @@ GenerateConstructorCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_ = $default$;\n");
}
void EnumFieldGenerator::
GenerateCopyConstructorCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_ = from.$name$_;\n");
}
void EnumFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
@ -186,7 +191,7 @@ EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
void EnumOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
std::map<string, string> variables(variables_);
variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
"$inline$$type$ $classname$::$name$() const {\n"
@ -223,8 +228,9 @@ GenerateSwappingCode(io::Printer* printer) const {
void EnumOneofFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
printer->Print(variables_,
" $classname$_default_oneof_instance_->$name$_ = $default$;\n");
printer->Print(
variables_,
" $classname$_default_oneof_instance_.$name$_ = $default$;\n");
}
// ===================================================================
@ -262,7 +268,7 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
std::map<string, string> variables(variables_);
variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
"$inline$$type$ $classname$::$name$(int index) const {\n"
@ -310,11 +316,6 @@ GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
}
void RepeatedEnumFieldGenerator::
GenerateUnsafeMergingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.UnsafeMergeFrom(from.$name$_);\n");
}
void RepeatedEnumFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");

View File

@ -58,6 +58,7 @@ class EnumFieldGenerator : public FieldGenerator {
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateCopyConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
@ -65,7 +66,7 @@ class EnumFieldGenerator : public FieldGenerator {
protected:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
std::map<string, string> variables_;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
@ -101,9 +102,9 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateUnsafeMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateCopyConstructorCode(io::Printer* printer) const {}
void GenerateMergeFromCodedStream(io::Printer* printer) const;
void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const;
void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
@ -112,7 +113,7 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
private:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
std::map<string, string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
};

View File

@ -92,7 +92,7 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor,
ExtensionGenerator::~ExtensionGenerator() {}
void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) {
map<string, string> vars;
std::map<string, string> vars;
vars["extendee" ] = ExtendeeClassName(descriptor_);
vars["number" ] = SimpleItoa(descriptor_->number());
vars["type_traits" ] = type_traits_;
@ -128,7 +128,7 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
ClassName(descriptor_->extension_scope(), false) + "::";
string name = scope + descriptor_->name();
map<string, string> vars;
std::map<string, string> vars;
vars["extendee" ] = ExtendeeClassName(descriptor_);
vars["type_traits" ] = type_traits_;
vars["name" ] = name;
@ -167,7 +167,7 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
}
void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
map<string, string> vars;
std::map<string, string> vars;
vars["extendee" ] = ExtendeeClassName(descriptor_);
vars["number" ] = SimpleItoa(descriptor_->number());
vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type()));

View File

@ -59,7 +59,7 @@ namespace cpp {
using internal::WireFormat;
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
map<string, string>* variables,
std::map<string, string>* variables,
const Options& options) {
(*variables)["name"] = FieldName(descriptor);
(*variables)["index"] = SimpleItoa(descriptor->index());
@ -98,7 +98,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
}
void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
map<string, string>* variables) {
std::map<string, string>* variables) {
const string prefix = descriptor->containing_oneof()->name() + "_.";
(*variables)["oneof_prefix"] = prefix;
(*variables)["oneof_name"] = descriptor->containing_oneof()->name();

View File

@ -61,11 +61,11 @@ namespace cpp {
// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
// 'deprecation'].
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
map<string, string>* variables,
std::map<string, string>* variables,
const Options& options);
void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
map<string, string>* variables);
std::map<string, string>* variables);
class FieldGenerator {
public:
@ -124,10 +124,20 @@ class FieldGenerator {
io::Printer* /*printer*/) const {}
// Generate lines of code (statements, not declarations) which clear the
// field. This is used to define the clear_$name$() method as well as
// the Clear() method for the whole message.
// field. This is used to define the clear_$name$() method
virtual void GenerateClearingCode(io::Printer* printer) const = 0;
// Generate lines of code (statements, not declarations) which clear the field
// as part of the Clear() method for the whole message. For message types
// which have field presence bits, MessageGenerator::GenerateClear will have
// already checked the presence bits.
//
// Since most field types can re-use GenerateClearingCode, this method is not
// pure virtual.
virtual void GenerateMessageClearingCode(io::Printer* printer) const {
GenerateClearingCode(printer);
}
// Generate lines of code (statements, not declarations) which merges the
// contents of the field from the current message to the target message,
// which is stored in the generated code variable "from".
@ -136,12 +146,8 @@ class FieldGenerator {
// GenerateMergeFrom method.
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
// The same, but the generated code may or may not check the possibility that
// the two objects being merged have the same address. To be safe, callers
// should avoid calling this unless they know the objects are different.
virtual void GenerateUnsafeMergingCode(io::Printer* printer) const {
GenerateMergingCode(printer);
}
// Generates a copy constructor
virtual void GenerateCopyConstructorCode(io::Printer* printer) const = 0;
// Generate lines of code (statements, not declarations) which swaps
// this field and the corresponding field of another message, which

View File

@ -60,33 +60,42 @@ namespace cpp {
FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
: file_(file),
options_(options),
message_generators_(
new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
enum_generators_(
new google::protobuf::scoped_ptr<EnumGenerator>[file->enum_type_count()]),
service_generators_(
new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]),
extension_generators_(
new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]) {
message_generators_owner_(
new google::protobuf::scoped_ptr<MessageGenerator>[ file->message_type_count() ]),
enum_generators_owner_(
new google::protobuf::scoped_ptr<EnumGenerator>[ file->enum_type_count() ]),
service_generators_owner_(
new google::protobuf::scoped_ptr<ServiceGenerator>[ file->service_count() ]),
extension_generators_owner_(
new google::protobuf::scoped_ptr<ExtensionGenerator>[ file->extension_count() ]) {
for (int i = 0; i < file->message_type_count(); i++) {
message_generators_[i].reset(
new MessageGenerator(file->message_type(i), options));
message_generators_owner_[i].reset(
new MessageGenerator(file->message_type(i), options));
message_generators_owner_[i]->Flatten(&message_generators_);
}
for (int i = 0; i < message_generators_.size(); i++) {
message_generators_[i]->AddGenerators(&enum_generators_,
&extension_generators_);
}
for (int i = 0; i < file->enum_type_count(); i++) {
enum_generators_[i].reset(
new EnumGenerator(file->enum_type(i), options));
enum_generators_owner_[i].reset(
new EnumGenerator(file->enum_type(i), options));
enum_generators_.push_back(enum_generators_owner_[i].get());
}
for (int i = 0; i < file->service_count(); i++) {
service_generators_[i].reset(
new ServiceGenerator(file->service(i), options));
service_generators_owner_[i].reset(
new ServiceGenerator(file->service(i), options));
service_generators_.push_back(service_generators_owner_[i].get());
}
for (int i = 0; i < file->extension_count(); i++) {
extension_generators_[i].reset(
new ExtensionGenerator(file->extension(i), options));
extension_generators_owner_[i].reset(
new ExtensionGenerator(file->extension(i), options));
extension_generators_.push_back(extension_generators_owner_[i].get());
}
package_parts_ = Split(file_->package(), ".", true);
@ -94,29 +103,7 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
FileGenerator::~FileGenerator() {}
void FileGenerator::GenerateProtoHeader(io::Printer* printer,
const string& info_path) {
if (!options_.proto_h) {
return;
}
string filename_identifier = FilenameIdentifier(file_->name());
GenerateTopHeaderGuard(printer, filename_identifier);
GenerateLibraryIncludes(printer);
for (int i = 0; i < file_->public_dependency_count(); i++) {
const FileDescriptor* dep = file_->public_dependency(i);
const char* extension = ".proto.h";
string dependency = StripProto(dep->name()) + extension;
printer->Print(
"#include \"$dependency$\" // IWYU pragma: export\n",
"dependency", dependency);
}
GenerateMetadataPragma(printer, info_path);
void FileGenerator::GenerateHeader(io::Printer* printer) {
printer->Print(
"// @@protoc_insertion_point(includes)\n");
@ -166,6 +153,32 @@ void FileGenerator::GenerateProtoHeader(io::Printer* printer,
"\n"
"// @@protoc_insertion_point(global_scope)\n"
"\n");
}
void FileGenerator::GenerateProtoHeader(io::Printer* printer,
const string& info_path) {
if (!options_.proto_h) {
return;
}
string filename_identifier = FilenameIdentifier(file_->name());
GenerateTopHeaderGuard(printer, filename_identifier);
GenerateLibraryIncludes(printer);
for (int i = 0; i < file_->public_dependency_count(); i++) {
const FileDescriptor* dep = file_->public_dependency(i);
const char* extension = ".proto.h";
string dependency = StripProto(dep->name()) + extension;
printer->Print(
"#include \"$dependency$\" // IWYU pragma: export\n",
"dependency", dependency);
}
GenerateMetadataPragma(printer, info_path);
GenerateHeader(printer);
GenerateBottomHeaderGuard(printer, filename_identifier);
}
@ -185,59 +198,29 @@ void FileGenerator::GeneratePBHeader(io::Printer* printer,
GenerateDependencyIncludes(printer);
GenerateMetadataPragma(printer, info_path);
printer->Print(
"// @@protoc_insertion_point(includes)\n");
// Open namespace.
GenerateNamespaceOpeners(printer);
if (!options_.proto_h) {
GenerateGlobalStateFunctionDeclarations(printer);
GenerateMessageForwardDeclarations(printer);
GenerateHeader(printer);
} else {
// This is unfortunately necessary for some plugins. I don't see why we
// need two of the same insertion points.
// TODO(gerbens) remove this.
printer->Print(
"// @@protoc_insertion_point(includes)\n");
printer->Print("\n");
// Open namespace.
GenerateNamespaceOpeners(printer);
printer->Print(
"\n"
"// @@protoc_insertion_point(namespace_scope)\n");
// Close up namespace.
GenerateNamespaceClosers(printer);
GenerateEnumDefinitions(printer);
printer->Print(kThickSeparator);
printer->Print("\n");
GenerateMessageDefinitions(printer);
printer->Print("\n");
printer->Print(kThickSeparator);
printer->Print("\n");
GenerateServiceDefinitions(printer);
GenerateExtensionIdentifiers(printer);
printer->Print("\n");
printer->Print(kThickSeparator);
printer->Print("\n");
GenerateInlineFunctionDefinitions(printer);
printer->Print(
"\n"
"// @@protoc_insertion_point(global_scope)\n"
"\n");
}
printer->Print(
"\n"
"// @@protoc_insertion_point(namespace_scope)\n");
// Close up namespace.
GenerateNamespaceClosers(printer);
if (!options_.proto_h) {
// We need to specialize some templates in the ::google::protobuf namespace:
GenerateProto2NamespaceEnumSpecializations(printer);
}
printer->Print(
"\n"
"// @@protoc_insertion_point(global_scope)\n"
"\n");
GenerateBottomHeaderGuard(printer, filename_identifier);
}
@ -267,7 +250,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"right", use_system_include ? ">" : "\"");
// Unknown fields implementation in lite mode uses StringOutputStream
if (!UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) {
if (!UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) {
printer->Print(
"#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
}
@ -297,25 +280,48 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
GenerateNamespaceOpeners(printer);
for (int i = 0; i < message_generators_.size(); i++) {
if (IsMapEntryMessage(message_generators_[i]->descriptor_)) continue;
printer->Print(
"class $classname$DefaultTypeInternal : "
"public ::google::protobuf::internal::ExplicitlyConstructed<$classname$> {};\n"
"$classname$DefaultTypeInternal _$classname$_default_instance_;\n",
"classname", message_generators_[i]->classname_);
}
if (HasDescriptorMethods(file_, options_)) {
printer->Print(
"\n"
"namespace {\n"
"\n");
for (int i = 0; i < file_->message_type_count(); i++) {
message_generators_[i]->GenerateDescriptorDeclarations(printer);
if (!message_generators_.empty()) {
printer->Print("::google::protobuf::Metadata file_level_metadata[$size$];\n",
"size", SimpleItoa(message_generators_.size()));
}
for (int i = 0; i < file_->enum_type_count(); i++) {
if (!enum_generators_.empty()) {
printer->Print(
"const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
"name", ClassName(file_->enum_type(i), false));
"const ::google::protobuf::EnumDescriptor* "
"file_level_enum_descriptors[$size$];\n",
"size", SimpleItoa(enum_generators_.size()));
}
if (HasGenericServices(file_, options_) && file_->service_count() > 0) {
printer->Print(
"const ::google::protobuf::ServiceDescriptor* "
"file_level_service_descriptors[$size$];\n",
"size", SimpleItoa(file_->service_count()));
}
for (int i = 0; i < message_generators_.size(); i++) {
message_generators_[i]->index_in_metadata_ = i;
message_generators_[i]->GenerateDescriptorDeclarations(printer);
}
for (int i = 0; i < enum_generators_.size(); i++) {
enum_generators_[i]->index_in_metadata_ = i;
}
if (HasGenericServices(file_, options_)) {
for (int i = 0; i < file_->service_count(); i++) {
printer->Print(
"const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
"name", file_->service(i)->name());
for (int i = 0; i < service_generators_.size(); i++) {
service_generators_[i]->index_in_metadata_ = i;
}
}
@ -330,26 +336,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
GenerateBuildDescriptors(printer);
// Generate enums.
for (int i = 0; i < file_->enum_type_count(); i++) {
for (int i = 0; i < enum_generators_.size(); i++) {
enum_generators_[i]->GenerateMethods(printer);
}
// Generate classes.
for (int i = 0; i < file_->message_type_count(); i++) {
if (i == 0 && HasGeneratedMethods(file_, options_)) {
printer->Print(
"\n"
"namespace {\n"
"\n"
"static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD"
" GOOGLE_ATTRIBUTE_NORETURN;\n"
"static void MergeFromFail(int line) {\n"
" ::google::protobuf::internal::MergeFromFail(__FILE__, line);\n"
"}\n"
"\n"
"} // namespace\n"
"\n");
}
for (int i = 0; i < message_generators_.size(); i++) {
printer->Print("\n");
printer->Print(kThickSeparator);
printer->Print("\n");
@ -364,7 +356,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
if (HasGenericServices(file_, options_)) {
// Generate services.
for (int i = 0; i < file_->service_count(); i++) {
for (int i = 0; i < service_generators_.size(); i++) {
if (i == 0) printer->Print("\n");
printer->Print(kThickSeparator);
printer->Print("\n");
@ -373,7 +365,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
}
// Define extensions.
for (int i = 0; i < file_->extension_count(); i++) {
for (int i = 0; i < extension_generators_.size(); i++) {
extension_generators_[i]->GenerateDefinition(printer);
}
@ -391,8 +383,9 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
class FileGenerator::ForwardDeclarations {
public:
~ForwardDeclarations() {
for (map<string, ForwardDeclarations *>::iterator it = namespaces_.begin(),
end = namespaces_.end();
for (std::map<string, ForwardDeclarations*>::iterator
it = namespaces_.begin(),
end = namespaces_.end();
it != end; ++it) {
delete it->second;
}
@ -407,11 +400,11 @@ class FileGenerator::ForwardDeclarations {
return ns;
}
map<string, const Descriptor*>& classes() { return classes_; }
map<string, const EnumDescriptor*>& enums() { return enums_; }
std::map<string, const Descriptor*>& classes() { return classes_; }
std::map<string, const EnumDescriptor*>& enums() { return enums_; }
void Print(io::Printer* printer) const {
for (map<string, const EnumDescriptor *>::const_iterator
for (std::map<string, const EnumDescriptor *>::const_iterator
it = enums_.begin(),
end = enums_.end();
it != end; ++it) {
@ -420,13 +413,21 @@ class FileGenerator::ForwardDeclarations {
printer->Print("bool $enumname$_IsValid(int value);\n", "enumname",
it->first);
}
for (map<string, const Descriptor *>::const_iterator it = classes_.begin(),
end = classes_.end();
for (std::map<string, const Descriptor*>::const_iterator
it = classes_.begin(),
end = classes_.end();
it != end; ++it) {
printer->Print("class $classname$;\n", "classname", it->first);
printer->Annotate("classname", it->second);
printer->Print(
"class $classname$DefaultTypeInternal;\n"
"extern $classname$DefaultTypeInternal "
"_$classname$_default_instance_;\n", // NOLINT
"classname",
it->first);
}
for (map<string, ForwardDeclarations *>::const_iterator
for (std::map<string, ForwardDeclarations *>::const_iterator
it = namespaces_.begin(),
end = namespaces_.end();
it != end; ++it) {
@ -440,9 +441,9 @@ class FileGenerator::ForwardDeclarations {
private:
map<string, ForwardDeclarations*> namespaces_;
map<string, const Descriptor*> classes_;
map<string, const EnumDescriptor*> enums_;
std::map<string, ForwardDeclarations*> namespaces_;
std::map<string, const Descriptor*> classes_;
std::map<string, const EnumDescriptor*> enums_;
};
void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
@ -465,75 +466,135 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// and we only use AddDescriptors() to allocate default instances.
if (HasDescriptorMethods(file_, options_)) {
printer->Print(
"\n"
"void $assigndescriptorsname$() GOOGLE_ATTRIBUTE_COLD;\n"
"void $assigndescriptorsname$() {\n",
"assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
printer->Indent();
if (!message_generators_.empty()) {
printer->Print(
"\n"
"const ::google::protobuf::uint32* $offsetfunname$() GOOGLE_ATTRIBUTE_COLD;\n"
"const ::google::protobuf::uint32* $offsetfunname$() {\n",
"offsetfunname", GlobalOffsetTableName(file_->name()));
printer->Indent();
// Make sure the file has found its way into the pool. If a descriptor
// is requested *during* static init then AddDescriptors() may not have
// been called yet, so we call it manually. Note that it's fine if
// AddDescriptors() is called multiple times.
printer->Print(
"$adddescriptorsname$();\n",
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
// Get the file's descriptor from the pool.
printer->Print(
"const ::google::protobuf::FileDescriptor* file =\n"
" ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n"
" \"$filename$\");\n"
// Note that this GOOGLE_CHECK is necessary to prevent a warning about "file"
// being unused when compiling an empty .proto file.
"GOOGLE_CHECK(file != NULL);\n",
"filename", file_->name());
// Go through all the stuff defined in this file and generated code to
// assign the global descriptor pointers based on the file descriptor.
for (int i = 0; i < file_->message_type_count(); i++) {
message_generators_[i]->GenerateDescriptorInitializer(printer, i);
}
for (int i = 0; i < file_->enum_type_count(); i++) {
enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
}
if (HasGenericServices(file_, options_)) {
for (int i = 0; i < file_->service_count(); i++) {
service_generators_[i]->GenerateDescriptorInitializer(printer, i);
printer->Print("static const ::google::protobuf::uint32 offsets[] = {\n");
printer->Indent();
std::vector<std::pair<size_t, size_t> > pairs;
for (int i = 0; i < message_generators_.size(); i++) {
pairs.push_back(message_generators_[i]->GenerateOffsets(printer));
}
}
printer->Outdent();
printer->Outdent();
printer->Print(
" };\n"
" return offsets;\n"
"}\n"
"\n");
printer->Outdent();
printer->Print(
"}\n"
"\n");
printer->Print(
"static const ::google::protobuf::internal::MigrationSchema schemas[] = {\n");
printer->Indent();
{
int offset = 0;
for (int i = 0; i < message_generators_.size(); i++) {
message_generators_[i]->GenerateSchema(printer, offset,
pairs[i].second);
offset += pairs[i].first;
}
}
printer->Outdent();
printer->Print(
"};\n"
"\n"
"static const ::google::protobuf::internal::DefaultInstanceData "
"file_default_instances[] = {\n");
printer->Indent();
for (int i = 0; i < message_generators_.size(); i++) {
const Descriptor* descriptor = message_generators_[i]->descriptor_;
if (IsMapEntryMessage(descriptor)) continue;
string oneof_default = "NULL";
if (message_generators_[i]->descriptor_->oneof_decl_count()) {
oneof_default =
"&" + ClassName(descriptor, false) + "_default_oneof_instance_";
}
printer->Print(
"{reinterpret_cast<const "
"::google::protobuf::Message*>(&_$classname$_default_instance_), "
"$oneof_default$},\n",
"classname", ClassName(descriptor, false), "oneof_default",
oneof_default);
}
printer->Outdent();
printer->Print(
"};\n"
"\n");
} else {
// we still need these symbols to exist
printer->Print(
"inline ::google::protobuf::uint32* $offsetfunname$() { return NULL; }\n"
"static const ::google::protobuf::internal::MigrationSchema* schemas = NULL;\n"
"static const ::google::protobuf::internal::DefaultInstanceData* "
"file_default_instances = NULL;\n",
"offsetfunname",
GlobalOffsetTableName(file_->name()));
}
// ---------------------------------------------------------------
// protobuf_AssignDescriptorsOnce(): The first time it is called, calls
// AssignDescriptors(). All later times, waits for the first call to
// complete and then returns.
string message_factory = "NULL";
printer->Print(
"namespace {\n"
"\n"
"GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
"void protobuf_AssignDescriptors() {\n"
// Make sure the file has found its way into the pool. If a descriptor
// is requested *during* static init then AddDescriptors() may not have
// been called yet, so we call it manually. Note that it's fine if
// AddDescriptors() is called multiple times.
" $adddescriptorsname$();\n"
" ::google::protobuf::MessageFactory* factory = $factory$;\n"
" AssignDescriptors(\n"
" \"$filename$\", schemas, file_default_instances, "
"$offsetfunname$(), factory,\n"
" $metadata$, $enum_descriptors$, $service_descriptors$);\n"
"}\n"
"\n"
"void protobuf_AssignDescriptorsOnce() {\n"
" ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
" &$assigndescriptorsname$);\n"
" static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n"
" ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);\n"
"}\n"
"\n",
"assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
"offsetfunname", GlobalOffsetTableName(file_->name()), "filename",
file_->name(), "metadata",
!message_generators_.empty() ? "file_level_metadata" : "NULL",
"enum_descriptors",
!enum_generators_.empty() ? "file_level_enum_descriptors" : "NULL",
"service_descriptors",
HasGenericServices(file_, options_) && file_->service_count() > 0
? "file_level_service_descriptors"
: "NULL",
"factory", message_factory);
// protobuf_RegisterTypes(): Calls
// MessageFactory::InternalRegisterGeneratedType() for each message type.
// Only here because of useless string reference that we don't want in
// protobuf_AssignDescriptorsOnce, because that is called from all the
// GetMetadata member methods.
printer->Print(
"void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;\n"
"void protobuf_RegisterTypes(const ::std::string&) {\n"
" protobuf_AssignDescriptorsOnce();\n");
printer->Indent();
for (int i = 0; i < file_->message_type_count(); i++) {
// All normal messages can be done generically
if (!message_generators_.empty()) {
printer->Print(
"::google::protobuf::internal::RegisterAllTypes(file_level_metadata, $size$);\n",
"size", SimpleItoa(message_generators_.size()));
}
// Map types are treated special
// TODO(gerbens) find a way to treat maps more like normal messages.
for (int i = 0; i < message_generators_.size(); i++) {
message_generators_[i]->GenerateTypeRegistrations(printer);
}
@ -553,7 +614,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
"shutdownfilename", GlobalShutdownFileName(file_->name()));
printer->Indent();
for (int i = 0; i < file_->message_type_count(); i++) {
for (int i = 0; i < message_generators_.size(); i++) {
message_generators_[i]->GenerateShutdownCode(printer);
}
@ -566,8 +627,8 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// Now generate the InitDefaults() function.
printer->Print(
"void $initdefaultsname$_impl() {\n"
" GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
"\n",
" GOOGLE_PROTOBUF_VERIFY_VERSION;\n\n"
"",
// Vars.
"initdefaultsname", GlobalInitDefaultsName(file_->name()));
@ -586,26 +647,28 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
"name", add_desc_name);
}
// Force initialization of primitive values we depend on.
printer->Print("::google::protobuf::internal::InitProtobufDefaults();\n");
// Allocate and initialize default instances. This can't be done lazily
// since default instances are returned by simple accessors and are used with
// extensions. Speaking of which, we also register extensions at this time.
for (int i = 0; i < file_->message_type_count(); i++) {
for (int i = 0; i < message_generators_.size(); i++) {
message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
}
for (int i = 0; i < file_->extension_count(); i++) {
for (int i = 0; i < extension_generators_.size(); i++) {
extension_generators_[i]->GenerateRegistration(printer);
}
for (int i = 0; i < file_->message_type_count(); i++) {
for (int i = 0; i < message_generators_.size(); i++) {
message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
}
printer->Outdent();
printer->Print(
"}\n"
"\n"
"GOOGLE_PROTOBUF_DECLARE_ONCE($initdefaultsname$_once_);\n"
"void $initdefaultsname$() {\n"
" ::google::protobuf::GoogleOnceInit(&$initdefaultsname$_once_,\n"
" &$initdefaultsname$_impl);\n"
" static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n"
" ::google::protobuf::GoogleOnceInit(&once, &$initdefaultsname$_impl);\n"
"}\n",
"initdefaultsname", GlobalInitDefaultsName(file_->name()));
@ -614,8 +677,6 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// Now generate the AddDescriptors() function.
printer->Print(
"void $adddescriptorsname$_impl() {\n"
" GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
"\n"
" $initdefaultsname$();\n",
// Vars.
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
@ -632,60 +693,42 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
string file_data;
file_proto.SerializeToString(&file_data);
printer->Print("static const char descriptor[] = {\n");
printer->Indent();
#ifdef _MSC_VER
bool breakdown_large_file = true;
#else
bool breakdown_large_file = false;
#endif
// Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
// bytes in length". Declare a static array of characters rather than use a
// string literal.
if (breakdown_large_file && file_data.size() > 65535) {
// This has to be explicitly marked as a signed char because the generated
// code puts negative values in the array, and sometimes plain char is
// unsigned. That implicit narrowing conversion is not allowed in C++11.
// <http://stackoverflow.com/questions/4434140/narrowing-conversions-in-c0x-is-it-just-me-or-does-this-sound-like-a-breakin>
// has details on why.
printer->Print(
"static const signed char descriptor[] = {\n");
printer->Indent();
// Only write 25 bytes per line.
if (breakdown_large_file && file_data.size() > 66538) {
// Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
// bytes in length". Declare a static array of characters rather than use
// a string literal. Only write 25 bytes per line.
static const int kBytesPerLine = 25;
for (int i = 0; i < file_data.size();) {
for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
printer->Print(
"$char$, ",
"char", SimpleItoa(file_data[i]));
}
printer->Print(
"\n");
for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
printer->Print("'$char$', ", "char",
CEscape(file_data.substr(i, 1)));
}
printer->Print("\n");
}
printer->Outdent();
printer->Print(
"};\n");
printer->Print(
"::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
"size", SimpleItoa(file_data.size()));
} else {
printer->Print(
"::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
// Only write 40 bytes per line.
static const int kBytesPerLine = 40;
for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
printer->Print("\n \"$data$\"",
"data",
EscapeTrigraphs(
CEscape(file_data.substr(i, kBytesPerLine))));
printer->Print(" \"$data$\"\n", "data",
EscapeTrigraphs(CEscape(
file_data.substr(i, kBytesPerLine))));
}
}
printer->Outdent();
printer->Print("};\n");
printer->Print(
", $size$);\n",
"::google::protobuf::DescriptorPool::InternalAddGeneratedFile(\n"
" descriptor, $size$);\n",
"size", SimpleItoa(file_data.size()));
}
// Call MessageFactory::InternalRegisterGeneratedFile().
printer->Print(
@ -777,14 +820,11 @@ void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) {
decls = decls->AddOrGetNamespace(package_parts_[i]);
}
// Generate enum definitions.
for (int i = 0; i < file_->message_type_count(); i++) {
message_generators_[i]->FillEnumForwardDeclarations(&decls->enums());
}
for (int i = 0; i < file_->enum_type_count(); i++) {
for (int i = 0; i < enum_generators_.size(); i++) {
enum_generators_[i]->FillForwardDeclaration(&decls->enums());
}
// Generate forward declarations of classes.
for (int i = 0; i < file_->message_type_count(); i++) {
for (int i = 0; i < message_generators_.size(); i++) {
message_generators_[i]->FillMessageForwardDeclarations(
&decls->classes());
}
@ -840,12 +880,10 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
printer->Print(
"#include <google/protobuf/arena.h>\n"
"#include <google/protobuf/arenastring.h>\n"
"#include <google/protobuf/generated_message_util.h>\n");
if (UseUnknownFieldSet(file_, options_)) {
printer->Print(
"#include <google/protobuf/metadata.h>\n");
}
if (file_->message_type_count() > 0) {
"#include <google/protobuf/generated_message_util.h>\n"
"#include <google/protobuf/metadata.h>\n");
if (!message_generators_.empty()) {
if (HasDescriptorMethods(file_, options_)) {
printer->Print(
"#include <google/protobuf/message.h>\n");
@ -855,8 +893,10 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
}
}
printer->Print(
"#include <google/protobuf/repeated_field.h>\n"
"#include <google/protobuf/extension_set.h>\n");
"#include <google/protobuf/repeated_field.h>"
" // IWYU pragma: export\n"
"#include <google/protobuf/extension_set.h>"
" // IWYU pragma: export\n");
if (HasMapFields(file_)) {
printer->Print(
"#include <google/protobuf/map.h>\n");
@ -884,7 +924,7 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
"#include <google/protobuf/service.h>\n");
}
if (UseUnknownFieldSet(file_, options_) && file_->message_type_count() > 0) {
if (UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) {
printer->Print(
"#include <google/protobuf/unknown_field_set.h>\n");
}
@ -910,7 +950,7 @@ void FileGenerator::GenerateMetadataPragma(io::Printer* printer,
}
void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
set<string> public_import_names;
std::set<string> public_import_names;
for (int i = 0; i < file_->public_dependency_count(); i++) {
public_import_names.insert(file_->public_dependency(i)->name());
}
@ -943,33 +983,11 @@ void FileGenerator::GenerateGlobalStateFunctionDeclarations(
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
"dllexport_decl",
options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
printer->Print(
// Note that we don't put dllexport_decl on these because they are only
// called by the .pb.cc file in which they are defined.
"void $assigndescriptorsname$();\n"
"void $shutdownfilename$();\n"
"\n",
"assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
"shutdownfilename", GlobalShutdownFileName(file_->name()));
}
void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
map<string, const Descriptor*> classes;
for (int i = 0; i < file_->message_type_count(); i++) {
message_generators_[i]->FillMessageForwardDeclarations(&classes);
}
for (map<string, const Descriptor *>::const_iterator it = classes.begin(),
end = classes.end();
it != end; ++it) {
printer->Print("class $classname$;\n", "classname", it->first);
printer->Annotate("classname", it->second);
}
}
void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
// Generate class definitions.
for (int i = 0; i < file_->message_type_count(); i++) {
for (int i = 0; i < message_generators_.size(); i++) {
if (i > 0) {
printer->Print("\n");
printer->Print(kThinSeparator);
@ -981,10 +999,7 @@ void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
// Generate enum definitions.
for (int i = 0; i < file_->message_type_count(); i++) {
message_generators_[i]->GenerateEnumDefinitions(printer);
}
for (int i = 0; i < file_->enum_type_count(); i++) {
for (int i = 0; i < enum_generators_.size(); i++) {
enum_generators_[i]->GenerateDefinition(printer);
}
}
@ -992,7 +1007,7 @@ void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
if (HasGenericServices(file_, options_)) {
// Generate service definitions.
for (int i = 0; i < file_->service_count(); i++) {
for (int i = 0; i < service_generators_.size(); i++) {
if (i > 0) {
printer->Print("\n");
printer->Print(kThinSeparator);
@ -1008,9 +1023,10 @@ void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
}
void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
// Declare extension identifiers.
// Declare extension identifiers. These are in global scope and so only
// the global scope extensions.
for (int i = 0; i < file_->extension_count(); i++) {
extension_generators_[i]->GenerateDeclaration(printer);
extension_generators_owner_[i]->GenerateDeclaration(printer);
}
}
@ -1051,7 +1067,7 @@ void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
// Generate class inline methods.
for (int i = 0; i < file_->message_type_count(); i++) {
for (int i = 0; i < message_generators_.size(); i++) {
if (i > 0) {
printer->Print(kThinSeparator);
printer->Print("\n");
@ -1061,7 +1077,7 @@ void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
}
printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
for (int i = 0; i < file_->message_type_count(); i++) {
for (int i = 0; i < message_generators_.size(); i++) {
if (i > 0) {
printer->Print(kThinSeparator);
printer->Print("\n");
@ -1084,10 +1100,7 @@ void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
"#ifndef SWIG\n"
"namespace google {\nnamespace protobuf {\n"
"\n");
for (int i = 0; i < file_->message_type_count(); i++) {
message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
}
for (int i = 0; i < file_->enum_type_count(); i++) {
for (int i = 0; i < enum_generators_.size(); i++) {
enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
}
printer->Print(

View File

@ -68,6 +68,9 @@ class FileGenerator {
FileGenerator(const FileDescriptor* file, const Options& options);
~FileGenerator();
// Shared code between the two header generators below.
void GenerateHeader(io::Printer* printer);
// info_path, if non-empty, should be the path (relative to printer's output)
// to the metadata file describing this proto header.
void GenerateProtoHeader(io::Printer* printer,
@ -117,18 +120,6 @@ class FileGenerator {
// Generates types for classes.
void GenerateMessageDefinitions(io::Printer* printer);
// Generates forward-declarations for just this file's classes. This is
// used for .pb.h headers, but not in proto_h mode.
void GenerateMessageForwardDeclarations(io::Printer* printer);
// Fills in types for forward declarations. This is used internally, and
// also by other FileGenerators to determine imports' declarations.
void FillMessageForwardDeclarations(ForwardDeclarations* decls);
void FillMessageDefinitions(ForwardDeclarations* decls);
// Generates enum definitions.
void GenerateEnumForwardDeclarations(io::Printer* printer);
void FillEnumForwardDeclarations(ForwardDeclarations* decls);
void GenerateEnumDefinitions(io::Printer* printer);
// Generates generic service definitions.
@ -145,13 +136,25 @@ class FileGenerator {
const FileDescriptor* file_;
const Options options_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > message_generators_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ServiceGenerator> > service_generators_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
// Contains the post-order walk of all the messages (and child messages) in
// this file. If you need a pre-order walk just reverse iterate.
std::vector<MessageGenerator*> message_generators_;
std::vector<EnumGenerator*> enum_generators_;
std::vector<ServiceGenerator*> service_generators_;
std::vector<ExtensionGenerator*> extension_generators_;
// These members are just for owning (and thus proper deleting). Some of the
// message_ and enum_generators above are owned by child messages.
google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> >
message_generators_owner_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_owner_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ServiceGenerator> >
service_generators_owner_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> >
extension_generators_owner_;
// E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
vector<string> package_parts_;
std::vector<string> package_parts_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
};

View File

@ -59,7 +59,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
const string& parameter,
GeneratorContext* generator_context,
string* error) const {
vector<pair<string, string> > options;
std::vector<std::pair<string, string> > options;
ParseGeneratorParameter(parameter, &options);
// -----------------------------------------------------------------

View File

@ -371,9 +371,9 @@ string DefaultValue(const FieldDescriptor* field) {
return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")";
case FieldDescriptor::CPPTYPE_DOUBLE: {
double value = field->default_value_double();
if (value == numeric_limits<double>::infinity()) {
if (value == std::numeric_limits<double>::infinity()) {
return "::google::protobuf::internal::Infinity()";
} else if (value == -numeric_limits<double>::infinity()) {
} else if (value == -std::numeric_limits<double>::infinity()) {
return "-::google::protobuf::internal::Infinity()";
} else if (value != value) {
return "::google::protobuf::internal::NaN()";
@ -384,9 +384,9 @@ string DefaultValue(const FieldDescriptor* field) {
case FieldDescriptor::CPPTYPE_FLOAT:
{
float value = field->default_value_float();
if (value == numeric_limits<float>::infinity()) {
if (value == std::numeric_limits<float>::infinity()) {
return "static_cast<float>(::google::protobuf::internal::Infinity())";
} else if (value == -numeric_limits<float>::infinity()) {
} else if (value == -std::numeric_limits<float>::infinity()) {
return "static_cast<float>(-::google::protobuf::internal::Infinity())";
} else if (value != value) {
return "static_cast<float>(::google::protobuf::internal::NaN())";
@ -450,8 +450,8 @@ string GlobalInitDefaultsName(const string& filename) {
}
// Return the name of the AssignDescriptors() function for a given file.
string GlobalAssignDescriptorsName(const string& filename) {
return "protobuf_AssignDesc_" + FilenameIdentifier(filename);
string GlobalOffsetTableName(const string& filename) {
return "protobuf_Offsets_" + FilenameIdentifier(filename);
}
// Return the name of the ShutdownFile() function for a given file.
@ -602,7 +602,7 @@ static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
static void GenerateUtf8CheckCode(const FieldDescriptor* field,
const Options& options, bool for_parse,
const map<string, string>& variables,
const std::map<string, string>& variables,
const char* parameters,
const char* strict_function,
const char* verify_function,
@ -652,7 +652,7 @@ static void GenerateUtf8CheckCode(const FieldDescriptor* field,
void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
const Options& options, bool for_parse,
const map<string, string>& variables,
const std::map<string, string>& variables,
const char* parameters,
io::Printer* printer) {
GenerateUtf8CheckCode(field, options, for_parse, variables, parameters,
@ -662,7 +662,7 @@ void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
const Options& options, bool for_parse,
const map<string, string>& variables,
const std::map<string, string>& variables,
const char* parameters,
io::Printer* printer) {
GenerateUtf8CheckCode(field, options, for_parse, variables, parameters,

View File

@ -150,8 +150,8 @@ string GlobalAddDescriptorsName(const string& filename);
// Return the name of the InitDefaults() function for a given file.
string GlobalInitDefaultsName(const string& filename);
// Return the name of the AssignDescriptors() function for a given file.
string GlobalAssignDescriptorsName(const string& filename);
// Return the name of the offset table function for a given file.
string GlobalOffsetTableName(const string& filename);
// Return the qualified C++ name for a file level symbol.
string QualifiedFileLevelSymbol(const string& package, const string& name);
@ -269,13 +269,13 @@ bool IsWellKnownMessage(const FileDescriptor* descriptor);
void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
const Options& options, bool for_parse,
const map<string, string>& variables,
const std::map<string, string>& variables,
const char* parameters,
io::Printer* printer);
void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
const Options& options, bool for_parse,
const map<string, string>& variables,
const std::map<string, string>& variables,
const char* parameters, io::Printer* printer);
inline ::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(

View File

@ -45,10 +45,10 @@ bool IsProto3Field(const FieldDescriptor* field_descriptor) {
}
void SetMessageVariables(const FieldDescriptor* descriptor,
map<string, string>* variables,
std::map<string, string>* variables,
const Options& options) {
SetCommonFieldVariables(descriptor, variables, options);
(*variables)["type"] = FieldMessageTypeName(descriptor);
(*variables)["type"] = ClassName(descriptor->message_type(), false);
(*variables)["stream_writer"] =
(*variables)["declared_type"] +
(HasFastArraySerialization(descriptor->message_type()->file(), options)
@ -137,7 +137,7 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
void MapFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
std::map<string, string> variables(variables_);
variables["inline"] = is_inline ? "inline" : "";
printer->Print(variables,
"$inline$ const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
@ -154,7 +154,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
void MapFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
map<string, string> variables(variables_);
std::map<string, string> variables(variables_);
variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
printer->Print(variables, "$this_message$$name$_.Clear();\n");
}
@ -173,13 +173,19 @@ void MapFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
if (HasDescriptorMethods(descriptor_->file(), options_)) {
printer->Print(variables_,
"$name$_.SetAssignDescriptorCallback(\n"
" protobuf_AssignDescriptorsOnce);\n"
"$name$_.SetEntryDescriptor(\n"
" &$type$_descriptor_);\n");
"$name$_.SetAssignDescriptorCallback(\n"
" protobuf_AssignDescriptorsOnce);\n"
"$name$_.SetEntryDescriptor(\n"
" &$type$_descriptor);\n");
}
}
void MapFieldGenerator::
GenerateCopyConstructorCode(io::Printer* printer) const {
GenerateConstructorCode(printer);
GenerateMergingCode(printer);
}
void MapFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
const FieldDescriptor* key_field =
@ -252,7 +258,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
}
static void GenerateSerializationLoop(io::Printer* printer,
const map<string, string>& variables,
const std::map<string, string>& variables,
bool supports_arenas,
const string& utf8_check,
const string& loop_header,
@ -291,17 +297,17 @@ static void GenerateSerializationLoop(io::Printer* printer,
void MapFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
map<string, string> variables(variables_);
std::map<string, string> variables(variables_);
variables["write_entry"] = "::google::protobuf::internal::WireFormatLite::Write" +
variables["stream_writer"] + "(\n " +
variables["number"] + ", *entry, output)";
variables["deterministic"] = "output->IsSerializationDeterminstic()";
variables["deterministic"] = "output->IsSerializationDeterministic()";
GenerateSerializeWithCachedSizes(printer, variables);
}
void MapFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
map<string, string> variables(variables_);
std::map<string, string> variables(variables_);
variables["write_entry"] =
"target = ::google::protobuf::internal::WireFormatLite::\n"
" InternalWrite" + variables["declared_type"] +
@ -312,7 +318,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
}
void MapFieldGenerator::GenerateSerializeWithCachedSizes(
io::Printer* printer, const map<string, string>& variables) const {
io::Printer* printer, const std::map<string, string>& variables) const {
printer->Print(variables,
"if (!this->$name$().empty()) {\n");
printer->Indent();

Some files were not shown because too many files have changed in this diff Show More