Submit recent changes from internal branch, including "lite mode" for
C++ and Java. See CHANGES.txt for more details.
This commit is contained in:
parent
d2fd0638c3
commit
80b1d62bfc
26
CHANGES.txt
26
CHANGES.txt
@ -1,6 +1,9 @@
|
||||
????-??-?? version 2.1.1:
|
||||
????-??-?? version 2.2.0:
|
||||
|
||||
C++
|
||||
* Lite mode: The "optimize_for = LITE_RUNTIME" option causes the compiler
|
||||
to generate code which only depends libprotobuf-lite, which is much smaller
|
||||
than libprotobuf but lacks descriptors, reflection, and some other features.
|
||||
* Fixed bug where Message.Swap(Message) was only implemented for
|
||||
optimize_for_speed. Swap now properly implemented in both modes
|
||||
(Issue 91).
|
||||
@ -10,6 +13,27 @@
|
||||
* Floating-point literals in generated code that are intended to be
|
||||
single-precision now explicitly have 'f' suffix to avoid pedantic warnings
|
||||
produced by some compilers.
|
||||
* The [deprecated=true] option now causes the C++ code generator to generate
|
||||
a GCC-style deprecation annotation (no-op on other compilers).
|
||||
* google::protobuf::GetEnumDescriptor<SomeGeneratedEnumType>() returns the
|
||||
EnumDescriptor for that type -- useful for templates which cannot call
|
||||
SomeGeneratedEnumType_descriptor().
|
||||
* Various optimizations and obscure bug fixes.
|
||||
|
||||
Java
|
||||
* Lite mode: The "optimize_for = LITE_RUNTIME" option causes the compiler
|
||||
to generate code which only depends libprotobuf-lite, which is much smaller
|
||||
than libprotobuf but lacks descriptors, reflection, and some other features.
|
||||
* Put Builder objects on a freelist after build() is called, so they may be
|
||||
reused later.
|
||||
* Lots of style cleanups.
|
||||
|
||||
Python
|
||||
* Fixed endianness bug with floats and doubles.
|
||||
* Text format parsing support.
|
||||
* Fix bug with parsing packed repeated fields in embedded messages.
|
||||
* Ability to initialize fields by passing keyword args to constructor.
|
||||
* Support iterators in extend and __setslice__ for containers.
|
||||
|
||||
2009-05-13 version 2.1.0:
|
||||
|
||||
|
@ -62,6 +62,7 @@ EXTRA_DIST = \
|
||||
examples/add_person.py \
|
||||
examples/list_people.py \
|
||||
java/src/main/java/com/google/protobuf/AbstractMessage.java \
|
||||
java/src/main/java/com/google/protobuf/AbstractMessageLite.java \
|
||||
java/src/main/java/com/google/protobuf/BlockingRpcChannel.java \
|
||||
java/src/main/java/com/google/protobuf/BlockingService.java \
|
||||
java/src/main/java/com/google/protobuf/ByteString.java \
|
||||
@ -70,10 +71,14 @@ EXTRA_DIST = \
|
||||
java/src/main/java/com/google/protobuf/Descriptors.java \
|
||||
java/src/main/java/com/google/protobuf/DynamicMessage.java \
|
||||
java/src/main/java/com/google/protobuf/ExtensionRegistry.java \
|
||||
java/src/main/java/com/google/protobuf/ExtensionRegistryLite.java \
|
||||
java/src/main/java/com/google/protobuf/FieldSet.java \
|
||||
java/src/main/java/com/google/protobuf/GeneratedMessage.java \
|
||||
java/src/main/java/com/google/protobuf/GeneratedMessageLite.java \
|
||||
java/src/main/java/com/google/protobuf/Internal.java \
|
||||
java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
|
||||
java/src/main/java/com/google/protobuf/Message.java \
|
||||
java/src/main/java/com/google/protobuf/MessageLite.java \
|
||||
java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java \
|
||||
java/src/main/java/com/google/protobuf/RpcCallback.java \
|
||||
java/src/main/java/com/google/protobuf/RpcChannel.java \
|
||||
@ -91,6 +96,7 @@ EXTRA_DIST = \
|
||||
java/src/test/java/com/google/protobuf/DescriptorsTest.java \
|
||||
java/src/test/java/com/google/protobuf/DynamicMessageTest.java \
|
||||
java/src/test/java/com/google/protobuf/GeneratedMessageTest.java \
|
||||
java/src/test/java/com/google/protobuf/LiteTest.java \
|
||||
java/src/test/java/com/google/protobuf/MessageTest.java \
|
||||
java/src/test/java/com/google/protobuf/ServiceTest.java \
|
||||
java/src/test/java/com/google/protobuf/TestUtil.java \
|
||||
@ -110,6 +116,7 @@ EXTRA_DIST = \
|
||||
python/google/protobuf/internal/input_stream.py \
|
||||
python/google/protobuf/internal/input_stream_test.py \
|
||||
python/google/protobuf/internal/message_listener.py \
|
||||
python/google/protobuf/internal/message_test.py \
|
||||
python/google/protobuf/internal/more_extensions.proto \
|
||||
python/google/protobuf/internal/more_messages.proto \
|
||||
python/google/protobuf/internal/output_stream.py \
|
||||
|
@ -5,6 +5,10 @@
|
||||
# itself, they cannot be generated automatically by a make rule. "make check"
|
||||
# will fail if these files do not match what the protocol compiler would
|
||||
# generate.
|
||||
#
|
||||
# HINT: Flags passed to generate_descriptor_proto.sh will be passed directly
|
||||
# to make when building protoc. This is particularly useful for passing
|
||||
# -j4 to run 4 jobs simultaneously.
|
||||
|
||||
if test ! -e src/google/protobuf/stubs/common.h; then
|
||||
cat >&2 << __EOF__
|
||||
@ -23,5 +27,5 @@ __EOF__
|
||||
fi
|
||||
|
||||
cd src
|
||||
make protoc && ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:. google/protobuf/descriptor.proto
|
||||
make $@ protoc && ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:. google/protobuf/descriptor.proto
|
||||
cd ..
|
||||
|
@ -124,6 +124,9 @@
|
||||
value="../src/google/protobuf/unittest_optimize_for.proto" />
|
||||
<arg
|
||||
value="../src/google/protobuf/unittest_custom_options.proto" />
|
||||
<arg value="../src/google/protobuf/unittest_lite.proto" />
|
||||
<arg value="../src/google/protobuf/unittest_import_lite.proto" />
|
||||
<arg value="../src/google/protobuf/unittest_lite_imports_nonlite.proto" />
|
||||
</exec>
|
||||
</tasks>
|
||||
<testSourceRoot>target/generated-test-sources</testSourceRoot>
|
||||
|
@ -30,12 +30,12 @@
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import com.google.protobuf.Descriptors.Descriptor;
|
||||
import com.google.protobuf.Descriptors.FieldDescriptor;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -45,11 +45,12 @@ import java.util.Map;
|
||||
*
|
||||
* @author kenton@google.com Kenton Varda
|
||||
*/
|
||||
public abstract class AbstractMessage implements Message {
|
||||
public abstract class AbstractMessage extends AbstractMessageLite
|
||||
implements Message {
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean isInitialized() {
|
||||
// Check that all required fields are present.
|
||||
for (FieldDescriptor field : getDescriptorForType().getFields()) {
|
||||
for (final FieldDescriptor field : getDescriptorForType().getFields()) {
|
||||
if (field.isRequired()) {
|
||||
if (!hasField(field)) {
|
||||
return false;
|
||||
@ -58,11 +59,12 @@ public abstract class AbstractMessage implements Message {
|
||||
}
|
||||
|
||||
// Check that embedded messages are initialized.
|
||||
for (Map.Entry<FieldDescriptor, Object> entry : getAllFields().entrySet()) {
|
||||
FieldDescriptor field = entry.getKey();
|
||||
for (final Map.Entry<FieldDescriptor, Object> entry :
|
||||
getAllFields().entrySet()) {
|
||||
final FieldDescriptor field = entry.getKey();
|
||||
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
|
||||
if (field.isRepeated()) {
|
||||
for (Message element : (List<Message>) entry.getValue()) {
|
||||
for (final Message element : (List<Message>) entry.getValue()) {
|
||||
if (!element.isInitialized()) {
|
||||
return false;
|
||||
}
|
||||
@ -83,117 +85,59 @@ public abstract class AbstractMessage implements Message {
|
||||
return TextFormat.printToString(this);
|
||||
}
|
||||
|
||||
public void writeTo(CodedOutputStream output) throws IOException {
|
||||
for (Map.Entry<FieldDescriptor, Object> entry : getAllFields().entrySet()) {
|
||||
FieldDescriptor field = entry.getKey();
|
||||
if (field.isRepeated()) {
|
||||
List valueList = (List) entry.getValue();
|
||||
if (field.getOptions().getPacked()) {
|
||||
public void writeTo(final CodedOutputStream output) throws IOException {
|
||||
final boolean isMessageSet =
|
||||
getDescriptorForType().getOptions().getMessageSetWireFormat();
|
||||
|
||||
output.writeTag(field.getNumber(),
|
||||
WireFormat.WIRETYPE_LENGTH_DELIMITED);
|
||||
int dataSize = 0;
|
||||
for (Object element : valueList) {
|
||||
dataSize += CodedOutputStream.computeFieldSizeNoTag(
|
||||
field.getType(), element);
|
||||
}
|
||||
output.writeRawVarint32(dataSize);
|
||||
|
||||
for (Object element : valueList) {
|
||||
output.writeFieldNoTag(field.getType(), element);
|
||||
}
|
||||
} else {
|
||||
for (Object element : valueList) {
|
||||
output.writeField(field.getType(), field.getNumber(), element);
|
||||
}
|
||||
}
|
||||
for (final Map.Entry<FieldDescriptor, Object> entry :
|
||||
getAllFields().entrySet()) {
|
||||
final FieldDescriptor field = entry.getKey();
|
||||
final Object value = entry.getValue();
|
||||
if (isMessageSet && field.isExtension() &&
|
||||
field.getType() == FieldDescriptor.Type.MESSAGE &&
|
||||
!field.isRepeated()) {
|
||||
output.writeMessageSetExtension(field.getNumber(), (Message) value);
|
||||
} else {
|
||||
output.writeField(field.getType(), field.getNumber(), entry.getValue());
|
||||
FieldSet.writeField(field, value, output);
|
||||
}
|
||||
}
|
||||
|
||||
UnknownFieldSet unknownFields = getUnknownFields();
|
||||
if (getDescriptorForType().getOptions().getMessageSetWireFormat()) {
|
||||
final UnknownFieldSet unknownFields = getUnknownFields();
|
||||
if (isMessageSet) {
|
||||
unknownFields.writeAsMessageSetTo(output);
|
||||
} else {
|
||||
unknownFields.writeTo(output);
|
||||
}
|
||||
}
|
||||
|
||||
public ByteString toByteString() {
|
||||
try {
|
||||
ByteString.CodedBuilder out =
|
||||
ByteString.newCodedBuilder(getSerializedSize());
|
||||
writeTo(out.getCodedOutput());
|
||||
return out.build();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Serializing to a ByteString threw an IOException (should " +
|
||||
"never happen).", e);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
try {
|
||||
byte[] result = new byte[getSerializedSize()];
|
||||
CodedOutputStream output = CodedOutputStream.newInstance(result);
|
||||
writeTo(output);
|
||||
output.checkNoSpaceLeft();
|
||||
return result;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Serializing to a byte array threw an IOException " +
|
||||
"(should never happen).", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeTo(OutputStream output) throws IOException {
|
||||
CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
|
||||
writeTo(codedOutput);
|
||||
codedOutput.flush();
|
||||
}
|
||||
|
||||
public void writeDelimitedTo(OutputStream output) throws IOException {
|
||||
CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
|
||||
codedOutput.writeRawVarint32(getSerializedSize());
|
||||
writeTo(codedOutput);
|
||||
codedOutput.flush();
|
||||
}
|
||||
|
||||
private int memoizedSize = -1;
|
||||
|
||||
public int getSerializedSize() {
|
||||
int size = memoizedSize;
|
||||
if (size != -1) return size;
|
||||
if (size != -1) {
|
||||
return size;
|
||||
}
|
||||
|
||||
size = 0;
|
||||
for (Map.Entry<FieldDescriptor, Object> entry : getAllFields().entrySet()) {
|
||||
FieldDescriptor field = entry.getKey();
|
||||
if (field.isRepeated()) {
|
||||
List valueList = (List) entry.getValue();
|
||||
if (field.getOptions().getPacked()) {
|
||||
int dataSize = 0;
|
||||
for (Object element : valueList) {
|
||||
dataSize += CodedOutputStream.computeFieldSizeNoTag(
|
||||
field.getType(), element);
|
||||
}
|
||||
size += dataSize;
|
||||
size += CodedOutputStream.computeTagSize(field.getNumber());
|
||||
size += CodedOutputStream.computeRawVarint32Size(dataSize);
|
||||
} else {
|
||||
for (Object element : valueList) {
|
||||
size += CodedOutputStream.computeFieldSize(
|
||||
field.getType(), field.getNumber(), element);
|
||||
}
|
||||
}
|
||||
final boolean isMessageSet =
|
||||
getDescriptorForType().getOptions().getMessageSetWireFormat();
|
||||
|
||||
for (final Map.Entry<FieldDescriptor, Object> entry :
|
||||
getAllFields().entrySet()) {
|
||||
final FieldDescriptor field = entry.getKey();
|
||||
final Object value = entry.getValue();
|
||||
if (isMessageSet && field.isExtension() &&
|
||||
field.getType() == FieldDescriptor.Type.MESSAGE &&
|
||||
!field.isRepeated()) {
|
||||
size += CodedOutputStream.computeMessageSetExtensionSize(
|
||||
field.getNumber(), (Message) value);
|
||||
} else {
|
||||
size += CodedOutputStream.computeFieldSize(
|
||||
field.getType(), field.getNumber(), entry.getValue());
|
||||
size += FieldSet.computeFieldSize(field, value);
|
||||
}
|
||||
}
|
||||
|
||||
UnknownFieldSet unknownFields = getUnknownFields();
|
||||
if (getDescriptorForType().getOptions().getMessageSetWireFormat()) {
|
||||
final UnknownFieldSet unknownFields = getUnknownFields();
|
||||
if (isMessageSet) {
|
||||
size += unknownFields.getSerializedSizeAsMessageSet();
|
||||
} else {
|
||||
size += unknownFields.getSerializedSize();
|
||||
@ -204,14 +148,14 @@ public abstract class AbstractMessage implements Message {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
public boolean equals(final Object other) {
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof Message)) {
|
||||
return false;
|
||||
}
|
||||
Message otherMessage = (Message) other;
|
||||
final Message otherMessage = (Message) other;
|
||||
if (getDescriptorForType() != otherMessage.getDescriptorForType()) {
|
||||
return false;
|
||||
}
|
||||
@ -237,20 +181,21 @@ public abstract class AbstractMessage implements Message {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static abstract class Builder<BuilderType extends Builder>
|
||||
extends AbstractMessageLite.Builder<BuilderType>
|
||||
implements Message.Builder {
|
||||
// The compiler produces an error if this is not declared explicitly.
|
||||
@Override
|
||||
public abstract BuilderType clone();
|
||||
|
||||
public BuilderType clear() {
|
||||
for (Map.Entry<FieldDescriptor, Object> entry :
|
||||
for (final Map.Entry<FieldDescriptor, Object> entry :
|
||||
getAllFields().entrySet()) {
|
||||
clearField(entry.getKey());
|
||||
}
|
||||
return (BuilderType) this;
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(Message other) {
|
||||
public BuilderType mergeFrom(final Message other) {
|
||||
if (other.getDescriptorForType() != getDescriptorForType()) {
|
||||
throw new IllegalArgumentException(
|
||||
"mergeFrom(Message) can only merge messages of the same type.");
|
||||
@ -265,15 +210,15 @@ public abstract class AbstractMessage implements Message {
|
||||
// TODO(kenton): Provide a function somewhere called makeDeepCopy()
|
||||
// which allows people to make secure deep copies of messages.
|
||||
|
||||
for (Map.Entry<FieldDescriptor, Object> entry :
|
||||
for (final Map.Entry<FieldDescriptor, Object> entry :
|
||||
other.getAllFields().entrySet()) {
|
||||
FieldDescriptor field = entry.getKey();
|
||||
final FieldDescriptor field = entry.getKey();
|
||||
if (field.isRepeated()) {
|
||||
for (Object element : (List)entry.getValue()) {
|
||||
for (final Object element : (List)entry.getValue()) {
|
||||
addRepeatedField(field, element);
|
||||
}
|
||||
} else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
|
||||
Message existingValue = (Message)getField(field);
|
||||
final Message existingValue = (Message)getField(field);
|
||||
if (existingValue == existingValue.getDefaultInstanceForType()) {
|
||||
setField(field, entry.getValue());
|
||||
} else {
|
||||
@ -288,24 +233,288 @@ public abstract class AbstractMessage implements Message {
|
||||
}
|
||||
}
|
||||
|
||||
mergeUnknownFields(other.getUnknownFields());
|
||||
|
||||
return (BuilderType) this;
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(CodedInputStream input) throws IOException {
|
||||
@Override
|
||||
public BuilderType mergeFrom(final CodedInputStream input)
|
||||
throws IOException {
|
||||
return mergeFrom(input, ExtensionRegistry.getEmptyRegistry());
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(CodedInputStream input,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
throws IOException {
|
||||
UnknownFieldSet.Builder unknownFields =
|
||||
@Override
|
||||
public BuilderType mergeFrom(
|
||||
final CodedInputStream input,
|
||||
final ExtensionRegistryLite extensionRegistry)
|
||||
throws IOException {
|
||||
final UnknownFieldSet.Builder unknownFields =
|
||||
UnknownFieldSet.newBuilder(getUnknownFields());
|
||||
FieldSet.mergeFrom(input, unknownFields, extensionRegistry, this);
|
||||
while (true) {
|
||||
final int tag = input.readTag();
|
||||
if (tag == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!mergeFieldFrom(input, unknownFields, extensionRegistry,
|
||||
this, tag)) {
|
||||
// end group tag
|
||||
break;
|
||||
}
|
||||
}
|
||||
setUnknownFields(unknownFields.build());
|
||||
return (BuilderType) this;
|
||||
}
|
||||
|
||||
public BuilderType mergeUnknownFields(UnknownFieldSet unknownFields) {
|
||||
/**
|
||||
* Like {@link #mergeFrom(CodedInputStream, UnknownFieldSet.Builder,
|
||||
* ExtensionRegistryLite, Message.Builder)}, but parses a single field.
|
||||
* Package-private because it is used by GeneratedMessage.ExtendableMessage.
|
||||
* @param tag The tag, which should have already been read.
|
||||
* @return {@code true} unless the tag is an end-group tag.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static boolean mergeFieldFrom(
|
||||
final CodedInputStream input,
|
||||
final UnknownFieldSet.Builder unknownFields,
|
||||
final ExtensionRegistryLite extensionRegistry,
|
||||
final Message.Builder builder,
|
||||
final int tag) throws IOException {
|
||||
final Descriptor type = builder.getDescriptorForType();
|
||||
|
||||
if (type.getOptions().getMessageSetWireFormat() &&
|
||||
tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
|
||||
mergeMessageSetExtensionFromCodedStream(
|
||||
input, unknownFields, extensionRegistry, builder);
|
||||
return true;
|
||||
}
|
||||
|
||||
final int wireType = WireFormat.getTagWireType(tag);
|
||||
final int fieldNumber = WireFormat.getTagFieldNumber(tag);
|
||||
|
||||
final FieldDescriptor field;
|
||||
Message defaultInstance = null;
|
||||
|
||||
if (type.isExtensionNumber(fieldNumber)) {
|
||||
// extensionRegistry may be either ExtensionRegistry or
|
||||
// ExtensionRegistryLite. Since the type we are parsing is a full
|
||||
// message, only a full ExtensionRegistry could possibly contain
|
||||
// extensions of it. Otherwise we will treat the registry as if it
|
||||
// were empty.
|
||||
if (extensionRegistry instanceof ExtensionRegistry) {
|
||||
final ExtensionRegistry.ExtensionInfo extension =
|
||||
((ExtensionRegistry) extensionRegistry)
|
||||
.findExtensionByNumber(type, fieldNumber);
|
||||
if (extension == null) {
|
||||
field = null;
|
||||
} else {
|
||||
field = extension.descriptor;
|
||||
defaultInstance = extension.defaultInstance;
|
||||
}
|
||||
} else {
|
||||
field = null;
|
||||
}
|
||||
} else {
|
||||
field = type.findFieldByNumber(fieldNumber);
|
||||
}
|
||||
|
||||
if (field == null || wireType !=
|
||||
FieldSet.getWireFormatForFieldType(
|
||||
field.getLiteType(),
|
||||
field.getOptions().getPacked())) {
|
||||
// Unknown field or wrong wire type. Skip.
|
||||
return unknownFields.mergeFieldFrom(tag, input);
|
||||
}
|
||||
|
||||
if (field.getOptions().getPacked()) {
|
||||
final int length = input.readRawVarint32();
|
||||
final int limit = input.pushLimit(length);
|
||||
if (field.getLiteType() == WireFormat.FieldType.ENUM) {
|
||||
while (input.getBytesUntilLimit() > 0) {
|
||||
final int rawValue = input.readEnum();
|
||||
final Object value = field.getEnumType().findValueByNumber(rawValue);
|
||||
if (value == null) {
|
||||
// If the number isn't recognized as a valid value for this
|
||||
// enum, drop it (don't even add it to unknownFields).
|
||||
return true;
|
||||
}
|
||||
builder.addRepeatedField(field, value);
|
||||
}
|
||||
} else {
|
||||
while (input.getBytesUntilLimit() > 0) {
|
||||
final Object value =
|
||||
FieldSet.readPrimitiveField(input, field.getLiteType());
|
||||
builder.addRepeatedField(field, value);
|
||||
}
|
||||
}
|
||||
input.popLimit(limit);
|
||||
} else {
|
||||
final Object value;
|
||||
switch (field.getType()) {
|
||||
case GROUP: {
|
||||
final Message.Builder subBuilder;
|
||||
if (defaultInstance != null) {
|
||||
subBuilder = defaultInstance.newBuilderForType();
|
||||
} else {
|
||||
subBuilder = builder.newBuilderForField(field);
|
||||
}
|
||||
if (!field.isRepeated()) {
|
||||
subBuilder.mergeFrom((Message) builder.getField(field));
|
||||
}
|
||||
input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
|
||||
value = subBuilder.build();
|
||||
break;
|
||||
}
|
||||
case MESSAGE: {
|
||||
final Message.Builder subBuilder;
|
||||
if (defaultInstance != null) {
|
||||
subBuilder = defaultInstance.newBuilderForType();
|
||||
} else {
|
||||
subBuilder = builder.newBuilderForField(field);
|
||||
}
|
||||
if (!field.isRepeated()) {
|
||||
subBuilder.mergeFrom((Message) builder.getField(field));
|
||||
}
|
||||
input.readMessage(subBuilder, extensionRegistry);
|
||||
value = subBuilder.build();
|
||||
break;
|
||||
}
|
||||
case ENUM:
|
||||
final int rawValue = input.readEnum();
|
||||
value = field.getEnumType().findValueByNumber(rawValue);
|
||||
// If the number isn't recognized as a valid value for this enum,
|
||||
// drop it.
|
||||
if (value == null) {
|
||||
unknownFields.mergeVarintField(fieldNumber, rawValue);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
value = FieldSet.readPrimitiveField(input, field.getLiteType());
|
||||
break;
|
||||
}
|
||||
|
||||
if (field.isRepeated()) {
|
||||
builder.addRepeatedField(field, value);
|
||||
} else {
|
||||
builder.setField(field, value);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Called by {@code #mergeFieldFrom()} to parse a MessageSet extension. */
|
||||
private static void mergeMessageSetExtensionFromCodedStream(
|
||||
final CodedInputStream input,
|
||||
final UnknownFieldSet.Builder unknownFields,
|
||||
final ExtensionRegistryLite extensionRegistry,
|
||||
final Message.Builder builder) throws IOException {
|
||||
final Descriptor type = builder.getDescriptorForType();
|
||||
|
||||
// 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"
|
||||
Message.Builder subBuilder = null;
|
||||
FieldDescriptor field = null;
|
||||
|
||||
while (true) {
|
||||
final int tag = input.readTag();
|
||||
if (tag == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
|
||||
typeId = input.readUInt32();
|
||||
// Zero is not a valid type ID.
|
||||
if (typeId != 0) {
|
||||
final ExtensionRegistry.ExtensionInfo extension;
|
||||
|
||||
// extensionRegistry may be either ExtensionRegistry or
|
||||
// ExtensionRegistryLite. Since the type we are parsing is a full
|
||||
// message, only a full ExtensionRegistry could possibly contain
|
||||
// extensions of it. Otherwise we will treat the registry as if it
|
||||
// were empty.
|
||||
if (extensionRegistry instanceof ExtensionRegistry) {
|
||||
extension = ((ExtensionRegistry) extensionRegistry)
|
||||
.findExtensionByNumber(type, typeId);
|
||||
} else {
|
||||
extension = null;
|
||||
}
|
||||
|
||||
if (extension != null) {
|
||||
field = extension.descriptor;
|
||||
subBuilder = extension.defaultInstance.newBuilderForType();
|
||||
final Message originalMessage = (Message)builder.getField(field);
|
||||
if (originalMessage != null) {
|
||||
subBuilder.mergeFrom(originalMessage);
|
||||
}
|
||||
if (rawBytes != null) {
|
||||
// We already encountered the message. Parse it now.
|
||||
subBuilder.mergeFrom(
|
||||
CodedInputStream.newInstance(rawBytes.newInput()));
|
||||
rawBytes = null;
|
||||
}
|
||||
} else {
|
||||
// Unknown extension number. If we already saw data, put it
|
||||
// in rawBytes.
|
||||
if (rawBytes != null) {
|
||||
unknownFields.mergeField(typeId,
|
||||
UnknownFieldSet.Field.newBuilder()
|
||||
.addLengthDelimited(rawBytes)
|
||||
.build());
|
||||
rawBytes = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
|
||||
if (typeId == 0) {
|
||||
// We haven't seen a type ID yet, so we have to store the raw bytes
|
||||
// for now.
|
||||
rawBytes = input.readBytes();
|
||||
} else if (subBuilder == null) {
|
||||
// We don't know how to parse this. Ignore it.
|
||||
unknownFields.mergeField(typeId,
|
||||
UnknownFieldSet.Field.newBuilder()
|
||||
.addLengthDelimited(input.readBytes())
|
||||
.build());
|
||||
} else {
|
||||
// We already know the type, so we can parse directly from the input
|
||||
// with no copying. Hooray!
|
||||
input.readMessage(subBuilder, extensionRegistry);
|
||||
}
|
||||
} else {
|
||||
// Unknown tag. Skip it.
|
||||
if (!input.skipField(tag)) {
|
||||
break; // end of group
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
|
||||
|
||||
if (subBuilder != null) {
|
||||
builder.setField(field, subBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
|
||||
setUnknownFields(
|
||||
UnknownFieldSet.newBuilder(getUnknownFields())
|
||||
.mergeFrom(unknownFields)
|
||||
@ -313,145 +522,169 @@ public abstract class AbstractMessage implements Message {
|
||||
return (BuilderType) this;
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(ByteString data)
|
||||
throws InvalidProtocolBufferException {
|
||||
try {
|
||||
CodedInputStream input = data.newCodedInput();
|
||||
mergeFrom(input);
|
||||
input.checkLastTagWas(0);
|
||||
return (BuilderType) this;
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Reading from a ByteString threw an IOException (should " +
|
||||
"never happen).", e);
|
||||
/**
|
||||
* Construct an UninitializedMessageException reporting missing fields in
|
||||
* the given message.
|
||||
*/
|
||||
protected static UninitializedMessageException
|
||||
newUninitializedMessageException(Message message) {
|
||||
return new UninitializedMessageException(findMissingFields(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates {@code this.missingFields} with the full "path" of each
|
||||
* missing required field in the given message.
|
||||
*/
|
||||
private static List<String> findMissingFields(final Message message) {
|
||||
final List<String> results = new ArrayList<String>();
|
||||
findMissingFields(message, "", results);
|
||||
return results;
|
||||
}
|
||||
|
||||
/** Recursive helper implementing {@link #findMissingFields(Message)}. */
|
||||
private static void findMissingFields(final Message message,
|
||||
final String prefix,
|
||||
final List<String> results) {
|
||||
for (final FieldDescriptor field :
|
||||
message.getDescriptorForType().getFields()) {
|
||||
if (field.isRequired() && !message.hasField(field)) {
|
||||
results.add(prefix + field.getName());
|
||||
}
|
||||
}
|
||||
|
||||
for (final Map.Entry<FieldDescriptor, Object> entry :
|
||||
message.getAllFields().entrySet()) {
|
||||
final FieldDescriptor field = entry.getKey();
|
||||
final Object value = entry.getValue();
|
||||
|
||||
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
|
||||
if (field.isRepeated()) {
|
||||
int i = 0;
|
||||
for (final Object element : (List) value) {
|
||||
findMissingFields((Message) element,
|
||||
subMessagePrefix(prefix, field, i++),
|
||||
results);
|
||||
}
|
||||
} else {
|
||||
if (message.hasField(field)) {
|
||||
findMissingFields((Message) value,
|
||||
subMessagePrefix(prefix, field, -1),
|
||||
results);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(ByteString data,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
throws InvalidProtocolBufferException {
|
||||
try {
|
||||
CodedInputStream input = data.newCodedInput();
|
||||
mergeFrom(input, extensionRegistry);
|
||||
input.checkLastTagWas(0);
|
||||
return (BuilderType) this;
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Reading from a ByteString threw an IOException (should " +
|
||||
"never happen).", e);
|
||||
private static String subMessagePrefix(final String prefix,
|
||||
final FieldDescriptor field,
|
||||
final int index) {
|
||||
final StringBuilder result = new StringBuilder(prefix);
|
||||
if (field.isExtension()) {
|
||||
result.append('(')
|
||||
.append(field.getFullName())
|
||||
.append(')');
|
||||
} else {
|
||||
result.append(field.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(byte[] data)
|
||||
throws InvalidProtocolBufferException {
|
||||
return mergeFrom(data, 0, data.length);
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(byte[] data, int off, int len)
|
||||
throws InvalidProtocolBufferException {
|
||||
try {
|
||||
CodedInputStream input = CodedInputStream.newInstance(data, off, len);
|
||||
mergeFrom(input);
|
||||
input.checkLastTagWas(0);
|
||||
return (BuilderType) this;
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Reading from a byte array threw an IOException (should " +
|
||||
"never happen).", e);
|
||||
if (index != -1) {
|
||||
result.append('[')
|
||||
.append(index)
|
||||
.append(']');
|
||||
}
|
||||
result.append('.');
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
// ===============================================================
|
||||
// The following definitions seem to be required in order to make javac
|
||||
// not produce weird errors like:
|
||||
//
|
||||
// java/com/google/protobuf/DynamicMessage.java:203: types
|
||||
// com.google.protobuf.AbstractMessage.Builder<
|
||||
// com.google.protobuf.DynamicMessage.Builder> and
|
||||
// com.google.protobuf.AbstractMessage.Builder<
|
||||
// com.google.protobuf.DynamicMessage.Builder> are incompatible; both
|
||||
// define mergeFrom(com.google.protobuf.ByteString), but with unrelated
|
||||
// return types.
|
||||
//
|
||||
// Strangely, these lines are only needed if javac is invoked separately
|
||||
// on AbstractMessage.java and AbstractMessageLite.java. If javac is
|
||||
// invoked on both simultaneously, it works. (Or maybe the important
|
||||
// point is whether or not DynamicMessage.java is compiled together with
|
||||
// AbstractMessageLite.java -- not sure.) I suspect this is a compiler
|
||||
// bug.
|
||||
|
||||
@Override
|
||||
public BuilderType mergeFrom(final ByteString data)
|
||||
throws InvalidProtocolBufferException {
|
||||
return super.mergeFrom(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuilderType mergeFrom(
|
||||
byte[] data,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
final ByteString data,
|
||||
final ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException {
|
||||
return mergeFrom(data, 0, data.length, extensionRegistry);
|
||||
return super.mergeFrom(data, extensionRegistry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuilderType mergeFrom(final byte[] data)
|
||||
throws InvalidProtocolBufferException {
|
||||
return super.mergeFrom(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuilderType mergeFrom(
|
||||
byte[] data, int off, int len,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
final byte[] data, final int off, final int len)
|
||||
throws InvalidProtocolBufferException {
|
||||
try {
|
||||
CodedInputStream input = CodedInputStream.newInstance(data, off, len);
|
||||
mergeFrom(input, extensionRegistry);
|
||||
input.checkLastTagWas(0);
|
||||
return (BuilderType) this;
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Reading from a byte array threw an IOException (should " +
|
||||
"never happen).", e);
|
||||
}
|
||||
return super.mergeFrom(data, off, len);
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(InputStream input) throws IOException {
|
||||
CodedInputStream codedInput = CodedInputStream.newInstance(input);
|
||||
mergeFrom(codedInput);
|
||||
codedInput.checkLastTagWas(0);
|
||||
return (BuilderType) this;
|
||||
@Override
|
||||
public BuilderType mergeFrom(
|
||||
final byte[] data,
|
||||
final ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException {
|
||||
return super.mergeFrom(data, extensionRegistry);
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(InputStream input,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
throws IOException {
|
||||
CodedInputStream codedInput = CodedInputStream.newInstance(input);
|
||||
mergeFrom(codedInput, extensionRegistry);
|
||||
codedInput.checkLastTagWas(0);
|
||||
return (BuilderType) this;
|
||||
@Override
|
||||
public BuilderType mergeFrom(
|
||||
final byte[] data, final int off, final int len,
|
||||
final ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException {
|
||||
return super.mergeFrom(data, off, len, extensionRegistry);
|
||||
}
|
||||
|
||||
public BuilderType mergeDelimitedFrom(InputStream input,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
throws IOException {
|
||||
final int size = CodedInputStream.readRawVarint32(input);
|
||||
|
||||
// A stream which will not read more than |size| bytes.
|
||||
InputStream limitedInput = new FilterInputStream(input) {
|
||||
int limit = size;
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
return Math.min(super.available(), limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (limit <= 0) return -1;
|
||||
int result = super.read();
|
||||
if (result >= 0) --limit;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
if (limit <= 0) return -1;
|
||||
len = Math.min(len, limit);
|
||||
int result = super.read(b, off, len);
|
||||
if (result >= 0) limit -= result;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
long result = super.skip(Math.min(n, limit));
|
||||
if (result >= 0) limit -= result;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
return mergeFrom(limitedInput, extensionRegistry);
|
||||
}
|
||||
|
||||
public BuilderType mergeDelimitedFrom(InputStream input)
|
||||
@Override
|
||||
public BuilderType mergeFrom(final InputStream input)
|
||||
throws IOException {
|
||||
return mergeDelimitedFrom(input, ExtensionRegistry.getEmptyRegistry());
|
||||
return super.mergeFrom(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuilderType mergeFrom(
|
||||
final InputStream input,
|
||||
final ExtensionRegistryLite extensionRegistry)
|
||||
throws IOException {
|
||||
return super.mergeFrom(input, extensionRegistry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuilderType mergeDelimitedFrom(final InputStream input)
|
||||
throws IOException {
|
||||
return super.mergeDelimitedFrom(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuilderType mergeDelimitedFrom(
|
||||
final InputStream input,
|
||||
final ExtensionRegistryLite extensionRegistry)
|
||||
throws IOException {
|
||||
return super.mergeDelimitedFrom(input, extensionRegistry);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
321
java/src/main/java/com/google/protobuf/AbstractMessageLite.java
Normal file
321
java/src/main/java/com/google/protobuf/AbstractMessageLite.java
Normal file
@ -0,0 +1,321 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A partial implementation of the {@link MessageLite} interface which
|
||||
* implements as many methods of that interface as possible in terms of other
|
||||
* methods.
|
||||
*
|
||||
* @author kenton@google.com Kenton Varda
|
||||
*/
|
||||
public abstract class AbstractMessageLite implements MessageLite {
|
||||
public ByteString toByteString() {
|
||||
try {
|
||||
final ByteString.CodedBuilder out =
|
||||
ByteString.newCodedBuilder(getSerializedSize());
|
||||
writeTo(out.getCodedOutput());
|
||||
return out.build();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Serializing to a ByteString threw an IOException (should " +
|
||||
"never happen).", e);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
try {
|
||||
final byte[] result = new byte[getSerializedSize()];
|
||||
final CodedOutputStream output = CodedOutputStream.newInstance(result);
|
||||
writeTo(output);
|
||||
output.checkNoSpaceLeft();
|
||||
return result;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Serializing to a byte array threw an IOException " +
|
||||
"(should never happen).", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeTo(final OutputStream output) throws IOException {
|
||||
final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
|
||||
writeTo(codedOutput);
|
||||
codedOutput.flush();
|
||||
}
|
||||
|
||||
public void writeDelimitedTo(final OutputStream output) throws IOException {
|
||||
final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
|
||||
codedOutput.writeRawVarint32(getSerializedSize());
|
||||
writeTo(codedOutput);
|
||||
codedOutput.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* A partial implementation of the {@link Message.Builder} interface which
|
||||
* implements as many methods of that interface as possible in terms of
|
||||
* other methods.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static abstract class Builder<BuilderType extends Builder>
|
||||
implements MessageLite.Builder {
|
||||
// The compiler produces an error if this is not declared explicitly.
|
||||
@Override
|
||||
public abstract BuilderType clone();
|
||||
|
||||
public BuilderType mergeFrom(final CodedInputStream input)
|
||||
throws IOException {
|
||||
// TODO(kenton): Don't use null here. Currently we have to because
|
||||
// using ExtensionRegistry.getEmptyRegistry() would imply a dependency
|
||||
// on ExtensionRegistry. However, AbstractMessage overrides this with
|
||||
// a correct implementation, and lite messages don't yet support
|
||||
// extensions, so it ends up not mattering for now. It will matter
|
||||
// once lite messages support extensions.
|
||||
return mergeFrom(input, null);
|
||||
}
|
||||
|
||||
// Re-defined here for return type covariance.
|
||||
public abstract BuilderType mergeFrom(
|
||||
final CodedInputStream input,
|
||||
final ExtensionRegistryLite extensionRegistry)
|
||||
throws IOException;
|
||||
|
||||
public BuilderType mergeFrom(final ByteString data)
|
||||
throws InvalidProtocolBufferException {
|
||||
try {
|
||||
final CodedInputStream input = data.newCodedInput();
|
||||
mergeFrom(input);
|
||||
input.checkLastTagWas(0);
|
||||
return (BuilderType) this;
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Reading from a ByteString threw an IOException (should " +
|
||||
"never happen).", e);
|
||||
}
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(
|
||||
final ByteString data,
|
||||
final ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException {
|
||||
try {
|
||||
final CodedInputStream input = data.newCodedInput();
|
||||
mergeFrom(input, extensionRegistry);
|
||||
input.checkLastTagWas(0);
|
||||
return (BuilderType) this;
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Reading from a ByteString threw an IOException (should " +
|
||||
"never happen).", e);
|
||||
}
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(final byte[] data)
|
||||
throws InvalidProtocolBufferException {
|
||||
return mergeFrom(data, 0, data.length);
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(final byte[] data, final int off,
|
||||
final int len)
|
||||
throws InvalidProtocolBufferException {
|
||||
try {
|
||||
final CodedInputStream input =
|
||||
CodedInputStream.newInstance(data, off, len);
|
||||
mergeFrom(input);
|
||||
input.checkLastTagWas(0);
|
||||
return (BuilderType) this;
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Reading from a byte array threw an IOException (should " +
|
||||
"never happen).", e);
|
||||
}
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(
|
||||
final byte[] data,
|
||||
final ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException {
|
||||
return mergeFrom(data, 0, data.length, extensionRegistry);
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(
|
||||
final byte[] data, final int off, final int len,
|
||||
final ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException {
|
||||
try {
|
||||
final CodedInputStream input =
|
||||
CodedInputStream.newInstance(data, off, len);
|
||||
mergeFrom(input, extensionRegistry);
|
||||
input.checkLastTagWas(0);
|
||||
return (BuilderType) this;
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Reading from a byte array threw an IOException (should " +
|
||||
"never happen).", e);
|
||||
}
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(final InputStream input) throws IOException {
|
||||
final CodedInputStream codedInput = CodedInputStream.newInstance(input);
|
||||
mergeFrom(codedInput);
|
||||
codedInput.checkLastTagWas(0);
|
||||
return (BuilderType) this;
|
||||
}
|
||||
|
||||
public BuilderType mergeFrom(
|
||||
final InputStream input,
|
||||
final ExtensionRegistryLite extensionRegistry)
|
||||
throws IOException {
|
||||
final CodedInputStream codedInput = CodedInputStream.newInstance(input);
|
||||
mergeFrom(codedInput, extensionRegistry);
|
||||
codedInput.checkLastTagWas(0);
|
||||
return (BuilderType) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* An InputStream implementations which reads from some other InputStream
|
||||
* but is limited to a particular number of bytes. Used by
|
||||
* mergeDelimitedFrom(). This is intentionally package-private so that
|
||||
* UnknownFieldSet can share it.
|
||||
*/
|
||||
static final class LimitedInputStream extends FilterInputStream {
|
||||
private int limit;
|
||||
|
||||
LimitedInputStream(InputStream in, int limit) {
|
||||
super(in);
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
return Math.min(super.available(), limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (limit <= 0) {
|
||||
return -1;
|
||||
}
|
||||
final int result = super.read();
|
||||
if (result >= 0) {
|
||||
--limit;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(final byte[] b, final int off, int len)
|
||||
throws IOException {
|
||||
if (limit <= 0) {
|
||||
return -1;
|
||||
}
|
||||
len = Math.min(len, limit);
|
||||
final int result = super.read(b, off, len);
|
||||
if (result >= 0) {
|
||||
limit -= result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(final long n) throws IOException {
|
||||
final long result = super.skip(Math.min(n, limit));
|
||||
if (result >= 0) {
|
||||
limit -= result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public BuilderType mergeDelimitedFrom(
|
||||
final InputStream input,
|
||||
final ExtensionRegistryLite extensionRegistry)
|
||||
throws IOException {
|
||||
final int size = CodedInputStream.readRawVarint32(input);
|
||||
final InputStream limitedInput = new LimitedInputStream(input, size);
|
||||
return mergeFrom(limitedInput, extensionRegistry);
|
||||
}
|
||||
|
||||
public BuilderType mergeDelimitedFrom(final InputStream input)
|
||||
throws IOException {
|
||||
final int size = CodedInputStream.readRawVarint32(input);
|
||||
final InputStream limitedInput = new LimitedInputStream(input, size);
|
||||
return mergeFrom(limitedInput);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an UninitializedMessageException reporting missing fields in
|
||||
* the given message.
|
||||
*/
|
||||
protected static UninitializedMessageException
|
||||
newUninitializedMessageException(MessageLite message) {
|
||||
return new UninitializedMessageException(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the {@code values} to the {@code list}. This is a helper method
|
||||
* used by generated code. Users should ignore it.
|
||||
*
|
||||
* @throws NullPointerException if any of the elements of {@code values} is
|
||||
* null.
|
||||
*/
|
||||
protected static <T> void addAll(final Iterable<T> values,
|
||||
final Collection<? super T> list) {
|
||||
for (final T value : values) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
}
|
||||
if (values instanceof Collection) {
|
||||
@SuppressWarnings("unsafe") final
|
||||
Collection<T> collection = (Collection<T>) values;
|
||||
list.addAll(collection);
|
||||
} else {
|
||||
for (final T value : values) {
|
||||
list.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -46,7 +46,7 @@ import java.nio.ByteBuffer;
|
||||
public final class ByteString {
|
||||
private final byte[] bytes;
|
||||
|
||||
private ByteString(byte[] bytes) {
|
||||
private ByteString(final byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ public final class ByteString {
|
||||
*
|
||||
* @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
|
||||
*/
|
||||
public byte byteAt(int index) {
|
||||
public byte byteAt(final int index) {
|
||||
return bytes[index];
|
||||
}
|
||||
|
||||
@ -63,14 +63,14 @@ public final class ByteString {
|
||||
* Gets the number of bytes.
|
||||
*/
|
||||
public int size() {
|
||||
return this.bytes.length;
|
||||
return bytes.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the size is {@code 0}, {@code false} otherwise.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return this.bytes.length == 0;
|
||||
return bytes.length == 0;
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
@ -84,8 +84,9 @@ public final class ByteString {
|
||||
/**
|
||||
* Copies the given bytes into a {@code ByteString}.
|
||||
*/
|
||||
public static ByteString copyFrom(byte[] bytes, int offset, int size) {
|
||||
byte[] copy = new byte[size];
|
||||
public static ByteString copyFrom(final byte[] bytes, final int offset,
|
||||
final int size) {
|
||||
final byte[] copy = new byte[size];
|
||||
System.arraycopy(bytes, offset, copy, 0, size);
|
||||
return new ByteString(copy);
|
||||
}
|
||||
@ -93,7 +94,7 @@ public final class ByteString {
|
||||
/**
|
||||
* Copies the given bytes into a {@code ByteString}.
|
||||
*/
|
||||
public static ByteString copyFrom(byte[] bytes) {
|
||||
public static ByteString copyFrom(final byte[] bytes) {
|
||||
return copyFrom(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
@ -101,7 +102,7 @@ public final class ByteString {
|
||||
* Encodes {@code text} into a sequence of bytes using the named charset
|
||||
* and returns the result as a {@code ByteString}.
|
||||
*/
|
||||
public static ByteString copyFrom(String text, String charsetName)
|
||||
public static ByteString copyFrom(final String text, final String charsetName)
|
||||
throws UnsupportedEncodingException {
|
||||
return new ByteString(text.getBytes(charsetName));
|
||||
}
|
||||
@ -110,7 +111,7 @@ public final class ByteString {
|
||||
* Encodes {@code text} into a sequence of UTF-8 bytes and returns the
|
||||
* result as a {@code ByteString}.
|
||||
*/
|
||||
public static ByteString copyFromUtf8(String text) {
|
||||
public static ByteString copyFromUtf8(final String text) {
|
||||
try {
|
||||
return new ByteString(text.getBytes("UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
@ -127,7 +128,7 @@ public final class ByteString {
|
||||
* @param target buffer to copy into
|
||||
* @param offset in the target buffer
|
||||
*/
|
||||
public void copyTo(byte[] target, int offset) {
|
||||
public void copyTo(final byte[] target, final int offset) {
|
||||
System.arraycopy(bytes, 0, target, offset, bytes.length);
|
||||
}
|
||||
|
||||
@ -139,8 +140,9 @@ public final class ByteString {
|
||||
* @param targetOffset offset within the target buffer
|
||||
* @param size number of bytes to copy
|
||||
*/
|
||||
public void copyTo(byte[] target, int sourceOffset, int targetOffset,
|
||||
int size) {
|
||||
public void copyTo(final byte[] target, final int sourceOffset,
|
||||
final int targetOffset,
|
||||
final int size) {
|
||||
System.arraycopy(bytes, sourceOffset, target, targetOffset, size);
|
||||
}
|
||||
|
||||
@ -148,9 +150,9 @@ public final class ByteString {
|
||||
* Copies bytes to a {@code byte[]}.
|
||||
*/
|
||||
public byte[] toByteArray() {
|
||||
int size = this.bytes.length;
|
||||
byte[] copy = new byte[size];
|
||||
System.arraycopy(this.bytes, 0, copy, 0, size);
|
||||
final int size = bytes.length;
|
||||
final byte[] copy = new byte[size];
|
||||
System.arraycopy(bytes, 0, copy, 0, size);
|
||||
return copy;
|
||||
}
|
||||
|
||||
@ -159,7 +161,7 @@ public final class ByteString {
|
||||
* same backing byte array.
|
||||
*/
|
||||
public ByteBuffer asReadOnlyByteBuffer() {
|
||||
ByteBuffer byteBuffer = ByteBuffer.wrap(this.bytes);
|
||||
final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
|
||||
return byteBuffer.asReadOnlyBuffer();
|
||||
}
|
||||
|
||||
@ -167,9 +169,9 @@ public final class ByteString {
|
||||
* Constructs a new {@code String} by decoding the bytes using the
|
||||
* specified charset.
|
||||
*/
|
||||
public String toString(String charsetName)
|
||||
public String toString(final String charsetName)
|
||||
throws UnsupportedEncodingException {
|
||||
return new String(this.bytes, charsetName);
|
||||
return new String(bytes, charsetName);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -177,7 +179,7 @@ public final class ByteString {
|
||||
*/
|
||||
public String toStringUtf8() {
|
||||
try {
|
||||
return new String(this.bytes, "UTF-8");
|
||||
return new String(bytes, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("UTF-8 not supported?", e);
|
||||
}
|
||||
@ -187,7 +189,7 @@ public final class ByteString {
|
||||
// equals() and hashCode()
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
public boolean equals(final Object o) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
@ -196,16 +198,16 @@ public final class ByteString {
|
||||
return false;
|
||||
}
|
||||
|
||||
ByteString other = (ByteString) o;
|
||||
int size = this.bytes.length;
|
||||
final ByteString other = (ByteString) o;
|
||||
final int size = bytes.length;
|
||||
if (size != other.bytes.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] bytes = this.bytes;
|
||||
byte[] otherBytes = other.bytes;
|
||||
final byte[] thisBytes = bytes;
|
||||
final byte[] otherBytes = other.bytes;
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (bytes[i] != otherBytes[i]) {
|
||||
if (thisBytes[i] != otherBytes[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -213,25 +215,25 @@ public final class ByteString {
|
||||
return true;
|
||||
}
|
||||
|
||||
volatile int hash = 0;
|
||||
private volatile int hash = 0;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = this.hash;
|
||||
int h = hash;
|
||||
|
||||
if (h == 0) {
|
||||
byte[] bytes = this.bytes;
|
||||
int size = this.bytes.length;
|
||||
final byte[] thisBytes = bytes;
|
||||
final int size = bytes.length;
|
||||
|
||||
h = size;
|
||||
for (int i = 0; i < size; i++) {
|
||||
h = h * 31 + bytes[i];
|
||||
h = h * 31 + thisBytes[i];
|
||||
}
|
||||
if (h == 0) {
|
||||
h = 1;
|
||||
}
|
||||
|
||||
this.hash = h;
|
||||
hash = h;
|
||||
}
|
||||
|
||||
return h;
|
||||
@ -264,7 +266,7 @@ public final class ByteString {
|
||||
/**
|
||||
* Creates a new {@link Output} with the given initial capacity.
|
||||
*/
|
||||
public static Output newOutput(int initialCapacity) {
|
||||
public static Output newOutput(final int initialCapacity) {
|
||||
return new Output(new ByteArrayOutputStream(initialCapacity));
|
||||
}
|
||||
|
||||
@ -285,7 +287,7 @@ public final class ByteString {
|
||||
/**
|
||||
* Constructs a new output with the given initial capacity.
|
||||
*/
|
||||
private Output(ByteArrayOutputStream bout) {
|
||||
private Output(final ByteArrayOutputStream bout) {
|
||||
super(bout);
|
||||
this.bout = bout;
|
||||
}
|
||||
@ -294,14 +296,14 @@ public final class ByteString {
|
||||
* Creates a {@code ByteString} instance from this {@code Output}.
|
||||
*/
|
||||
public ByteString toByteString() {
|
||||
byte[] byteArray = bout.toByteArray();
|
||||
final byte[] byteArray = bout.toByteArray();
|
||||
return new ByteString(byteArray);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new ByteString builder, which allows you to efficiently
|
||||
* construct a {@code ByteString} by writing to a {@link CodedOutputSteam}.
|
||||
* construct a {@code ByteString} by writing to a {@link CodedOutputStream}.
|
||||
* Using this is much more efficient than calling {@code newOutput()} and
|
||||
* wrapping that in a {@code CodedOutputStream}.
|
||||
*
|
||||
@ -312,7 +314,7 @@ public final class ByteString {
|
||||
* @param size The target byte size of the {@code ByteString}. You must
|
||||
* write exactly this many bytes before building the result.
|
||||
*/
|
||||
static CodedBuilder newCodedBuilder(int size) {
|
||||
static CodedBuilder newCodedBuilder(final int size) {
|
||||
return new CodedBuilder(size);
|
||||
}
|
||||
|
||||
@ -321,7 +323,7 @@ public final class ByteString {
|
||||
private final CodedOutputStream output;
|
||||
private final byte[] buffer;
|
||||
|
||||
private CodedBuilder(int size) {
|
||||
private CodedBuilder(final int size) {
|
||||
buffer = new byte[size];
|
||||
output = CodedOutputStream.newInstance(buffer);
|
||||
}
|
||||
|
@ -51,21 +51,22 @@ public final class CodedInputStream {
|
||||
/**
|
||||
* Create a new CodedInputStream wrapping the given InputStream.
|
||||
*/
|
||||
public static CodedInputStream newInstance(InputStream input) {
|
||||
public static CodedInputStream newInstance(final InputStream input) {
|
||||
return new CodedInputStream(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new CodedInputStream wrapping the given byte array.
|
||||
*/
|
||||
public static CodedInputStream newInstance(byte[] buf) {
|
||||
public static CodedInputStream newInstance(final byte[] buf) {
|
||||
return newInstance(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new CodedInputStream wrapping the given byte array slice.
|
||||
*/
|
||||
public static CodedInputStream newInstance(byte[] buf, int off, int len) {
|
||||
public static CodedInputStream newInstance(final byte[] buf, final int off,
|
||||
final int len) {
|
||||
return new CodedInputStream(buf, off, len);
|
||||
}
|
||||
|
||||
@ -98,7 +99,8 @@ public final class CodedInputStream {
|
||||
* @throws InvalidProtocolBufferException {@code value} does not match the
|
||||
* last tag.
|
||||
*/
|
||||
public void checkLastTagWas(int value) throws InvalidProtocolBufferException {
|
||||
public void checkLastTagWas(final int value)
|
||||
throws InvalidProtocolBufferException {
|
||||
if (lastTag != value) {
|
||||
throw InvalidProtocolBufferException.invalidEndTag();
|
||||
}
|
||||
@ -110,7 +112,7 @@ public final class CodedInputStream {
|
||||
* @return {@code false} if the tag is an endgroup tag, in which case
|
||||
* nothing is skipped. Otherwise, returns {@code true}.
|
||||
*/
|
||||
public boolean skipField(int tag) throws IOException {
|
||||
public boolean skipField(final int tag) throws IOException {
|
||||
switch (WireFormat.getTagWireType(tag)) {
|
||||
case WireFormat.WIRETYPE_VARINT:
|
||||
readInt32();
|
||||
@ -143,8 +145,10 @@ public final class CodedInputStream {
|
||||
*/
|
||||
public void skipMessage() throws IOException {
|
||||
while (true) {
|
||||
int tag = readTag();
|
||||
if (tag == 0 || !skipField(tag)) return;
|
||||
final int tag = readTag();
|
||||
if (tag == 0 || !skipField(tag)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,11 +196,11 @@ public final class CodedInputStream {
|
||||
|
||||
/** Read a {@code string} field value from the stream. */
|
||||
public String readString() throws IOException {
|
||||
int size = readRawVarint32();
|
||||
final int size = readRawVarint32();
|
||||
if (size <= (bufferSize - bufferPos) && size > 0) {
|
||||
// Fast path: We already have the bytes in a contiguous buffer, so
|
||||
// just copy directly from it.
|
||||
String result = new String(buffer, bufferPos, size, "UTF-8");
|
||||
final String result = new String(buffer, bufferPos, size, "UTF-8");
|
||||
bufferPos += size;
|
||||
return result;
|
||||
} else {
|
||||
@ -206,8 +210,9 @@ public final class CodedInputStream {
|
||||
}
|
||||
|
||||
/** Read a {@code group} field value from the stream. */
|
||||
public void readGroup(int fieldNumber, Message.Builder builder,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
public void readGroup(final int fieldNumber,
|
||||
final MessageLite.Builder builder,
|
||||
final ExtensionRegistryLite extensionRegistry)
|
||||
throws IOException {
|
||||
if (recursionDepth >= recursionLimit) {
|
||||
throw InvalidProtocolBufferException.recursionLimitExceeded();
|
||||
@ -222,28 +227,31 @@ public final class CodedInputStream {
|
||||
/**
|
||||
* Reads a {@code group} field value from the stream and merges it into the
|
||||
* given {@link UnknownFieldSet}.
|
||||
*
|
||||
* @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so
|
||||
* you can just call {@link #readGroup}.
|
||||
*/
|
||||
public void readUnknownGroup(int fieldNumber, UnknownFieldSet.Builder builder)
|
||||
@Deprecated
|
||||
public void readUnknownGroup(final int fieldNumber,
|
||||
final MessageLite.Builder builder)
|
||||
throws IOException {
|
||||
if (recursionDepth >= recursionLimit) {
|
||||
throw InvalidProtocolBufferException.recursionLimitExceeded();
|
||||
}
|
||||
++recursionDepth;
|
||||
builder.mergeFrom(this);
|
||||
checkLastTagWas(
|
||||
WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
|
||||
--recursionDepth;
|
||||
// We know that UnknownFieldSet will ignore any ExtensionRegistry so it
|
||||
// is safe to pass null here. (We can't call
|
||||
// ExtensionRegistry.getEmptyRegistry() because that would make this
|
||||
// class depend on ExtensionRegistry, which is not part of the lite
|
||||
// library.)
|
||||
readGroup(fieldNumber, builder, null);
|
||||
}
|
||||
|
||||
/** Read an embedded message field value from the stream. */
|
||||
public void readMessage(Message.Builder builder,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
public void readMessage(final MessageLite.Builder builder,
|
||||
final ExtensionRegistryLite extensionRegistry)
|
||||
throws IOException {
|
||||
int length = readRawVarint32();
|
||||
final int length = readRawVarint32();
|
||||
if (recursionDepth >= recursionLimit) {
|
||||
throw InvalidProtocolBufferException.recursionLimitExceeded();
|
||||
}
|
||||
int oldLimit = pushLimit(length);
|
||||
final int oldLimit = pushLimit(length);
|
||||
++recursionDepth;
|
||||
builder.mergeFrom(this, extensionRegistry);
|
||||
checkLastTagWas(0);
|
||||
@ -253,11 +261,11 @@ public final class CodedInputStream {
|
||||
|
||||
/** Read a {@code bytes} field value from the stream. */
|
||||
public ByteString readBytes() throws IOException {
|
||||
int size = readRawVarint32();
|
||||
if (size < bufferSize - bufferPos && size > 0) {
|
||||
final int size = readRawVarint32();
|
||||
if (size <= (bufferSize - bufferPos) && size > 0) {
|
||||
// Fast path: We already have the bytes in a contiguous buffer, so
|
||||
// just copy directly from it.
|
||||
ByteString result = ByteString.copyFrom(buffer, bufferPos, size);
|
||||
final ByteString result = ByteString.copyFrom(buffer, bufferPos, size);
|
||||
bufferPos += size;
|
||||
return result;
|
||||
} else {
|
||||
@ -299,52 +307,6 @@ public final class CodedInputStream {
|
||||
return decodeZigZag64(readRawVarint64());
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a field of any primitive type. Enums, groups, and embedded
|
||||
* messages are not handled by this method.
|
||||
*
|
||||
* @param type Declared type of the field.
|
||||
* @return An object representing the field's value, of the exact
|
||||
* type which would be returned by
|
||||
* {@link Message#getField(Descriptors.FieldDescriptor)} for
|
||||
* this field.
|
||||
*/
|
||||
public Object readPrimitiveField(
|
||||
Descriptors.FieldDescriptor.Type type) throws IOException {
|
||||
switch (type) {
|
||||
case DOUBLE : return readDouble ();
|
||||
case FLOAT : return readFloat ();
|
||||
case INT64 : return readInt64 ();
|
||||
case UINT64 : return readUInt64 ();
|
||||
case INT32 : return readInt32 ();
|
||||
case FIXED64 : return readFixed64 ();
|
||||
case FIXED32 : return readFixed32 ();
|
||||
case BOOL : return readBool ();
|
||||
case STRING : return readString ();
|
||||
case BYTES : return readBytes ();
|
||||
case UINT32 : return readUInt32 ();
|
||||
case SFIXED32: return readSFixed32();
|
||||
case SFIXED64: return readSFixed64();
|
||||
case SINT32 : return readSInt32 ();
|
||||
case SINT64 : return readSInt64 ();
|
||||
|
||||
case GROUP:
|
||||
throw new IllegalArgumentException(
|
||||
"readPrimitiveField() cannot handle nested groups.");
|
||||
case MESSAGE:
|
||||
throw new IllegalArgumentException(
|
||||
"readPrimitiveField() cannot handle embedded messages.");
|
||||
case ENUM:
|
||||
// We don't hanlde enums because we don't know what to do if the
|
||||
// value is not recognized.
|
||||
throw new IllegalArgumentException(
|
||||
"readPrimitiveField() cannot handle enums.");
|
||||
}
|
||||
|
||||
throw new RuntimeException(
|
||||
"There is no way to get here, but the compiler thinks otherwise.");
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
|
||||
/**
|
||||
@ -373,7 +335,9 @@ public final class CodedInputStream {
|
||||
if (tmp < 0) {
|
||||
// Discard upper 32 bits.
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (readRawByte() >= 0) return result;
|
||||
if (readRawByte() >= 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
throw InvalidProtocolBufferException.malformedVarint();
|
||||
}
|
||||
@ -390,11 +354,11 @@ public final class CodedInputStream {
|
||||
* then you would probably end up reading past the end of the varint since
|
||||
* CodedInputStream buffers its input.
|
||||
*/
|
||||
static int readRawVarint32(InputStream input) throws IOException {
|
||||
static int readRawVarint32(final InputStream input) throws IOException {
|
||||
int result = 0;
|
||||
int offset = 0;
|
||||
for (; offset < 32; offset += 7) {
|
||||
int b = input.read();
|
||||
final int b = input.read();
|
||||
if (b == -1) {
|
||||
throw InvalidProtocolBufferException.truncatedMessage();
|
||||
}
|
||||
@ -405,7 +369,7 @@ public final class CodedInputStream {
|
||||
}
|
||||
// Keep reading up to 64 bits.
|
||||
for (; offset < 64; offset += 7) {
|
||||
int b = input.read();
|
||||
final int b = input.read();
|
||||
if (b == -1) {
|
||||
throw InvalidProtocolBufferException.truncatedMessage();
|
||||
}
|
||||
@ -421,9 +385,11 @@ public final class CodedInputStream {
|
||||
int shift = 0;
|
||||
long result = 0;
|
||||
while (shift < 64) {
|
||||
byte b = readRawByte();
|
||||
final byte b = readRawByte();
|
||||
result |= (long)(b & 0x7F) << shift;
|
||||
if ((b & 0x80) == 0) return result;
|
||||
if ((b & 0x80) == 0) {
|
||||
return result;
|
||||
}
|
||||
shift += 7;
|
||||
}
|
||||
throw InvalidProtocolBufferException.malformedVarint();
|
||||
@ -431,10 +397,10 @@ public final class CodedInputStream {
|
||||
|
||||
/** Read a 32-bit little-endian integer from the stream. */
|
||||
public int readRawLittleEndian32() throws IOException {
|
||||
byte b1 = readRawByte();
|
||||
byte b2 = readRawByte();
|
||||
byte b3 = readRawByte();
|
||||
byte b4 = readRawByte();
|
||||
final byte b1 = readRawByte();
|
||||
final byte b2 = readRawByte();
|
||||
final byte b3 = readRawByte();
|
||||
final byte b4 = readRawByte();
|
||||
return (((int)b1 & 0xff) ) |
|
||||
(((int)b2 & 0xff) << 8) |
|
||||
(((int)b3 & 0xff) << 16) |
|
||||
@ -443,14 +409,14 @@ public final class CodedInputStream {
|
||||
|
||||
/** Read a 64-bit little-endian integer from the stream. */
|
||||
public long readRawLittleEndian64() throws IOException {
|
||||
byte b1 = readRawByte();
|
||||
byte b2 = readRawByte();
|
||||
byte b3 = readRawByte();
|
||||
byte b4 = readRawByte();
|
||||
byte b5 = readRawByte();
|
||||
byte b6 = readRawByte();
|
||||
byte b7 = readRawByte();
|
||||
byte b8 = readRawByte();
|
||||
final byte b1 = readRawByte();
|
||||
final byte b2 = readRawByte();
|
||||
final byte b3 = readRawByte();
|
||||
final byte b4 = readRawByte();
|
||||
final byte b5 = readRawByte();
|
||||
final byte b6 = readRawByte();
|
||||
final byte b7 = readRawByte();
|
||||
final byte b8 = readRawByte();
|
||||
return (((long)b1 & 0xff) ) |
|
||||
(((long)b2 & 0xff) << 8) |
|
||||
(((long)b3 & 0xff) << 16) |
|
||||
@ -471,7 +437,7 @@ public final class CodedInputStream {
|
||||
* Java has no explicit unsigned support.
|
||||
* @return A signed 32-bit integer.
|
||||
*/
|
||||
public static int decodeZigZag32(int n) {
|
||||
public static int decodeZigZag32(final int n) {
|
||||
return (n >>> 1) ^ -(n & 1);
|
||||
}
|
||||
|
||||
@ -485,31 +451,31 @@ public final class CodedInputStream {
|
||||
* Java has no explicit unsigned support.
|
||||
* @return A signed 64-bit integer.
|
||||
*/
|
||||
public static long decodeZigZag64(long n) {
|
||||
public static long decodeZigZag64(final long n) {
|
||||
return (n >>> 1) ^ -(n & 1);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
private byte[] buffer;
|
||||
private final byte[] buffer;
|
||||
private int bufferSize;
|
||||
private int bufferSizeAfterLimit = 0;
|
||||
private int bufferSizeAfterLimit;
|
||||
private int bufferPos;
|
||||
private InputStream input;
|
||||
private int lastTag = 0;
|
||||
private final InputStream input;
|
||||
private int lastTag;
|
||||
|
||||
/**
|
||||
* The total number of bytes read before the current buffer. The total
|
||||
* bytes read up to the current position can be computed as
|
||||
* {@code totalBytesRetired + bufferPos}.
|
||||
*/
|
||||
private int totalBytesRetired = 0;
|
||||
private int totalBytesRetired;
|
||||
|
||||
/** The absolute position of the end of the current message. */
|
||||
private int currentLimit = Integer.MAX_VALUE;
|
||||
|
||||
/** See setRecursionLimit() */
|
||||
private int recursionDepth = 0;
|
||||
private int recursionDepth;
|
||||
private int recursionLimit = DEFAULT_RECURSION_LIMIT;
|
||||
|
||||
/** See setSizeLimit() */
|
||||
@ -519,17 +485,17 @@ public final class CodedInputStream {
|
||||
private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB
|
||||
private static final int BUFFER_SIZE = 4096;
|
||||
|
||||
private CodedInputStream(byte[] buffer, int off, int len) {
|
||||
private CodedInputStream(final byte[] buffer, final int off, final int len) {
|
||||
this.buffer = buffer;
|
||||
this.bufferSize = off + len;
|
||||
this.bufferPos = off;
|
||||
this.input = null;
|
||||
bufferSize = off + len;
|
||||
bufferPos = off;
|
||||
input = null;
|
||||
}
|
||||
|
||||
private CodedInputStream(InputStream input) {
|
||||
this.buffer = new byte[BUFFER_SIZE];
|
||||
this.bufferSize = 0;
|
||||
this.bufferPos = 0;
|
||||
private CodedInputStream(final InputStream input) {
|
||||
buffer = new byte[BUFFER_SIZE];
|
||||
bufferSize = 0;
|
||||
bufferPos = 0;
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
@ -540,12 +506,12 @@ public final class CodedInputStream {
|
||||
*
|
||||
* @return the old limit.
|
||||
*/
|
||||
public int setRecursionLimit(int limit) {
|
||||
public int setRecursionLimit(final int limit) {
|
||||
if (limit < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Recursion limit cannot be negative: " + limit);
|
||||
}
|
||||
int oldLimit = recursionLimit;
|
||||
final int oldLimit = recursionLimit;
|
||||
recursionLimit = limit;
|
||||
return oldLimit;
|
||||
}
|
||||
@ -566,12 +532,12 @@ public final class CodedInputStream {
|
||||
*
|
||||
* @return the old limit.
|
||||
*/
|
||||
public int setSizeLimit(int limit) {
|
||||
public int setSizeLimit(final int limit) {
|
||||
if (limit < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Size limit cannot be negative: " + limit);
|
||||
}
|
||||
int oldLimit = sizeLimit;
|
||||
final int oldLimit = sizeLimit;
|
||||
sizeLimit = limit;
|
||||
return oldLimit;
|
||||
}
|
||||
@ -594,7 +560,7 @@ public final class CodedInputStream {
|
||||
throw InvalidProtocolBufferException.negativeSize();
|
||||
}
|
||||
byteLimit += totalBytesRetired + bufferPos;
|
||||
int oldLimit = currentLimit;
|
||||
final int oldLimit = currentLimit;
|
||||
if (byteLimit > oldLimit) {
|
||||
throw InvalidProtocolBufferException.truncatedMessage();
|
||||
}
|
||||
@ -607,7 +573,7 @@ public final class CodedInputStream {
|
||||
|
||||
private void recomputeBufferSizeAfterLimit() {
|
||||
bufferSize += bufferSizeAfterLimit;
|
||||
int bufferEnd = totalBytesRetired + bufferSize;
|
||||
final int bufferEnd = totalBytesRetired + bufferSize;
|
||||
if (bufferEnd > currentLimit) {
|
||||
// Limit is in current buffer.
|
||||
bufferSizeAfterLimit = bufferEnd - currentLimit;
|
||||
@ -622,7 +588,7 @@ public final class CodedInputStream {
|
||||
*
|
||||
* @param oldLimit The old limit, as returned by {@code pushLimit}.
|
||||
*/
|
||||
public void popLimit(int oldLimit) {
|
||||
public void popLimit(final int oldLimit) {
|
||||
currentLimit = oldLimit;
|
||||
recomputeBufferSizeAfterLimit();
|
||||
}
|
||||
@ -636,7 +602,7 @@ public final class CodedInputStream {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int currentAbsolutePosition = totalBytesRetired + bufferPos;
|
||||
final int currentAbsolutePosition = totalBytesRetired + bufferPos;
|
||||
return currentLimit - currentAbsolutePosition;
|
||||
}
|
||||
|
||||
@ -656,7 +622,7 @@ public final class CodedInputStream {
|
||||
* or it will throw an exception. If {@code mustSucceed} is false,
|
||||
* refillBuffer() returns false if no more bytes were available.
|
||||
*/
|
||||
private boolean refillBuffer(boolean mustSucceed) throws IOException {
|
||||
private boolean refillBuffer(final boolean mustSucceed) throws IOException {
|
||||
if (bufferPos < bufferSize) {
|
||||
throw new IllegalStateException(
|
||||
"refillBuffer() called when buffer wasn't empty.");
|
||||
@ -689,7 +655,7 @@ public final class CodedInputStream {
|
||||
}
|
||||
} else {
|
||||
recomputeBufferSizeAfterLimit();
|
||||
int totalBytesRead =
|
||||
final int totalBytesRead =
|
||||
totalBytesRetired + bufferSize + bufferSizeAfterLimit;
|
||||
if (totalBytesRead > sizeLimit || totalBytesRead < 0) {
|
||||
throw InvalidProtocolBufferException.sizeLimitExceeded();
|
||||
@ -717,7 +683,7 @@ public final class CodedInputStream {
|
||||
* @throws InvalidProtocolBufferException The end of the stream or the current
|
||||
* limit was reached.
|
||||
*/
|
||||
public byte[] readRawBytes(int size) throws IOException {
|
||||
public byte[] readRawBytes(final int size) throws IOException {
|
||||
if (size < 0) {
|
||||
throw InvalidProtocolBufferException.negativeSize();
|
||||
}
|
||||
@ -731,7 +697,7 @@ public final class CodedInputStream {
|
||||
|
||||
if (size <= bufferSize - bufferPos) {
|
||||
// We have all the bytes we need already.
|
||||
byte[] bytes = new byte[size];
|
||||
final byte[] bytes = new byte[size];
|
||||
System.arraycopy(buffer, bufferPos, bytes, 0, size);
|
||||
bufferPos += size;
|
||||
return bytes;
|
||||
@ -740,7 +706,7 @@ public final class CodedInputStream {
|
||||
// of bytes. We can safely allocate the resulting array ahead of time.
|
||||
|
||||
// First copy what we have.
|
||||
byte[] bytes = new byte[size];
|
||||
final byte[] bytes = new byte[size];
|
||||
int pos = bufferSize - bufferPos;
|
||||
System.arraycopy(buffer, bufferPos, bytes, 0, pos);
|
||||
bufferPos = bufferSize;
|
||||
@ -772,8 +738,8 @@ public final class CodedInputStream {
|
||||
|
||||
// Remember the buffer markers since we'll have to copy the bytes out of
|
||||
// it later.
|
||||
int originalBufferPos = bufferPos;
|
||||
int originalBufferSize = bufferSize;
|
||||
final int originalBufferPos = bufferPos;
|
||||
final int originalBufferSize = bufferSize;
|
||||
|
||||
// Mark the current buffer consumed.
|
||||
totalBytesRetired += bufferSize;
|
||||
@ -782,13 +748,13 @@ public final class CodedInputStream {
|
||||
|
||||
// Read all the rest of the bytes we need.
|
||||
int sizeLeft = size - (originalBufferSize - originalBufferPos);
|
||||
List<byte[]> chunks = new ArrayList<byte[]>();
|
||||
final List<byte[]> chunks = new ArrayList<byte[]>();
|
||||
|
||||
while (sizeLeft > 0) {
|
||||
byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
|
||||
final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
|
||||
int pos = 0;
|
||||
while (pos < chunk.length) {
|
||||
int n = (input == null) ? -1 :
|
||||
final int n = (input == null) ? -1 :
|
||||
input.read(chunk, pos, chunk.length - pos);
|
||||
if (n == -1) {
|
||||
throw InvalidProtocolBufferException.truncatedMessage();
|
||||
@ -801,14 +767,14 @@ public final class CodedInputStream {
|
||||
}
|
||||
|
||||
// OK, got everything. Now concatenate it all into one buffer.
|
||||
byte[] bytes = new byte[size];
|
||||
final byte[] bytes = new byte[size];
|
||||
|
||||
// Start by copying the leftover bytes from this.buffer.
|
||||
int pos = originalBufferSize - originalBufferPos;
|
||||
System.arraycopy(buffer, originalBufferPos, bytes, 0, pos);
|
||||
|
||||
// And now all the chunks.
|
||||
for (byte[] chunk : chunks) {
|
||||
for (final byte[] chunk : chunks) {
|
||||
System.arraycopy(chunk, 0, bytes, pos, chunk.length);
|
||||
pos += chunk.length;
|
||||
}
|
||||
@ -824,7 +790,7 @@ public final class CodedInputStream {
|
||||
* @throws InvalidProtocolBufferException The end of the stream or the current
|
||||
* limit was reached.
|
||||
*/
|
||||
public void skipRawBytes(int size) throws IOException {
|
||||
public void skipRawBytes(final int size) throws IOException {
|
||||
if (size < 0) {
|
||||
throw InvalidProtocolBufferException.negativeSize();
|
||||
}
|
||||
@ -848,7 +814,7 @@ public final class CodedInputStream {
|
||||
|
||||
// Then skip directly from the InputStream for the rest.
|
||||
while (pos < size) {
|
||||
int n = (input == null) ? -1 : (int) input.skip(size - pos);
|
||||
final int n = (input == null) ? -1 : (int) input.skip(size - pos);
|
||||
if (n <= 0) {
|
||||
throw InvalidProtocolBufferException.truncatedMessage();
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ package com.google.protobuf;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
/**
|
||||
* Encodes and writes protocol message fields.
|
||||
@ -55,29 +56,30 @@ public final class CodedOutputStream {
|
||||
private final OutputStream output;
|
||||
|
||||
/**
|
||||
* The buffer size used in {@link #newInstance(java.io.OutputStream)}.
|
||||
* The buffer size used in {@link #newInstance(OutputStream)}.
|
||||
*/
|
||||
public static final int DEFAULT_BUFFER_SIZE = 4096;
|
||||
|
||||
private CodedOutputStream(byte[] buffer, int offset, int length) {
|
||||
this.output = null;
|
||||
private CodedOutputStream(final byte[] buffer, final int offset,
|
||||
final int length) {
|
||||
output = null;
|
||||
this.buffer = buffer;
|
||||
this.position = offset;
|
||||
this.limit = offset + length;
|
||||
position = offset;
|
||||
limit = offset + length;
|
||||
}
|
||||
|
||||
private CodedOutputStream(OutputStream output, byte[] buffer) {
|
||||
private CodedOutputStream(final OutputStream output, final byte[] buffer) {
|
||||
this.output = output;
|
||||
this.buffer = buffer;
|
||||
this.position = 0;
|
||||
this.limit = buffer.length;
|
||||
position = 0;
|
||||
limit = buffer.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code CodedOutputStream} wrapping the given
|
||||
* {@code OutputStream}.
|
||||
*/
|
||||
public static CodedOutputStream newInstance(OutputStream output) {
|
||||
public static CodedOutputStream newInstance(final OutputStream output) {
|
||||
return newInstance(output, DEFAULT_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
@ -85,8 +87,8 @@ public final class CodedOutputStream {
|
||||
* Create a new {@code CodedOutputStream} wrapping the given
|
||||
* {@code OutputStream} with a given buffer size.
|
||||
*/
|
||||
public static CodedOutputStream newInstance(OutputStream output,
|
||||
int bufferSize) {
|
||||
public static CodedOutputStream newInstance(final OutputStream output,
|
||||
final int bufferSize) {
|
||||
return new CodedOutputStream(output, new byte[bufferSize]);
|
||||
}
|
||||
|
||||
@ -97,7 +99,7 @@ public final class CodedOutputStream {
|
||||
* array is faster than writing to an {@code OutputStream}. See also
|
||||
* {@link ByteString#newCodedBuilder}.
|
||||
*/
|
||||
public static CodedOutputStream newInstance(byte[] flatArray) {
|
||||
public static CodedOutputStream newInstance(final byte[] flatArray) {
|
||||
return newInstance(flatArray, 0, flatArray.length);
|
||||
}
|
||||
|
||||
@ -108,96 +110,115 @@ public final class CodedOutputStream {
|
||||
* array is faster than writing to an {@code OutputStream}. See also
|
||||
* {@link ByteString#newCodedBuilder}.
|
||||
*/
|
||||
public static CodedOutputStream newInstance(byte[] flatArray, int offset,
|
||||
int length) {
|
||||
public static CodedOutputStream newInstance(final byte[] flatArray,
|
||||
final int offset,
|
||||
final int length) {
|
||||
return new CodedOutputStream(flatArray, offset, length);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
/** Write a {@code double} field, including tag, to the stream. */
|
||||
public void writeDouble(int fieldNumber, double value) throws IOException {
|
||||
public void writeDouble(final int fieldNumber, final double value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
|
||||
writeDoubleNoTag(value);
|
||||
}
|
||||
|
||||
/** Write a {@code float} field, including tag, to the stream. */
|
||||
public void writeFloat(int fieldNumber, float value) throws IOException {
|
||||
public void writeFloat(final int fieldNumber, final float value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
|
||||
writeFloatNoTag(value);
|
||||
}
|
||||
|
||||
/** Write a {@code uint64} field, including tag, to the stream. */
|
||||
public void writeUInt64(int fieldNumber, long value) throws IOException {
|
||||
public void writeUInt64(final int fieldNumber, final long value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
|
||||
writeUInt64NoTag(value);
|
||||
}
|
||||
|
||||
/** Write an {@code int64} field, including tag, to the stream. */
|
||||
public void writeInt64(int fieldNumber, long value) throws IOException {
|
||||
public void writeInt64(final int fieldNumber, final long value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
|
||||
writeInt64NoTag(value);
|
||||
}
|
||||
|
||||
/** Write an {@code int32} field, including tag, to the stream. */
|
||||
public void writeInt32(int fieldNumber, int value) throws IOException {
|
||||
public void writeInt32(final int fieldNumber, final int value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
|
||||
writeInt32NoTag(value);
|
||||
}
|
||||
|
||||
/** Write a {@code fixed64} field, including tag, to the stream. */
|
||||
public void writeFixed64(int fieldNumber, long value) throws IOException {
|
||||
public void writeFixed64(final int fieldNumber, final long value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
|
||||
writeFixed64NoTag(value);
|
||||
}
|
||||
|
||||
/** Write a {@code fixed32} field, including tag, to the stream. */
|
||||
public void writeFixed32(int fieldNumber, int value) throws IOException {
|
||||
public void writeFixed32(final int fieldNumber, final int value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
|
||||
writeFixed32NoTag(value);
|
||||
}
|
||||
|
||||
/** Write a {@code bool} field, including tag, to the stream. */
|
||||
public void writeBool(int fieldNumber, boolean value) throws IOException {
|
||||
public void writeBool(final int fieldNumber, final boolean value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
|
||||
writeBoolNoTag(value);
|
||||
}
|
||||
|
||||
/** Write a {@code string} field, including tag, to the stream. */
|
||||
public void writeString(int fieldNumber, String value) throws IOException {
|
||||
public void writeString(final int fieldNumber, final String value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
|
||||
writeStringNoTag(value);
|
||||
}
|
||||
|
||||
/** Write a {@code group} field, including tag, to the stream. */
|
||||
public void writeGroup(int fieldNumber, Message value) throws IOException {
|
||||
public void writeGroup(final int fieldNumber, final MessageLite value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
|
||||
writeGroupNoTag(value);
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
|
||||
}
|
||||
|
||||
/** Write a group represented by an {@link UnknownFieldSet}. */
|
||||
public void writeUnknownGroup(int fieldNumber, UnknownFieldSet value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
|
||||
writeUnknownGroupNoTag(value);
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
|
||||
/**
|
||||
* Write a group represented by an {@link UnknownFieldSet}.
|
||||
*
|
||||
* @deprecated UnknownFieldSet now implements MessageLite, so you can just
|
||||
* call {@link #writeGroup}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void writeUnknownGroup(final int fieldNumber,
|
||||
final MessageLite value)
|
||||
throws IOException {
|
||||
writeGroup(fieldNumber, value);
|
||||
}
|
||||
|
||||
/** Write an embedded message field, including tag, to the stream. */
|
||||
public void writeMessage(int fieldNumber, Message value) throws IOException {
|
||||
public void writeMessage(final int fieldNumber, final MessageLite value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
|
||||
writeMessageNoTag(value);
|
||||
}
|
||||
|
||||
/** Write a {@code bytes} field, including tag, to the stream. */
|
||||
public void writeBytes(int fieldNumber, ByteString value) throws IOException {
|
||||
public void writeBytes(final int fieldNumber, final ByteString value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
|
||||
writeBytesNoTag(value);
|
||||
}
|
||||
|
||||
/** Write a {@code uint32} field, including tag, to the stream. */
|
||||
public void writeUInt32(int fieldNumber, int value) throws IOException {
|
||||
public void writeUInt32(final int fieldNumber, final int value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
|
||||
writeUInt32NoTag(value);
|
||||
}
|
||||
@ -206,31 +227,36 @@ public final class CodedOutputStream {
|
||||
* Write an enum field, including tag, to the stream. Caller is responsible
|
||||
* for converting the enum value to its numeric value.
|
||||
*/
|
||||
public void writeEnum(int fieldNumber, int value) throws IOException {
|
||||
public void writeEnum(final int fieldNumber, final int value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
|
||||
writeEnumNoTag(value);
|
||||
}
|
||||
|
||||
/** Write an {@code sfixed32} field, including tag, to the stream. */
|
||||
public void writeSFixed32(int fieldNumber, int value) throws IOException {
|
||||
public void writeSFixed32(final int fieldNumber, final int value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
|
||||
writeSFixed32NoTag(value);
|
||||
}
|
||||
|
||||
/** Write an {@code sfixed64} field, including tag, to the stream. */
|
||||
public void writeSFixed64(int fieldNumber, long value) throws IOException {
|
||||
public void writeSFixed64(final int fieldNumber, final long value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
|
||||
writeSFixed64NoTag(value);
|
||||
}
|
||||
|
||||
/** Write an {@code sint32} field, including tag, to the stream. */
|
||||
public void writeSInt32(int fieldNumber, int value) throws IOException {
|
||||
public void writeSInt32(final int fieldNumber, final int value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
|
||||
writeSInt32NoTag(value);
|
||||
}
|
||||
|
||||
/** Write an {@code sint64} field, including tag, to the stream. */
|
||||
public void writeSInt64(int fieldNumber, long value) throws IOException {
|
||||
public void writeSInt64(final int fieldNumber, final long value)
|
||||
throws IOException {
|
||||
writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
|
||||
writeSInt64NoTag(value);
|
||||
}
|
||||
@ -239,8 +265,9 @@ public final class CodedOutputStream {
|
||||
* Write a MessageSet extension field to the stream. For historical reasons,
|
||||
* the wire format differs from normal fields.
|
||||
*/
|
||||
public void writeMessageSetExtension(int fieldNumber, Message value)
|
||||
throws IOException {
|
||||
public void writeMessageSetExtension(final int fieldNumber,
|
||||
final MessageLite value)
|
||||
throws IOException {
|
||||
writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
|
||||
writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
|
||||
writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
|
||||
@ -251,7 +278,8 @@ public final class CodedOutputStream {
|
||||
* Write an unparsed MessageSet extension field to the stream. For
|
||||
* historical reasons, the wire format differs from normal fields.
|
||||
*/
|
||||
public void writeRawMessageSetExtension(int fieldNumber, ByteString value)
|
||||
public void writeRawMessageSetExtension(final int fieldNumber,
|
||||
final ByteString value)
|
||||
throws IOException {
|
||||
writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
|
||||
writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
|
||||
@ -259,89 +287,30 @@ public final class CodedOutputStream {
|
||||
writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a field of arbitrary type, including tag, to the stream.
|
||||
*
|
||||
* @param type The field's type.
|
||||
* @param number The field's number.
|
||||
* @param value Object representing the field's value. Must be of the exact
|
||||
* type which would be returned by
|
||||
* {@link Message#getField(Descriptors.FieldDescriptor)} for
|
||||
* this field.
|
||||
*/
|
||||
public void writeField(Descriptors.FieldDescriptor.Type type,
|
||||
int number,
|
||||
Object value) throws IOException {
|
||||
// Special case for groups, which need a start and end tag; other fields
|
||||
// can just use writeTag() and writeFieldNoTag().
|
||||
if (type == Descriptors.FieldDescriptor.Type.GROUP) {
|
||||
writeGroup(number, (Message) value);
|
||||
} else {
|
||||
writeTag(number, WireFormat.getWireFormatForFieldType(type));
|
||||
writeFieldNoTag(type, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a field of arbitrary type, without its tag, to the stream.
|
||||
*
|
||||
* @param type The field's type.
|
||||
* @param value Object representing the field's value. Must be of the exact
|
||||
* type which would be returned by
|
||||
* {@link Message#getField(Descriptors.FieldDescriptor)} for
|
||||
* this field.
|
||||
*/
|
||||
public void writeFieldNoTag(Descriptors.FieldDescriptor.Type type,
|
||||
Object value) throws IOException {
|
||||
switch (type) {
|
||||
case DOUBLE : writeDoubleNoTag ((Double ) value); break;
|
||||
case FLOAT : writeFloatNoTag ((Float ) value); break;
|
||||
case INT64 : writeInt64NoTag ((Long ) value); break;
|
||||
case UINT64 : writeUInt64NoTag ((Long ) value); break;
|
||||
case INT32 : writeInt32NoTag ((Integer ) value); break;
|
||||
case FIXED64 : writeFixed64NoTag ((Long ) value); break;
|
||||
case FIXED32 : writeFixed32NoTag ((Integer ) value); break;
|
||||
case BOOL : writeBoolNoTag ((Boolean ) value); break;
|
||||
case STRING : writeStringNoTag ((String ) value); break;
|
||||
case GROUP : writeGroupNoTag ((Message ) value); break;
|
||||
case MESSAGE : writeMessageNoTag ((Message ) value); break;
|
||||
case BYTES : writeBytesNoTag ((ByteString) value); break;
|
||||
case UINT32 : writeUInt32NoTag ((Integer ) value); break;
|
||||
case SFIXED32: writeSFixed32NoTag((Integer ) value); break;
|
||||
case SFIXED64: writeSFixed64NoTag((Long ) value); break;
|
||||
case SINT32 : writeSInt32NoTag ((Integer ) value); break;
|
||||
case SINT64 : writeSInt64NoTag ((Long ) value); break;
|
||||
|
||||
case ENUM:
|
||||
writeEnumNoTag(((Descriptors.EnumValueDescriptor) value).getNumber());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
/** Write a {@code double} field to the stream. */
|
||||
public void writeDoubleNoTag(double value) throws IOException {
|
||||
public void writeDoubleNoTag(final double value) throws IOException {
|
||||
writeRawLittleEndian64(Double.doubleToRawLongBits(value));
|
||||
}
|
||||
|
||||
/** Write a {@code float} field to the stream. */
|
||||
public void writeFloatNoTag(float value) throws IOException {
|
||||
public void writeFloatNoTag(final float value) throws IOException {
|
||||
writeRawLittleEndian32(Float.floatToRawIntBits(value));
|
||||
}
|
||||
|
||||
/** Write a {@code uint64} field to the stream. */
|
||||
public void writeUInt64NoTag(long value) throws IOException {
|
||||
public void writeUInt64NoTag(final long value) throws IOException {
|
||||
writeRawVarint64(value);
|
||||
}
|
||||
|
||||
/** Write an {@code int64} field to the stream. */
|
||||
public void writeInt64NoTag(long value) throws IOException {
|
||||
public void writeInt64NoTag(final long value) throws IOException {
|
||||
writeRawVarint64(value);
|
||||
}
|
||||
|
||||
/** Write an {@code int32} field to the stream. */
|
||||
public void writeInt32NoTag(int value) throws IOException {
|
||||
public void writeInt32NoTag(final int value) throws IOException {
|
||||
if (value >= 0) {
|
||||
writeRawVarint32(value);
|
||||
} else {
|
||||
@ -351,56 +320,62 @@ public final class CodedOutputStream {
|
||||
}
|
||||
|
||||
/** Write a {@code fixed64} field to the stream. */
|
||||
public void writeFixed64NoTag(long value) throws IOException {
|
||||
public void writeFixed64NoTag(final long value) throws IOException {
|
||||
writeRawLittleEndian64(value);
|
||||
}
|
||||
|
||||
/** Write a {@code fixed32} field to the stream. */
|
||||
public void writeFixed32NoTag(int value) throws IOException {
|
||||
public void writeFixed32NoTag(final int value) throws IOException {
|
||||
writeRawLittleEndian32(value);
|
||||
}
|
||||
|
||||
/** Write a {@code bool} field to the stream. */
|
||||
public void writeBoolNoTag(boolean value) throws IOException {
|
||||
public void writeBoolNoTag(final boolean value) throws IOException {
|
||||
writeRawByte(value ? 1 : 0);
|
||||
}
|
||||
|
||||
/** Write a {@code string} field to the stream. */
|
||||
public void writeStringNoTag(String value) throws IOException {
|
||||
public void writeStringNoTag(final String value) throws IOException {
|
||||
// Unfortunately there does not appear to be any way to tell Java to encode
|
||||
// UTF-8 directly into our buffer, so we have to let it create its own byte
|
||||
// array and then copy.
|
||||
byte[] bytes = value.getBytes("UTF-8");
|
||||
final byte[] bytes = value.getBytes("UTF-8");
|
||||
writeRawVarint32(bytes.length);
|
||||
writeRawBytes(bytes);
|
||||
}
|
||||
|
||||
/** Write a {@code group} field to the stream. */
|
||||
public void writeGroupNoTag(Message value) throws IOException {
|
||||
public void writeGroupNoTag(final MessageLite value) throws IOException {
|
||||
value.writeTo(this);
|
||||
}
|
||||
|
||||
/** Write a group represented by an {@link UnknownFieldSet}. */
|
||||
public void writeUnknownGroupNoTag(UnknownFieldSet value)
|
||||
/**
|
||||
* Write a group represented by an {@link UnknownFieldSet}.
|
||||
*
|
||||
* @deprecated UnknownFieldSet now implements MessageLite, so you can just
|
||||
* call {@link #writeGroupNoTag}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void writeUnknownGroupNoTag(final MessageLite value)
|
||||
throws IOException {
|
||||
value.writeTo(this);
|
||||
writeGroupNoTag(value);
|
||||
}
|
||||
|
||||
/** Write an embedded message field to the stream. */
|
||||
public void writeMessageNoTag(Message value) throws IOException {
|
||||
public void writeMessageNoTag(final MessageLite value) throws IOException {
|
||||
writeRawVarint32(value.getSerializedSize());
|
||||
value.writeTo(this);
|
||||
}
|
||||
|
||||
/** Write a {@code bytes} field to the stream. */
|
||||
public void writeBytesNoTag(ByteString value) throws IOException {
|
||||
byte[] bytes = value.toByteArray();
|
||||
public void writeBytesNoTag(final ByteString value) throws IOException {
|
||||
final byte[] bytes = value.toByteArray();
|
||||
writeRawVarint32(bytes.length);
|
||||
writeRawBytes(bytes);
|
||||
}
|
||||
|
||||
/** Write a {@code uint32} field to the stream. */
|
||||
public void writeUInt32NoTag(int value) throws IOException {
|
||||
public void writeUInt32NoTag(final int value) throws IOException {
|
||||
writeRawVarint32(value);
|
||||
}
|
||||
|
||||
@ -408,27 +383,27 @@ public final class CodedOutputStream {
|
||||
* Write an enum field to the stream. Caller is responsible
|
||||
* for converting the enum value to its numeric value.
|
||||
*/
|
||||
public void writeEnumNoTag(int value) throws IOException {
|
||||
public void writeEnumNoTag(final int value) throws IOException {
|
||||
writeRawVarint32(value);
|
||||
}
|
||||
|
||||
/** Write an {@code sfixed32} field to the stream. */
|
||||
public void writeSFixed32NoTag(int value) throws IOException {
|
||||
public void writeSFixed32NoTag(final int value) throws IOException {
|
||||
writeRawLittleEndian32(value);
|
||||
}
|
||||
|
||||
/** Write an {@code sfixed64} field to the stream. */
|
||||
public void writeSFixed64NoTag(long value) throws IOException {
|
||||
public void writeSFixed64NoTag(final long value) throws IOException {
|
||||
writeRawLittleEndian64(value);
|
||||
}
|
||||
|
||||
/** Write an {@code sint32} field to the stream. */
|
||||
public void writeSInt32NoTag(int value) throws IOException {
|
||||
public void writeSInt32NoTag(final int value) throws IOException {
|
||||
writeRawVarint32(encodeZigZag32(value));
|
||||
}
|
||||
|
||||
/** Write an {@code sint64} field to the stream. */
|
||||
public void writeSInt64NoTag(long value) throws IOException {
|
||||
public void writeSInt64NoTag(final long value) throws IOException {
|
||||
writeRawVarint64(encodeZigZag64(value));
|
||||
}
|
||||
|
||||
@ -438,7 +413,8 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code double} field, including tag.
|
||||
*/
|
||||
public static int computeDoubleSize(int fieldNumber, double value) {
|
||||
public static int computeDoubleSize(final int fieldNumber,
|
||||
final double value) {
|
||||
return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -446,7 +422,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code float} field, including tag.
|
||||
*/
|
||||
public static int computeFloatSize(int fieldNumber, float value) {
|
||||
public static int computeFloatSize(final int fieldNumber, final float value) {
|
||||
return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -454,7 +430,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code uint64} field, including tag.
|
||||
*/
|
||||
public static int computeUInt64Size(int fieldNumber, long value) {
|
||||
public static int computeUInt64Size(final int fieldNumber, final long value) {
|
||||
return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -462,7 +438,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode an
|
||||
* {@code int64} field, including tag.
|
||||
*/
|
||||
public static int computeInt64Size(int fieldNumber, long value) {
|
||||
public static int computeInt64Size(final int fieldNumber, final long value) {
|
||||
return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -470,7 +446,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode an
|
||||
* {@code int32} field, including tag.
|
||||
*/
|
||||
public static int computeInt32Size(int fieldNumber, int value) {
|
||||
public static int computeInt32Size(final int fieldNumber, final int value) {
|
||||
return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -478,7 +454,8 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code fixed64} field, including tag.
|
||||
*/
|
||||
public static int computeFixed64Size(int fieldNumber, long value) {
|
||||
public static int computeFixed64Size(final int fieldNumber,
|
||||
final long value) {
|
||||
return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -486,7 +463,8 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code fixed32} field, including tag.
|
||||
*/
|
||||
public static int computeFixed32Size(int fieldNumber, int value) {
|
||||
public static int computeFixed32Size(final int fieldNumber,
|
||||
final int value) {
|
||||
return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -494,7 +472,8 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code bool} field, including tag.
|
||||
*/
|
||||
public static int computeBoolSize(int fieldNumber, boolean value) {
|
||||
public static int computeBoolSize(final int fieldNumber,
|
||||
final boolean value) {
|
||||
return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -502,7 +481,8 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code string} field, including tag.
|
||||
*/
|
||||
public static int computeStringSize(int fieldNumber, String value) {
|
||||
public static int computeStringSize(final int fieldNumber,
|
||||
final String value) {
|
||||
return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -510,7 +490,8 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code group} field, including tag.
|
||||
*/
|
||||
public static int computeGroupSize(int fieldNumber, Message value) {
|
||||
public static int computeGroupSize(final int fieldNumber,
|
||||
final MessageLite value) {
|
||||
return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -518,18 +499,22 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code group} field represented by an {@code UnknownFieldSet}, including
|
||||
* tag.
|
||||
*
|
||||
* @deprecated UnknownFieldSet now implements MessageLite, so you can just
|
||||
* call {@link #computeGroupSize}.
|
||||
*/
|
||||
public static int computeUnknownGroupSize(int fieldNumber,
|
||||
UnknownFieldSet value) {
|
||||
return computeTagSize(fieldNumber) * 2 +
|
||||
computeUnknownGroupSizeNoTag(value);
|
||||
@Deprecated
|
||||
public static int computeUnknownGroupSize(final int fieldNumber,
|
||||
final MessageLite value) {
|
||||
return computeGroupSize(fieldNumber, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the number of bytes that would be needed to encode an
|
||||
* embedded message field, including tag.
|
||||
*/
|
||||
public static int computeMessageSize(int fieldNumber, Message value) {
|
||||
public static int computeMessageSize(final int fieldNumber,
|
||||
final MessageLite value) {
|
||||
return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -537,7 +522,8 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code bytes} field, including tag.
|
||||
*/
|
||||
public static int computeBytesSize(int fieldNumber, ByteString value) {
|
||||
public static int computeBytesSize(final int fieldNumber,
|
||||
final ByteString value) {
|
||||
return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -545,7 +531,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code uint32} field, including tag.
|
||||
*/
|
||||
public static int computeUInt32Size(int fieldNumber, int value) {
|
||||
public static int computeUInt32Size(final int fieldNumber, final int value) {
|
||||
return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -554,7 +540,7 @@ public final class CodedOutputStream {
|
||||
* enum field, including tag. Caller is responsible for converting the
|
||||
* enum value to its numeric value.
|
||||
*/
|
||||
public static int computeEnumSize(int fieldNumber, int value) {
|
||||
public static int computeEnumSize(final int fieldNumber, final int value) {
|
||||
return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -562,7 +548,8 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode an
|
||||
* {@code sfixed32} field, including tag.
|
||||
*/
|
||||
public static int computeSFixed32Size(int fieldNumber, int value) {
|
||||
public static int computeSFixed32Size(final int fieldNumber,
|
||||
final int value) {
|
||||
return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -570,7 +557,8 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode an
|
||||
* {@code sfixed64} field, including tag.
|
||||
*/
|
||||
public static int computeSFixed64Size(int fieldNumber, long value) {
|
||||
public static int computeSFixed64Size(final int fieldNumber,
|
||||
final long value) {
|
||||
return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -578,7 +566,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode an
|
||||
* {@code sint32} field, including tag.
|
||||
*/
|
||||
public static int computeSInt32Size(int fieldNumber, int value) {
|
||||
public static int computeSInt32Size(final int fieldNumber, final int value) {
|
||||
return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -586,7 +574,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode an
|
||||
* {@code sint64} field, including tag.
|
||||
*/
|
||||
public static int computeSInt64Size(int fieldNumber, long value) {
|
||||
public static int computeSInt64Size(final int fieldNumber, final long value) {
|
||||
return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
|
||||
}
|
||||
|
||||
@ -596,7 +584,7 @@ public final class CodedOutputStream {
|
||||
* the wire format differs from normal fields.
|
||||
*/
|
||||
public static int computeMessageSetExtensionSize(
|
||||
int fieldNumber, Message value) {
|
||||
final int fieldNumber, final MessageLite value) {
|
||||
return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 +
|
||||
computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) +
|
||||
computeMessageSize(WireFormat.MESSAGE_SET_MESSAGE, value);
|
||||
@ -608,7 +596,7 @@ public final class CodedOutputStream {
|
||||
* historical reasons, the wire format differs from normal fields.
|
||||
*/
|
||||
public static int computeRawMessageSetExtensionSize(
|
||||
int fieldNumber, ByteString value) {
|
||||
final int fieldNumber, final ByteString value) {
|
||||
return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2 +
|
||||
computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber) +
|
||||
computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value);
|
||||
@ -620,7 +608,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code double} field, including tag.
|
||||
*/
|
||||
public static int computeDoubleSizeNoTag(double value) {
|
||||
public static int computeDoubleSizeNoTag(final double value) {
|
||||
return LITTLE_ENDIAN_64_SIZE;
|
||||
}
|
||||
|
||||
@ -628,7 +616,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code float} field, including tag.
|
||||
*/
|
||||
public static int computeFloatSizeNoTag(float value) {
|
||||
public static int computeFloatSizeNoTag(final float value) {
|
||||
return LITTLE_ENDIAN_32_SIZE;
|
||||
}
|
||||
|
||||
@ -636,7 +624,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code uint64} field, including tag.
|
||||
*/
|
||||
public static int computeUInt64SizeNoTag(long value) {
|
||||
public static int computeUInt64SizeNoTag(final long value) {
|
||||
return computeRawVarint64Size(value);
|
||||
}
|
||||
|
||||
@ -644,7 +632,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode an
|
||||
* {@code int64} field, including tag.
|
||||
*/
|
||||
public static int computeInt64SizeNoTag(long value) {
|
||||
public static int computeInt64SizeNoTag(final long value) {
|
||||
return computeRawVarint64Size(value);
|
||||
}
|
||||
|
||||
@ -652,7 +640,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode an
|
||||
* {@code int32} field, including tag.
|
||||
*/
|
||||
public static int computeInt32SizeNoTag(int value) {
|
||||
public static int computeInt32SizeNoTag(final int value) {
|
||||
if (value >= 0) {
|
||||
return computeRawVarint32Size(value);
|
||||
} else {
|
||||
@ -665,7 +653,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code fixed64} field.
|
||||
*/
|
||||
public static int computeFixed64SizeNoTag(long value) {
|
||||
public static int computeFixed64SizeNoTag(final long value) {
|
||||
return LITTLE_ENDIAN_64_SIZE;
|
||||
}
|
||||
|
||||
@ -673,7 +661,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code fixed32} field.
|
||||
*/
|
||||
public static int computeFixed32SizeNoTag(int value) {
|
||||
public static int computeFixed32SizeNoTag(final int value) {
|
||||
return LITTLE_ENDIAN_32_SIZE;
|
||||
}
|
||||
|
||||
@ -681,7 +669,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code bool} field.
|
||||
*/
|
||||
public static int computeBoolSizeNoTag(boolean value) {
|
||||
public static int computeBoolSizeNoTag(final boolean value) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -689,12 +677,12 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code string} field.
|
||||
*/
|
||||
public static int computeStringSizeNoTag(String value) {
|
||||
public static int computeStringSizeNoTag(final String value) {
|
||||
try {
|
||||
byte[] bytes = value.getBytes("UTF-8");
|
||||
final byte[] bytes = value.getBytes("UTF-8");
|
||||
return computeRawVarint32Size(bytes.length) +
|
||||
bytes.length;
|
||||
} catch (java.io.UnsupportedEncodingException e) {
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("UTF-8 not supported.", e);
|
||||
}
|
||||
}
|
||||
@ -703,7 +691,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code group} field.
|
||||
*/
|
||||
public static int computeGroupSizeNoTag(Message value) {
|
||||
public static int computeGroupSizeNoTag(final MessageLite value) {
|
||||
return value.getSerializedSize();
|
||||
}
|
||||
|
||||
@ -711,17 +699,21 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code group} field represented by an {@code UnknownFieldSet}, including
|
||||
* tag.
|
||||
*
|
||||
* @deprecated UnknownFieldSet now implements MessageLite, so you can just
|
||||
* call {@link #computeUnknownGroupSizeNoTag}.
|
||||
*/
|
||||
public static int computeUnknownGroupSizeNoTag(UnknownFieldSet value) {
|
||||
return value.getSerializedSize();
|
||||
@Deprecated
|
||||
public static int computeUnknownGroupSizeNoTag(final MessageLite value) {
|
||||
return computeGroupSizeNoTag(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the number of bytes that would be needed to encode an embedded
|
||||
* message field.
|
||||
*/
|
||||
public static int computeMessageSizeNoTag(Message value) {
|
||||
int size = value.getSerializedSize();
|
||||
public static int computeMessageSizeNoTag(final MessageLite value) {
|
||||
final int size = value.getSerializedSize();
|
||||
return computeRawVarint32Size(size) + size;
|
||||
}
|
||||
|
||||
@ -729,7 +721,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code bytes} field.
|
||||
*/
|
||||
public static int computeBytesSizeNoTag(ByteString value) {
|
||||
public static int computeBytesSizeNoTag(final ByteString value) {
|
||||
return computeRawVarint32Size(value.size()) +
|
||||
value.size();
|
||||
}
|
||||
@ -738,15 +730,15 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* {@code uint32} field.
|
||||
*/
|
||||
public static int computeUInt32SizeNoTag(int value) {
|
||||
public static int computeUInt32SizeNoTag(final int value) {
|
||||
return computeRawVarint32Size(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the number of bytes that would be needed to encode an enum field.
|
||||
* Compute the number of bytes that would be needed to encode an enum field.
|
||||
* Caller is responsible for converting the enum value to its numeric value.
|
||||
*/
|
||||
public static int computeEnumSizeNoTag(int value) {
|
||||
public static int computeEnumSizeNoTag(final int value) {
|
||||
return computeRawVarint32Size(value);
|
||||
}
|
||||
|
||||
@ -754,7 +746,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode an
|
||||
* {@code sfixed32} field.
|
||||
*/
|
||||
public static int computeSFixed32SizeNoTag(int value) {
|
||||
public static int computeSFixed32SizeNoTag(final int value) {
|
||||
return LITTLE_ENDIAN_32_SIZE;
|
||||
}
|
||||
|
||||
@ -762,7 +754,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode an
|
||||
* {@code sfixed64} field.
|
||||
*/
|
||||
public static int computeSFixed64SizeNoTag(long value) {
|
||||
public static int computeSFixed64SizeNoTag(final long value) {
|
||||
return LITTLE_ENDIAN_64_SIZE;
|
||||
}
|
||||
|
||||
@ -770,7 +762,7 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode an
|
||||
* {@code sint32} field.
|
||||
*/
|
||||
public static int computeSInt32SizeNoTag(int value) {
|
||||
public static int computeSInt32SizeNoTag(final int value) {
|
||||
return computeRawVarint32Size(encodeZigZag32(value));
|
||||
}
|
||||
|
||||
@ -778,71 +770,10 @@ public final class CodedOutputStream {
|
||||
* Compute the number of bytes that would be needed to encode an
|
||||
* {@code sint64} field.
|
||||
*/
|
||||
public static int computeSInt64SizeNoTag(long value) {
|
||||
public static int computeSInt64SizeNoTag(final long value) {
|
||||
return computeRawVarint64Size(encodeZigZag64(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* field of arbitrary type, including tag, to the stream.
|
||||
*
|
||||
* @param type The field's type.
|
||||
* @param number The field's number.
|
||||
* @param value Object representing the field's value. Must be of the exact
|
||||
* type which would be returned by
|
||||
* {@link Message#getField(Descriptors.FieldDescriptor)} for
|
||||
* this field.
|
||||
*/
|
||||
public static int computeFieldSize(
|
||||
Descriptors.FieldDescriptor.Type type,
|
||||
int number, Object value) {
|
||||
int tagSize = computeTagSize(number);
|
||||
if (type == Descriptors.FieldDescriptor.Type.GROUP) {
|
||||
tagSize *= 2;
|
||||
}
|
||||
return tagSize + computeFieldSizeNoTag(type, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the number of bytes that would be needed to encode a
|
||||
* field of arbitrary type, excluding tag, to the stream.
|
||||
*
|
||||
* @param type The field's type.
|
||||
* @param value Object representing the field's value. Must be of the exact
|
||||
* type which would be returned by
|
||||
* {@link Message#getField(Descriptors.FieldDescriptor)} for
|
||||
* this field.
|
||||
*/
|
||||
public static int computeFieldSizeNoTag(
|
||||
Descriptors.FieldDescriptor.Type type, Object value) {
|
||||
switch (type) {
|
||||
case DOUBLE : return computeDoubleSizeNoTag ((Double )value);
|
||||
case FLOAT : return computeFloatSizeNoTag ((Float )value);
|
||||
case INT64 : return computeInt64SizeNoTag ((Long )value);
|
||||
case UINT64 : return computeUInt64SizeNoTag ((Long )value);
|
||||
case INT32 : return computeInt32SizeNoTag ((Integer )value);
|
||||
case FIXED64 : return computeFixed64SizeNoTag ((Long )value);
|
||||
case FIXED32 : return computeFixed32SizeNoTag ((Integer )value);
|
||||
case BOOL : return computeBoolSizeNoTag ((Boolean )value);
|
||||
case STRING : return computeStringSizeNoTag ((String )value);
|
||||
case GROUP : return computeGroupSizeNoTag ((Message )value);
|
||||
case MESSAGE : return computeMessageSizeNoTag ((Message )value);
|
||||
case BYTES : return computeBytesSizeNoTag ((ByteString)value);
|
||||
case UINT32 : return computeUInt32SizeNoTag ((Integer )value);
|
||||
case SFIXED32: return computeSFixed32SizeNoTag((Integer )value);
|
||||
case SFIXED64: return computeSFixed64SizeNoTag((Long )value);
|
||||
case SINT32 : return computeSInt32SizeNoTag ((Integer )value);
|
||||
case SINT64 : return computeSInt64SizeNoTag ((Long )value);
|
||||
|
||||
case ENUM:
|
||||
return computeEnumSizeNoTag(
|
||||
((Descriptors.EnumValueDescriptor)value).getNumber());
|
||||
}
|
||||
|
||||
throw new RuntimeException(
|
||||
"There is no way to get here, but the compiler thinks otherwise.");
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
|
||||
/**
|
||||
@ -905,6 +836,8 @@ public final class CodedOutputStream {
|
||||
* this exception will be thrown.
|
||||
*/
|
||||
public static class OutOfSpaceException extends IOException {
|
||||
private static final long serialVersionUID = -6947486886997889499L;
|
||||
|
||||
OutOfSpaceException() {
|
||||
super("CodedOutputStream was writing to a flat byte array and ran " +
|
||||
"out of space.");
|
||||
@ -912,7 +845,7 @@ public final class CodedOutputStream {
|
||||
}
|
||||
|
||||
/** Write a single byte. */
|
||||
public void writeRawByte(byte value) throws IOException {
|
||||
public void writeRawByte(final byte value) throws IOException {
|
||||
if (position == limit) {
|
||||
refreshBuffer();
|
||||
}
|
||||
@ -921,17 +854,17 @@ public final class CodedOutputStream {
|
||||
}
|
||||
|
||||
/** Write a single byte, represented by an integer value. */
|
||||
public void writeRawByte(int value) throws IOException {
|
||||
public void writeRawByte(final int value) throws IOException {
|
||||
writeRawByte((byte) value);
|
||||
}
|
||||
|
||||
/** Write an array of bytes. */
|
||||
public void writeRawBytes(byte[] value) throws IOException {
|
||||
public void writeRawBytes(final byte[] value) throws IOException {
|
||||
writeRawBytes(value, 0, value.length);
|
||||
}
|
||||
|
||||
/** Write part of an array of bytes. */
|
||||
public void writeRawBytes(byte[] value, int offset, int length)
|
||||
public void writeRawBytes(final byte[] value, int offset, int length)
|
||||
throws IOException {
|
||||
if (limit - position >= length) {
|
||||
// We have room in the current buffer.
|
||||
@ -940,7 +873,7 @@ public final class CodedOutputStream {
|
||||
} else {
|
||||
// Write extends past current buffer. Fill the rest of this buffer and
|
||||
// flush.
|
||||
int bytesWritten = limit - position;
|
||||
final int bytesWritten = limit - position;
|
||||
System.arraycopy(value, offset, buffer, position, bytesWritten);
|
||||
offset += bytesWritten;
|
||||
length -= bytesWritten;
|
||||
@ -962,12 +895,13 @@ public final class CodedOutputStream {
|
||||
}
|
||||
|
||||
/** Encode and write a tag. */
|
||||
public void writeTag(int fieldNumber, int wireType) throws IOException {
|
||||
public void writeTag(final int fieldNumber, final int wireType)
|
||||
throws IOException {
|
||||
writeRawVarint32(WireFormat.makeTag(fieldNumber, wireType));
|
||||
}
|
||||
|
||||
/** Compute the number of bytes that would be needed to encode a tag. */
|
||||
public static int computeTagSize(int fieldNumber) {
|
||||
public static int computeTagSize(final int fieldNumber) {
|
||||
return computeRawVarint32Size(WireFormat.makeTag(fieldNumber, 0));
|
||||
}
|
||||
|
||||
@ -992,7 +926,7 @@ public final class CodedOutputStream {
|
||||
* {@code value} is treated as unsigned, so it won't be sign-extended if
|
||||
* negative.
|
||||
*/
|
||||
public static int computeRawVarint32Size(int value) {
|
||||
public static int computeRawVarint32Size(final int value) {
|
||||
if ((value & (0xffffffff << 7)) == 0) return 1;
|
||||
if ((value & (0xffffffff << 14)) == 0) return 2;
|
||||
if ((value & (0xffffffff << 21)) == 0) return 3;
|
||||
@ -1014,7 +948,7 @@ public final class CodedOutputStream {
|
||||
}
|
||||
|
||||
/** Compute the number of bytes that would be needed to encode a varint. */
|
||||
public static int computeRawVarint64Size(long value) {
|
||||
public static int computeRawVarint64Size(final long value) {
|
||||
if ((value & (0xffffffffffffffffL << 7)) == 0) return 1;
|
||||
if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
|
||||
if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
|
||||
@ -1028,7 +962,7 @@ public final class CodedOutputStream {
|
||||
}
|
||||
|
||||
/** Write a little-endian 32-bit integer. */
|
||||
public void writeRawLittleEndian32(int value) throws IOException {
|
||||
public void writeRawLittleEndian32(final int value) throws IOException {
|
||||
writeRawByte((value ) & 0xFF);
|
||||
writeRawByte((value >> 8) & 0xFF);
|
||||
writeRawByte((value >> 16) & 0xFF);
|
||||
@ -1038,7 +972,7 @@ public final class CodedOutputStream {
|
||||
public static final int LITTLE_ENDIAN_32_SIZE = 4;
|
||||
|
||||
/** Write a little-endian 64-bit integer. */
|
||||
public void writeRawLittleEndian64(long value) throws IOException {
|
||||
public void writeRawLittleEndian64(final long value) throws IOException {
|
||||
writeRawByte((int)(value ) & 0xFF);
|
||||
writeRawByte((int)(value >> 8) & 0xFF);
|
||||
writeRawByte((int)(value >> 16) & 0xFF);
|
||||
@ -1061,7 +995,7 @@ public final class CodedOutputStream {
|
||||
* @return An unsigned 32-bit integer, stored in a signed int because
|
||||
* Java has no explicit unsigned support.
|
||||
*/
|
||||
public static int encodeZigZag32(int n) {
|
||||
public static int encodeZigZag32(final int n) {
|
||||
// Note: the right-shift must be arithmetic
|
||||
return (n << 1) ^ (n >> 31);
|
||||
}
|
||||
@ -1076,7 +1010,7 @@ public final class CodedOutputStream {
|
||||
* @return An unsigned 64-bit integer, stored in a signed int because
|
||||
* Java has no explicit unsigned support.
|
||||
*/
|
||||
public static long encodeZigZag64(long n) {
|
||||
public static long encodeZigZag64(final long n) {
|
||||
// Note: the right-shift must be arithmetic
|
||||
return (n << 1) ^ (n >> 63);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -45,14 +45,14 @@ import java.util.Map;
|
||||
*/
|
||||
public final class DynamicMessage extends AbstractMessage {
|
||||
private final Descriptor type;
|
||||
private final FieldSet fields;
|
||||
private final FieldSet<FieldDescriptor> fields;
|
||||
private final UnknownFieldSet unknownFields;
|
||||
private int memoizedSize = -1;
|
||||
|
||||
/**
|
||||
* Construct a {@code DynamicMessage} using the given {@code FieldSet}.
|
||||
*/
|
||||
private DynamicMessage(Descriptor type, FieldSet fields,
|
||||
private DynamicMessage(Descriptor type, FieldSet<FieldDescriptor> fields,
|
||||
UnknownFieldSet unknownFields) {
|
||||
this.type = type;
|
||||
this.fields = fields;
|
||||
@ -64,7 +64,7 @@ public final class DynamicMessage extends AbstractMessage {
|
||||
* given type.
|
||||
*/
|
||||
public static DynamicMessage getDefaultInstance(Descriptor type) {
|
||||
return new DynamicMessage(type, FieldSet.emptySet(),
|
||||
return new DynamicMessage(type, FieldSet.<FieldDescriptor>emptySet(),
|
||||
UnknownFieldSet.getDefaultInstance());
|
||||
}
|
||||
|
||||
@ -160,7 +160,11 @@ public final class DynamicMessage extends AbstractMessage {
|
||||
verifyContainingType(field);
|
||||
Object result = fields.getField(field);
|
||||
if (result == null) {
|
||||
result = getDefaultInstance(field.getMessageType());
|
||||
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
|
||||
result = getDefaultInstance(field.getMessageType());
|
||||
} else {
|
||||
result = field.getDefaultValue();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -179,15 +183,31 @@ public final class DynamicMessage extends AbstractMessage {
|
||||
return unknownFields;
|
||||
}
|
||||
|
||||
private static boolean isInitialized(Descriptor type,
|
||||
FieldSet<FieldDescriptor> fields) {
|
||||
// Check that all required fields are present.
|
||||
for (final FieldDescriptor field : type.getFields()) {
|
||||
if (field.isRequired()) {
|
||||
if (!fields.hasField(field)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check that embedded messages are initialized.
|
||||
return fields.isInitialized();
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return fields.isInitialized(type);
|
||||
return isInitialized(type, fields);
|
||||
}
|
||||
|
||||
public void writeTo(CodedOutputStream output) throws IOException {
|
||||
fields.writeTo(output);
|
||||
if (type.getOptions().getMessageSetWireFormat()) {
|
||||
fields.writeMessageSetTo(output);
|
||||
unknownFields.writeAsMessageSetTo(output);
|
||||
} else {
|
||||
fields.writeTo(output);
|
||||
unknownFields.writeTo(output);
|
||||
}
|
||||
}
|
||||
@ -196,10 +216,11 @@ public final class DynamicMessage extends AbstractMessage {
|
||||
int size = memoizedSize;
|
||||
if (size != -1) return size;
|
||||
|
||||
size = fields.getSerializedSize();
|
||||
if (type.getOptions().getMessageSetWireFormat()) {
|
||||
size = fields.getMessageSetSerializedSize();
|
||||
size += unknownFields.getSerializedSizeAsMessageSet();
|
||||
} else {
|
||||
size = fields.getSerializedSize();
|
||||
size += unknownFields.getSerializedSize();
|
||||
}
|
||||
|
||||
@ -230,7 +251,7 @@ public final class DynamicMessage extends AbstractMessage {
|
||||
*/
|
||||
public static final class Builder extends AbstractMessage.Builder<Builder> {
|
||||
private final Descriptor type;
|
||||
private FieldSet fields;
|
||||
private FieldSet<FieldDescriptor> fields;
|
||||
private UnknownFieldSet unknownFields;
|
||||
|
||||
/** Construct a {@code Builder} for the given type. */
|
||||
@ -244,25 +265,33 @@ public final class DynamicMessage extends AbstractMessage {
|
||||
// Implementation of Message.Builder interface.
|
||||
|
||||
public Builder clear() {
|
||||
if (fields == null) {
|
||||
throw new IllegalStateException("Cannot call clear() after build().");
|
||||
}
|
||||
fields.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder mergeFrom(Message other) {
|
||||
if (other.getDescriptorForType() != type) {
|
||||
throw new IllegalArgumentException(
|
||||
"mergeFrom(Message) can only merge messages of the same type.");
|
||||
if (other instanceof DynamicMessage) {
|
||||
// This should be somewhat faster than calling super.mergeFrom().
|
||||
DynamicMessage otherDynamicMessage = (DynamicMessage) other;
|
||||
if (otherDynamicMessage.type != type) {
|
||||
throw new IllegalArgumentException(
|
||||
"mergeFrom(Message) can only merge messages of the same type.");
|
||||
}
|
||||
fields.mergeFrom(otherDynamicMessage.fields);
|
||||
mergeUnknownFields(otherDynamicMessage.unknownFields);
|
||||
return this;
|
||||
} else {
|
||||
return super.mergeFrom(other);
|
||||
}
|
||||
|
||||
fields.mergeFrom(other);
|
||||
mergeUnknownFields(other.getUnknownFields());
|
||||
return this;
|
||||
}
|
||||
|
||||
public DynamicMessage build() {
|
||||
// If fields == null, we'll throw an appropriate exception later.
|
||||
if (fields != null && !isInitialized()) {
|
||||
throw new UninitializedMessageException(
|
||||
throw newUninitializedMessageException(
|
||||
new DynamicMessage(type, fields, unknownFields));
|
||||
}
|
||||
return buildPartial();
|
||||
@ -275,7 +304,7 @@ public final class DynamicMessage extends AbstractMessage {
|
||||
*/
|
||||
private DynamicMessage buildParsed() throws InvalidProtocolBufferException {
|
||||
if (!isInitialized()) {
|
||||
throw new UninitializedMessageException(
|
||||
throw newUninitializedMessageException(
|
||||
new DynamicMessage(type, fields, unknownFields))
|
||||
.asInvalidProtocolBufferException();
|
||||
}
|
||||
@ -302,17 +331,7 @@ public final class DynamicMessage extends AbstractMessage {
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return fields.isInitialized(type);
|
||||
}
|
||||
|
||||
public Builder mergeFrom(CodedInputStream input,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
throws IOException {
|
||||
UnknownFieldSet.Builder unknownFieldsBuilder =
|
||||
UnknownFieldSet.newBuilder(unknownFields);
|
||||
fields.mergeFrom(input, unknownFieldsBuilder, extensionRegistry, this);
|
||||
unknownFields = unknownFieldsBuilder.build();
|
||||
return this;
|
||||
return DynamicMessage.isInitialized(type, fields);
|
||||
}
|
||||
|
||||
public Descriptor getDescriptorForType() {
|
||||
@ -347,7 +366,11 @@ public final class DynamicMessage extends AbstractMessage {
|
||||
verifyContainingType(field);
|
||||
Object result = fields.getField(field);
|
||||
if (result == null) {
|
||||
result = getDefaultInstance(field.getMessageType());
|
||||
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
|
||||
result = getDefaultInstance(field.getMessageType());
|
||||
} else {
|
||||
result = field.getDefaultValue();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -84,18 +84,16 @@ import java.util.Map;
|
||||
* would be slow. Second, corrupt data would not be detected until first
|
||||
* access, at which point it would be much harder to deal with it. Third, it
|
||||
* could violate the expectation that message objects are immutable, since the
|
||||
* type provided could be any arbitrary message class. An unpriviledged user
|
||||
* type provided could be any arbitrary message class. An unprivileged user
|
||||
* could take advantage of this to inject a mutable object into a message
|
||||
* belonging to priviledged code and create mischief.
|
||||
* belonging to privileged code and create mischief.
|
||||
*
|
||||
* @author kenton@google.com Kenton Varda
|
||||
*/
|
||||
public final class ExtensionRegistry {
|
||||
public final class ExtensionRegistry extends ExtensionRegistryLite {
|
||||
/** Construct a new, empty instance. */
|
||||
public static ExtensionRegistry newInstance() {
|
||||
return new ExtensionRegistry(
|
||||
new HashMap<String, ExtensionInfo>(),
|
||||
new HashMap<DescriptorIntPair, ExtensionInfo>());
|
||||
return new ExtensionRegistry();
|
||||
}
|
||||
|
||||
/** Get the unmodifiable singleton empty instance. */
|
||||
@ -104,10 +102,9 @@ public final class ExtensionRegistry {
|
||||
}
|
||||
|
||||
/** Returns an unmodifiable view of the registry. */
|
||||
@Override
|
||||
public ExtensionRegistry getUnmodifiable() {
|
||||
return new ExtensionRegistry(
|
||||
Collections.unmodifiableMap(extensionsByName),
|
||||
Collections.unmodifiableMap(extensionsByNumber));
|
||||
return new ExtensionRegistry(this);
|
||||
}
|
||||
|
||||
/** A (Descriptor, Message) pair, returned by lookup methods. */
|
||||
@ -121,11 +118,12 @@ public final class ExtensionRegistry {
|
||||
*/
|
||||
public final Message defaultInstance;
|
||||
|
||||
private ExtensionInfo(FieldDescriptor descriptor) {
|
||||
private ExtensionInfo(final FieldDescriptor descriptor) {
|
||||
this.descriptor = descriptor;
|
||||
this.defaultInstance = null;
|
||||
defaultInstance = null;
|
||||
}
|
||||
private ExtensionInfo(FieldDescriptor descriptor, Message defaultInstance) {
|
||||
private ExtensionInfo(final FieldDescriptor descriptor,
|
||||
final Message defaultInstance) {
|
||||
this.descriptor = descriptor;
|
||||
this.defaultInstance = defaultInstance;
|
||||
}
|
||||
@ -139,7 +137,7 @@ public final class ExtensionRegistry {
|
||||
* @return Information about the extension if found, or {@code null}
|
||||
* otherwise.
|
||||
*/
|
||||
public ExtensionInfo findExtensionByName(String fullName) {
|
||||
public ExtensionInfo findExtensionByName(final String fullName) {
|
||||
return extensionsByName.get(fullName);
|
||||
}
|
||||
|
||||
@ -149,14 +147,14 @@ public final class ExtensionRegistry {
|
||||
* @return Information about the extension if found, or {@code null}
|
||||
* otherwise.
|
||||
*/
|
||||
public ExtensionInfo findExtensionByNumber(Descriptor containingType,
|
||||
int fieldNumber) {
|
||||
public ExtensionInfo findExtensionByNumber(final Descriptor containingType,
|
||||
final int fieldNumber) {
|
||||
return extensionsByNumber.get(
|
||||
new DescriptorIntPair(containingType, fieldNumber));
|
||||
}
|
||||
|
||||
/** Add an extension from a generated file to the registry. */
|
||||
public void add(GeneratedMessage.GeneratedExtension<?, ?> extension) {
|
||||
public void add(final GeneratedMessage.GeneratedExtension<?, ?> extension) {
|
||||
if (extension.getDescriptor().getJavaType() ==
|
||||
FieldDescriptor.JavaType.MESSAGE) {
|
||||
add(new ExtensionInfo(extension.getDescriptor(),
|
||||
@ -167,7 +165,7 @@ public final class ExtensionRegistry {
|
||||
}
|
||||
|
||||
/** Add a non-message-type extension to the registry by descriptor. */
|
||||
public void add(FieldDescriptor type) {
|
||||
public void add(final FieldDescriptor type) {
|
||||
if (type.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
|
||||
throw new IllegalArgumentException(
|
||||
"ExtensionRegistry.add() must be provided a default instance when " +
|
||||
@ -177,7 +175,7 @@ public final class ExtensionRegistry {
|
||||
}
|
||||
|
||||
/** Add a message-type extension to the registry by descriptor. */
|
||||
public void add(FieldDescriptor type, Message defaultInstance) {
|
||||
public void add(final FieldDescriptor type, final Message defaultInstance) {
|
||||
if (type.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
|
||||
throw new IllegalArgumentException(
|
||||
"ExtensionRegistry.add() provided a default instance for a " +
|
||||
@ -189,22 +187,30 @@ public final class ExtensionRegistry {
|
||||
// =================================================================
|
||||
// Private stuff.
|
||||
|
||||
private ExtensionRegistry(
|
||||
Map<String, ExtensionInfo> extensionsByName,
|
||||
Map<DescriptorIntPair, ExtensionInfo> extensionsByNumber) {
|
||||
this.extensionsByName = extensionsByName;
|
||||
this.extensionsByNumber = extensionsByNumber;
|
||||
private ExtensionRegistry() {
|
||||
this.extensionsByName = new HashMap<String, ExtensionInfo>();
|
||||
this.extensionsByNumber = new HashMap<DescriptorIntPair, ExtensionInfo>();
|
||||
}
|
||||
|
||||
private ExtensionRegistry(ExtensionRegistry other) {
|
||||
super(other);
|
||||
this.extensionsByName = Collections.unmodifiableMap(other.extensionsByName);
|
||||
this.extensionsByNumber =
|
||||
Collections.unmodifiableMap(other.extensionsByNumber);
|
||||
}
|
||||
|
||||
private final Map<String, ExtensionInfo> extensionsByName;
|
||||
private final Map<DescriptorIntPair, ExtensionInfo> extensionsByNumber;
|
||||
|
||||
private static final ExtensionRegistry EMPTY =
|
||||
new ExtensionRegistry(
|
||||
Collections.<String, ExtensionInfo>emptyMap(),
|
||||
Collections.<DescriptorIntPair, ExtensionInfo>emptyMap());
|
||||
private ExtensionRegistry(boolean empty) {
|
||||
super(ExtensionRegistryLite.getEmptyRegistry());
|
||||
this.extensionsByName = Collections.<String, ExtensionInfo>emptyMap();
|
||||
this.extensionsByNumber =
|
||||
Collections.<DescriptorIntPair, ExtensionInfo>emptyMap();
|
||||
}
|
||||
private static final ExtensionRegistry EMPTY = new ExtensionRegistry(true);
|
||||
|
||||
private void add(ExtensionInfo extension) {
|
||||
private void add(final ExtensionInfo extension) {
|
||||
if (!extension.descriptor.isExtension()) {
|
||||
throw new IllegalArgumentException(
|
||||
"ExtensionRegistry.add() was given a FieldDescriptor for a regular " +
|
||||
@ -217,7 +223,7 @@ public final class ExtensionRegistry {
|
||||
extension.descriptor.getNumber()),
|
||||
extension);
|
||||
|
||||
FieldDescriptor field = extension.descriptor;
|
||||
final FieldDescriptor field = extension.descriptor;
|
||||
if (field.getContainingType().getOptions().getMessageSetWireFormat() &&
|
||||
field.getType() == FieldDescriptor.Type.MESSAGE &&
|
||||
field.isOptional() &&
|
||||
@ -231,20 +237,24 @@ public final class ExtensionRegistry {
|
||||
|
||||
/** A (GenericDescriptor, int) pair, used as a map key. */
|
||||
private static final class DescriptorIntPair {
|
||||
final Descriptor descriptor;
|
||||
final int number;
|
||||
private final Descriptor descriptor;
|
||||
private final int number;
|
||||
|
||||
DescriptorIntPair(Descriptor descriptor, int number) {
|
||||
DescriptorIntPair(final Descriptor descriptor, final int number) {
|
||||
this.descriptor = descriptor;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return descriptor.hashCode() * ((1 << 16) - 1) + number;
|
||||
}
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof DescriptorIntPair)) return false;
|
||||
DescriptorIntPair other = (DescriptorIntPair)obj;
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (!(obj instanceof DescriptorIntPair)) {
|
||||
return false;
|
||||
}
|
||||
final DescriptorIntPair other = (DescriptorIntPair)obj;
|
||||
return descriptor == other.descriptor && number == other.number;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,169 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Equivalent to {@link ExtensionRegistry} but supports only "lite" types.
|
||||
* <p>
|
||||
* If all of your types are lite types, then you only need to use
|
||||
* {@code ExtensionRegistryLite}. Similarly, if all your types are regular
|
||||
* types, then you only need {@link ExtensionRegistry}. Typically it does not
|
||||
* make sense to mix the two, since if you have any regular types in your
|
||||
* program, you then require the full runtime and lose all the benefits of
|
||||
* the lite runtime, so you might as well make all your types be regular types.
|
||||
* However, in some cases (e.g. when depending on multiple third-patry libraries
|
||||
* where one uses lite types and one uses regular), you may find yourself
|
||||
* wanting to mix the two. In this case things get more complicated.
|
||||
* <p>
|
||||
* There are three factors to consider: Whether the type being extended is
|
||||
* lite, whether the embedded type (in the case of a message-typed extension)
|
||||
* is lite, and whether the extension itself is lite. Since all three are
|
||||
* declared in different files, they could all be different. Here are all
|
||||
* the combinations and which type of registry to use:
|
||||
* <pre>
|
||||
* Extended type Inner type Extension Use registry
|
||||
* =======================================================================
|
||||
* lite lite lite ExtensionRegistryLite
|
||||
* lite regular lite ExtensionRegistry
|
||||
* regular regular regular ExtensionRegistry
|
||||
* all other combinations not supported
|
||||
* </pre>
|
||||
* <p>
|
||||
* Note that just as regular types are not allowed to contain lite-type fields,
|
||||
* they are also not allowed to contain lite-type extensions. This is because
|
||||
* regular types must be fully accessible via reflection, which in turn means
|
||||
* that all the inner messages must also support reflection. On the other hand,
|
||||
* since regular types implement the entire lite interface, there is no problem
|
||||
* with embedding regular types inside lite types.
|
||||
*
|
||||
* @author kenton@google.com Kenton Varda
|
||||
*/
|
||||
public class ExtensionRegistryLite {
|
||||
/** Construct a new, empty instance. */
|
||||
public static ExtensionRegistryLite newInstance() {
|
||||
return new ExtensionRegistryLite();
|
||||
}
|
||||
|
||||
/** Get the unmodifiable singleton empty instance. */
|
||||
public static ExtensionRegistryLite getEmptyRegistry() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
/** Returns an unmodifiable view of the registry. */
|
||||
public ExtensionRegistryLite getUnmodifiable() {
|
||||
return new ExtensionRegistryLite(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an extension by containing type and field number.
|
||||
*
|
||||
* @return Information about the extension if found, or {@code null}
|
||||
* otherwise.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <ContainingType extends MessageLite>
|
||||
GeneratedMessageLite.GeneratedExtension<ContainingType, ?>
|
||||
findLiteExtensionByNumber(
|
||||
final ContainingType containingTypeDefaultInstance,
|
||||
final int fieldNumber) {
|
||||
return (GeneratedMessageLite.GeneratedExtension<ContainingType, ?>)
|
||||
extensionsByNumber.get(
|
||||
new ObjectIntPair(containingTypeDefaultInstance, fieldNumber));
|
||||
}
|
||||
|
||||
/** Add an extension from a lite generated file to the registry. */
|
||||
public final void add(
|
||||
final GeneratedMessageLite.GeneratedExtension<?, ?> extension) {
|
||||
extensionsByNumber.put(
|
||||
new ObjectIntPair(extension.getContainingTypeDefaultInstance(),
|
||||
extension.getNumber()),
|
||||
extension);
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Private stuff.
|
||||
|
||||
// Constructors are package-private so that ExtensionRegistry can subclass
|
||||
// this.
|
||||
|
||||
ExtensionRegistryLite() {
|
||||
this.extensionsByNumber =
|
||||
new HashMap<ObjectIntPair,
|
||||
GeneratedMessageLite.GeneratedExtension<?, ?>>();
|
||||
}
|
||||
|
||||
ExtensionRegistryLite(ExtensionRegistryLite other) {
|
||||
if (other == EMPTY) {
|
||||
this.extensionsByNumber = Collections.emptyMap();
|
||||
} else {
|
||||
this.extensionsByNumber =
|
||||
Collections.unmodifiableMap(other.extensionsByNumber);
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<ObjectIntPair,
|
||||
GeneratedMessageLite.GeneratedExtension<?, ?>>
|
||||
extensionsByNumber;
|
||||
|
||||
private ExtensionRegistryLite(boolean empty) {
|
||||
this.extensionsByNumber = Collections.emptyMap();
|
||||
}
|
||||
private static final ExtensionRegistryLite EMPTY =
|
||||
new ExtensionRegistryLite(true);
|
||||
|
||||
/** A (Object, int) pair, used as a map key. */
|
||||
private static final class ObjectIntPair {
|
||||
private final Object object;
|
||||
private final int number;
|
||||
|
||||
ObjectIntPair(final Object object, final int number) {
|
||||
this.object = object;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return System.identityHashCode(object) * ((1 << 16) - 1) + number;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (!(obj instanceof ObjectIntPair)) {
|
||||
return false;
|
||||
}
|
||||
final ObjectIntPair other = (ObjectIntPair)obj;
|
||||
return object == other.object && number == other.number;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
539
java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
Normal file
539
java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
Normal file
@ -0,0 +1,539 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Lite version of {@link GeneratedMessage}.
|
||||
*
|
||||
* @author kenton@google.com Kenton Varda
|
||||
*/
|
||||
public abstract class GeneratedMessageLite extends AbstractMessageLite {
|
||||
protected GeneratedMessageLite() {}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public abstract static class Builder<MessageType extends GeneratedMessageLite,
|
||||
BuilderType extends Builder>
|
||||
extends AbstractMessageLite.Builder<BuilderType> {
|
||||
protected Builder() {}
|
||||
|
||||
// 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() {
|
||||
throw new UnsupportedOperationException(
|
||||
"This is supposed to be overridden by subclasses.");
|
||||
}
|
||||
|
||||
/** All subclasses implement this. */
|
||||
public abstract BuilderType mergeFrom(MessageType message);
|
||||
|
||||
// Defined here for return type covariance.
|
||||
public abstract MessageType getDefaultInstanceForType();
|
||||
|
||||
/**
|
||||
* Get the message being built. We don't just pass this to the
|
||||
* constructor because it becomes null when build() is called.
|
||||
*/
|
||||
protected abstract MessageType internalGetResult();
|
||||
|
||||
/**
|
||||
* Called by subclasses to parse an unknown field.
|
||||
* @return {@code true} unless the tag is an end-group tag.
|
||||
*/
|
||||
protected boolean parseUnknownField(
|
||||
final CodedInputStream input,
|
||||
final ExtensionRegistryLite extensionRegistry,
|
||||
final int tag) throws IOException {
|
||||
return input.skipField(tag);
|
||||
}
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Extensions-related stuff
|
||||
|
||||
/**
|
||||
* Lite equivalent of {@link GeneratedMessage.ExtendableMessage}.
|
||||
*/
|
||||
public abstract static class ExtendableMessage<
|
||||
MessageType extends ExtendableMessage<MessageType>>
|
||||
extends GeneratedMessageLite {
|
||||
protected ExtendableMessage() {}
|
||||
private final FieldSet<ExtensionDescriptor> extensions =
|
||||
FieldSet.newFieldSet();
|
||||
|
||||
private void verifyExtensionContainingType(
|
||||
final GeneratedExtension<MessageType, ?> extension) {
|
||||
if (extension.getContainingTypeDefaultInstance() !=
|
||||
getDefaultInstanceForType()) {
|
||||
// This can only happen if someone uses unchecked operations.
|
||||
throw new IllegalArgumentException(
|
||||
"This extension is for a different message type. Please make " +
|
||||
"sure that you are not suppressing any generics type warnings.");
|
||||
}
|
||||
}
|
||||
|
||||
/** Check if a singular extension is present. */
|
||||
public final boolean hasExtension(
|
||||
final GeneratedExtension<MessageType, ?> extension) {
|
||||
verifyExtensionContainingType(extension);
|
||||
return extensions.hasField(extension.descriptor);
|
||||
}
|
||||
|
||||
/** Get the number of elements in a repeated extension. */
|
||||
public final <Type> int getExtensionCount(
|
||||
final GeneratedExtension<MessageType, List<Type>> extension) {
|
||||
verifyExtensionContainingType(extension);
|
||||
return extensions.getRepeatedFieldCount(extension.descriptor);
|
||||
}
|
||||
|
||||
/** Get the value of an extension. */
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <Type> Type getExtension(
|
||||
final GeneratedExtension<MessageType, Type> extension) {
|
||||
verifyExtensionContainingType(extension);
|
||||
final Object value = extensions.getField(extension.descriptor);
|
||||
if (value == null) {
|
||||
return extension.defaultValue;
|
||||
} else {
|
||||
return (Type) value;
|
||||
}
|
||||
}
|
||||
|
||||
/** Get one element of a repeated extension. */
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <Type> Type getExtension(
|
||||
final GeneratedExtension<MessageType, List<Type>> extension,
|
||||
final int index) {
|
||||
verifyExtensionContainingType(extension);
|
||||
return (Type) extensions.getRepeatedField(extension.descriptor, index);
|
||||
}
|
||||
|
||||
/** Called by subclasses to check if all extensions are initialized. */
|
||||
protected boolean extensionsAreInitialized() {
|
||||
return extensions.isInitialized();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by subclasses to serialize extensions. Extension ranges may be
|
||||
* interleaved with field numbers, but we must write them in canonical
|
||||
* (sorted by field number) order. ExtensionWriter helps us write
|
||||
* individual ranges of extensions at once.
|
||||
*/
|
||||
protected class ExtensionWriter {
|
||||
// Imagine how much simpler this code would be if Java iterators had
|
||||
// a way to get the next element without advancing the iterator.
|
||||
|
||||
private final Iterator<Map.Entry<ExtensionDescriptor, Object>> iter =
|
||||
extensions.iterator();
|
||||
private Map.Entry<ExtensionDescriptor, Object> next;
|
||||
private final boolean messageSetWireFormat;
|
||||
|
||||
private ExtensionWriter(boolean messageSetWireFormat) {
|
||||
if (iter.hasNext()) {
|
||||
next = iter.next();
|
||||
}
|
||||
this.messageSetWireFormat = messageSetWireFormat;
|
||||
}
|
||||
|
||||
public void writeUntil(final int end, final CodedOutputStream output)
|
||||
throws IOException {
|
||||
while (next != null && next.getKey().getNumber() < end) {
|
||||
ExtensionDescriptor extension = next.getKey();
|
||||
if (messageSetWireFormat && extension.getLiteJavaType() ==
|
||||
WireFormat.JavaType.MESSAGE &&
|
||||
!extension.isRepeated()) {
|
||||
output.writeMessageSetExtension(extension.getNumber(),
|
||||
(MessageLite) next.getValue());
|
||||
} else {
|
||||
FieldSet.writeField(extension, next.getValue(), output);
|
||||
}
|
||||
if (iter.hasNext()) {
|
||||
next = iter.next();
|
||||
} else {
|
||||
next = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected ExtensionWriter newExtensionWriter() {
|
||||
return new ExtensionWriter(false);
|
||||
}
|
||||
protected ExtensionWriter newMessageSetExtensionWriter() {
|
||||
return new ExtensionWriter(true);
|
||||
}
|
||||
|
||||
/** Called by subclasses to compute the size of extensions. */
|
||||
protected int extensionsSerializedSize() {
|
||||
return extensions.getSerializedSize();
|
||||
}
|
||||
protected int extensionsSerializedSizeAsMessageSet() {
|
||||
return extensions.getMessageSetSerializedSize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lite equivalent of {@link GeneratedMessage.ExtendableBuilder}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public abstract static class ExtendableBuilder<
|
||||
MessageType extends ExtendableMessage<MessageType>,
|
||||
BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
|
||||
extends Builder<MessageType, BuilderType> {
|
||||
protected ExtendableBuilder() {}
|
||||
|
||||
// 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() {
|
||||
throw new UnsupportedOperationException(
|
||||
"This is supposed to be overridden by subclasses.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected abstract MessageType internalGetResult();
|
||||
|
||||
/** Check if a singular extension is present. */
|
||||
public final boolean hasExtension(
|
||||
final GeneratedExtension<MessageType, ?> extension) {
|
||||
return internalGetResult().hasExtension(extension);
|
||||
}
|
||||
|
||||
/** Get the number of elements in a repeated extension. */
|
||||
public final <Type> int getExtensionCount(
|
||||
final GeneratedExtension<MessageType, List<Type>> extension) {
|
||||
return internalGetResult().getExtensionCount(extension);
|
||||
}
|
||||
|
||||
/** Get the value of an extension. */
|
||||
public final <Type> Type getExtension(
|
||||
final GeneratedExtension<MessageType, Type> extension) {
|
||||
return internalGetResult().getExtension(extension);
|
||||
}
|
||||
|
||||
/** Get one element of a repeated extension. */
|
||||
public final <Type> Type getExtension(
|
||||
final GeneratedExtension<MessageType, List<Type>> extension,
|
||||
final int index) {
|
||||
return internalGetResult().getExtension(extension, index);
|
||||
}
|
||||
|
||||
/** Set the value of an extension. */
|
||||
public final <Type> BuilderType setExtension(
|
||||
final GeneratedExtension<MessageType, Type> extension,
|
||||
final Type value) {
|
||||
final ExtendableMessage<MessageType> message = internalGetResult();
|
||||
message.verifyExtensionContainingType(extension);
|
||||
message.extensions.setField(extension.descriptor, value);
|
||||
return (BuilderType) this;
|
||||
}
|
||||
|
||||
/** Set the value of one element of a repeated extension. */
|
||||
public final <Type> BuilderType setExtension(
|
||||
final GeneratedExtension<MessageType, List<Type>> extension,
|
||||
final int index, final Type value) {
|
||||
final ExtendableMessage<MessageType> message = internalGetResult();
|
||||
message.verifyExtensionContainingType(extension);
|
||||
message.extensions.setRepeatedField(extension.descriptor, index, value);
|
||||
return (BuilderType) this;
|
||||
}
|
||||
|
||||
/** Append a value to a repeated extension. */
|
||||
public final <Type> BuilderType addExtension(
|
||||
final GeneratedExtension<MessageType, List<Type>> extension,
|
||||
final Type value) {
|
||||
final ExtendableMessage<MessageType> message = internalGetResult();
|
||||
message.verifyExtensionContainingType(extension);
|
||||
message.extensions.addRepeatedField(extension.descriptor, value);
|
||||
return (BuilderType) this;
|
||||
}
|
||||
|
||||
/** Clear an extension. */
|
||||
public final <Type> BuilderType clearExtension(
|
||||
final GeneratedExtension<MessageType, ?> extension) {
|
||||
final ExtendableMessage<MessageType> message = internalGetResult();
|
||||
message.verifyExtensionContainingType(extension);
|
||||
message.extensions.clearField(extension.descriptor);
|
||||
return (BuilderType) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by subclasses to parse an unknown field or an extension.
|
||||
* @return {@code true} unless the tag is an end-group tag.
|
||||
*/
|
||||
@Override
|
||||
protected boolean parseUnknownField(
|
||||
final CodedInputStream input,
|
||||
final ExtensionRegistryLite extensionRegistry,
|
||||
final int tag) throws IOException {
|
||||
final FieldSet<ExtensionDescriptor> extensions =
|
||||
internalGetResult().extensions;
|
||||
|
||||
final int wireType = WireFormat.getTagWireType(tag);
|
||||
final int fieldNumber = WireFormat.getTagFieldNumber(tag);
|
||||
|
||||
final GeneratedExtension<MessageType, ?> extension =
|
||||
extensionRegistry.findLiteExtensionByNumber(
|
||||
getDefaultInstanceForType(), fieldNumber);
|
||||
|
||||
if (extension == null || wireType !=
|
||||
FieldSet.getWireFormatForFieldType(
|
||||
extension.descriptor.getLiteType(),
|
||||
extension.descriptor.isPacked())) {
|
||||
// Unknown field or wrong wire type. Skip.
|
||||
return input.skipField(tag);
|
||||
}
|
||||
|
||||
if (extension.descriptor.isPacked()) {
|
||||
final int length = input.readRawVarint32();
|
||||
final int limit = input.pushLimit(length);
|
||||
if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
|
||||
while (input.getBytesUntilLimit() > 0) {
|
||||
final int rawValue = input.readEnum();
|
||||
final Object value =
|
||||
extension.descriptor.getEnumType().findValueByNumber(rawValue);
|
||||
if (value == null) {
|
||||
// If the number isn't recognized as a valid value for this
|
||||
// enum, drop it (don't even add it to unknownFields).
|
||||
return true;
|
||||
}
|
||||
extensions.addRepeatedField(extension.descriptor, value);
|
||||
}
|
||||
} else {
|
||||
while (input.getBytesUntilLimit() > 0) {
|
||||
final Object value =
|
||||
FieldSet.readPrimitiveField(input,
|
||||
extension.descriptor.getLiteType());
|
||||
extensions.addRepeatedField(extension.descriptor, value);
|
||||
}
|
||||
}
|
||||
input.popLimit(limit);
|
||||
} else {
|
||||
final Object value;
|
||||
switch (extension.descriptor.getLiteJavaType()) {
|
||||
case MESSAGE: {
|
||||
MessageLite.Builder subBuilder = null;
|
||||
if (!extension.descriptor.isRepeated()) {
|
||||
MessageLite existingValue =
|
||||
(MessageLite) extensions.getField(extension.descriptor);
|
||||
if (existingValue != null) {
|
||||
subBuilder = existingValue.toBuilder();
|
||||
}
|
||||
}
|
||||
if (subBuilder == null) {
|
||||
subBuilder = extension.messageDefaultInstance.newBuilderForType();
|
||||
}
|
||||
if (extension.descriptor.getLiteType() ==
|
||||
WireFormat.FieldType.GROUP) {
|
||||
input.readGroup(extension.getNumber(),
|
||||
subBuilder, extensionRegistry);
|
||||
} else {
|
||||
input.readMessage(subBuilder, extensionRegistry);
|
||||
}
|
||||
value = subBuilder.build();
|
||||
break;
|
||||
}
|
||||
case ENUM:
|
||||
final int rawValue = input.readEnum();
|
||||
value = extension.descriptor.getEnumType()
|
||||
.findValueByNumber(rawValue);
|
||||
// If the number isn't recognized as a valid value for this enum,
|
||||
// drop it.
|
||||
if (value == null) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
value = FieldSet.readPrimitiveField(input,
|
||||
extension.descriptor.getLiteType());
|
||||
break;
|
||||
}
|
||||
|
||||
if (extension.descriptor.isRepeated()) {
|
||||
extensions.addRepeatedField(extension.descriptor, value);
|
||||
} else {
|
||||
extensions.setField(extension.descriptor, value);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected final void mergeExtensionFields(final MessageType other) {
|
||||
internalGetResult().extensions.mergeFrom(other.extensions);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
/** For use by generated code only. */
|
||||
public static <ContainingType extends MessageLite, Type>
|
||||
GeneratedExtension<ContainingType, Type>
|
||||
newGeneratedExtension(
|
||||
final ContainingType containingTypeDefaultInstance,
|
||||
final Type defaultValue,
|
||||
final MessageLite messageDefaultInstance,
|
||||
final Internal.EnumLiteMap<?> enumTypeMap,
|
||||
final int number,
|
||||
final WireFormat.FieldType type) {
|
||||
return new GeneratedExtension<ContainingType, Type>(
|
||||
containingTypeDefaultInstance, defaultValue, messageDefaultInstance,
|
||||
new ExtensionDescriptor(enumTypeMap, number, type,
|
||||
false /* isRepeated */, false /* isPacked */));
|
||||
}
|
||||
|
||||
/** For use by generated code only. */
|
||||
public static <ContainingType extends MessageLite, Type>
|
||||
GeneratedExtension<ContainingType, List<Type>>
|
||||
newRepeatedGeneratedExtension(
|
||||
final ContainingType containingTypeDefaultInstance,
|
||||
final MessageLite messageDefaultInstance,
|
||||
final Internal.EnumLiteMap<?> enumTypeMap,
|
||||
final int number,
|
||||
final WireFormat.FieldType type,
|
||||
final boolean isPacked) {
|
||||
return new GeneratedExtension<ContainingType, List<Type>>(
|
||||
containingTypeDefaultInstance, Collections.<Type>emptyList(),
|
||||
messageDefaultInstance,
|
||||
new ExtensionDescriptor(
|
||||
enumTypeMap, number, type, true /* isRepeated */, isPacked));
|
||||
}
|
||||
|
||||
private static final class ExtensionDescriptor
|
||||
implements FieldSet.FieldDescriptorLite<
|
||||
ExtensionDescriptor> {
|
||||
private ExtensionDescriptor(
|
||||
final Internal.EnumLiteMap<?> enumTypeMap,
|
||||
final int number,
|
||||
final WireFormat.FieldType type,
|
||||
final boolean isRepeated,
|
||||
final boolean isPacked) {
|
||||
this.enumTypeMap = enumTypeMap;
|
||||
this.number = number;
|
||||
this.type = type;
|
||||
this.isRepeated = isRepeated;
|
||||
this.isPacked = isPacked;
|
||||
}
|
||||
|
||||
private final Internal.EnumLiteMap<?> enumTypeMap;
|
||||
private final int number;
|
||||
private final WireFormat.FieldType type;
|
||||
private final boolean isRepeated;
|
||||
private final boolean isPacked;
|
||||
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public WireFormat.FieldType getLiteType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public WireFormat.JavaType getLiteJavaType() {
|
||||
return type.getJavaType();
|
||||
}
|
||||
|
||||
public boolean isRepeated() {
|
||||
return isRepeated;
|
||||
}
|
||||
|
||||
public boolean isPacked() {
|
||||
return isPacked;
|
||||
}
|
||||
|
||||
public Internal.EnumLiteMap<?> getEnumType() {
|
||||
return enumTypeMap;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public MessageLite.Builder internalMergeFrom(
|
||||
MessageLite.Builder to, MessageLite from) {
|
||||
return ((Builder) to).mergeFrom((GeneratedMessageLite) from);
|
||||
}
|
||||
|
||||
public int compareTo(ExtensionDescriptor other) {
|
||||
return number - other.number;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lite equivalent to {@link GeneratedMessage.GeneratedExtension}.
|
||||
*
|
||||
* Users should ignore the contents of this class and only use objects of
|
||||
* this type as parameters to extension accessors and ExtensionRegistry.add().
|
||||
*/
|
||||
public static final class GeneratedExtension<
|
||||
ContainingType extends MessageLite, Type> {
|
||||
private GeneratedExtension(
|
||||
final ContainingType containingTypeDefaultInstance,
|
||||
final Type defaultValue,
|
||||
final MessageLite messageDefaultInstance,
|
||||
final ExtensionDescriptor descriptor) {
|
||||
this.containingTypeDefaultInstance = containingTypeDefaultInstance;
|
||||
this.defaultValue = defaultValue;
|
||||
this.messageDefaultInstance = messageDefaultInstance;
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
private final ContainingType containingTypeDefaultInstance;
|
||||
private final Type defaultValue;
|
||||
private final MessageLite messageDefaultInstance;
|
||||
private final ExtensionDescriptor descriptor;
|
||||
|
||||
/**
|
||||
* Default instance of the type being extended, used to identify that type.
|
||||
*/
|
||||
public ContainingType getContainingTypeDefaultInstance() {
|
||||
return containingTypeDefaultInstance;
|
||||
}
|
||||
|
||||
/** Get the field number. */
|
||||
public int getNumber() {
|
||||
return descriptor.getNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the extension is an embedded message, this is the default instance of
|
||||
* that type.
|
||||
*/
|
||||
public MessageLite getMessageDefaultInstance() {
|
||||
return messageDefaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
194
java/src/main/java/com/google/protobuf/Internal.java
Normal file
194
java/src/main/java/com/google/protobuf/Internal.java
Normal file
@ -0,0 +1,194 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
/**
|
||||
* The classes contained within are used internally by the Protocol Buffer
|
||||
* library and generated message implementations. They are public only because
|
||||
* those generated messages do not reside in the {@code protobuf} package.
|
||||
* Others should not use this class directly.
|
||||
*
|
||||
* @author cyrusn@google.com (Cyrus Najmabadi)
|
||||
*/
|
||||
public class Internal {
|
||||
/**
|
||||
* Implementation of a Queue designed to have as little overhead as possible.
|
||||
* No guarantees are made as to the order you will get values back from the
|
||||
* queue. Currently it is a Last-In-First-Out implementation, but that may
|
||||
* change in the future.
|
||||
*
|
||||
* Duplicate values are allowed, as are null values.
|
||||
*
|
||||
* Not threadsafe.
|
||||
*
|
||||
* @author cyrusn@google.com (Cyrus Najmabadi)
|
||||
*/
|
||||
public static final class QuickQueue<T> {
|
||||
@SuppressWarnings("unchecked")
|
||||
private T[] array = (T[]) new Object[16];
|
||||
private int size;
|
||||
|
||||
/**
|
||||
* Adds a value to the queue.
|
||||
*
|
||||
* @param value The value to add to the queue.
|
||||
*/
|
||||
public void offer(final T value) {
|
||||
if (size == array.length) {
|
||||
// I'd like to use Arrays.copy here. However, it is currently
|
||||
// unavailable
|
||||
// on android. So, for now, we just use the tried and true arraycopy
|
||||
// technique.
|
||||
@SuppressWarnings("unchecked")
|
||||
final T[] copy = (T[]) new Object[size * 2];
|
||||
System.arraycopy(array, 0, copy, 0, array.length);
|
||||
array = copy;
|
||||
}
|
||||
|
||||
array[size++] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes some previously added value to the queue, or {@code null} if the
|
||||
* queue is empty.
|
||||
*
|
||||
* @return An existing value in the queue, or {@code null} if the queue is
|
||||
* empty.
|
||||
*/
|
||||
public T poll() {
|
||||
if (size == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final T result = array[--size];
|
||||
// make sure we null out the entry so that we're not keeping anything
|
||||
// alive unnecessarily.
|
||||
array[size] = null;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instances of this class will provide a unique {@code QuickQueue} to each
|
||||
* thread that accesses it. Very useful for providing free lists without
|
||||
* needing to take any locks.
|
||||
*
|
||||
* @author cyrusn@google.com (Cyrus Najmabadi)
|
||||
*/
|
||||
public static final class ThreadLocalQuickQueue<T>
|
||||
extends ThreadLocal<QuickQueue<T>> {
|
||||
@Override
|
||||
protected QuickQueue<T> initialValue() {
|
||||
return new QuickQueue<T>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper called by generated code to construct default values for string
|
||||
* fields.
|
||||
* <p>
|
||||
* The protocol compiler does not actually contain a UTF-8 decoder -- it
|
||||
* just pushes UTF-8-encoded text around without touching it. The one place
|
||||
* where this presents a problem is when generating Java string literals.
|
||||
* Unicode characters in the string literal would normally need to be encoded
|
||||
* using a Unicode escape sequence, which would require decoding them.
|
||||
* To get around this, protoc instead embeds the UTF-8 bytes into the
|
||||
* generated code and leaves it to the runtime library to decode them.
|
||||
* <p>
|
||||
* It gets worse, though. If protoc just generated a byte array, like:
|
||||
* new byte[] {0x12, 0x34, 0x56, 0x78}
|
||||
* Java actually generates *code* which allocates an array and then fills
|
||||
* in each value. This is much less efficient than just embedding the bytes
|
||||
* directly into the bytecode. To get around this, we need another
|
||||
* work-around. String literals are embedded directly, so protoc actually
|
||||
* generates a string literal corresponding to the bytes. The easiest way
|
||||
* to do this is to use the ISO-8859-1 character set, which corresponds to
|
||||
* the first 256 characters of the Unicode range. Protoc can then use
|
||||
* good old CEscape to generate the string.
|
||||
* <p>
|
||||
* So we have a string literal which represents a set of bytes which
|
||||
* represents another string. This function -- stringDefaultValue --
|
||||
* converts from the generated string to the string we actually want. The
|
||||
* generated code calls this automatically.
|
||||
*/
|
||||
public static String stringDefaultValue(String bytes) {
|
||||
try {
|
||||
return new String(bytes.getBytes("ISO-8859-1"), "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// This should never happen since all JVMs are required to implement
|
||||
// both of the above character sets.
|
||||
throw new IllegalStateException(
|
||||
"Java VM does not support a standard character set.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper called by generated code to construct default values for bytes
|
||||
* fields.
|
||||
* <p>
|
||||
* This is a lot like {@link #stringDefaultValue}, but for bytes fields.
|
||||
* In this case we only need the second of the two hacks -- allowing us to
|
||||
* embed raw bytes as a string literal with ISO-8859-1 encoding.
|
||||
*/
|
||||
public static ByteString bytesDefaultValue(String bytes) {
|
||||
try {
|
||||
return ByteString.copyFrom(bytes.getBytes("ISO-8859-1"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// This should never happen since all JVMs are required to implement
|
||||
// ISO-8859-1.
|
||||
throw new IllegalStateException(
|
||||
"Java VM does not support a standard character set.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for an enum value or value descriptor, to be used in FieldSet.
|
||||
* The lite library stores enum values directly in FieldSets but the full
|
||||
* library stores EnumValueDescriptors in order to better support reflection.
|
||||
*/
|
||||
public interface EnumLite {
|
||||
int getNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for an object which maps integers to {@link EnumLite}s.
|
||||
* {@link Descriptors.EnumDescriptor} implements this interface by mapping
|
||||
* numbers to {@link Descriptors.EnumValueDescriptor}s. Additionally,
|
||||
* every generated enum type has a static method internalGetValueMap() which
|
||||
* returns an implementation of this type that maps numbers to enum values.
|
||||
*/
|
||||
public interface EnumLiteMap<T extends EnumLite> {
|
||||
T findValueByNumber(int number);
|
||||
}
|
||||
}
|
@ -39,7 +39,9 @@ import java.io.IOException;
|
||||
* @author kenton@google.com Kenton Varda
|
||||
*/
|
||||
public class InvalidProtocolBufferException extends IOException {
|
||||
public InvalidProtocolBufferException(String description) {
|
||||
private static final long serialVersionUID = -1616151763072450476L;
|
||||
|
||||
public InvalidProtocolBufferException(final String description) {
|
||||
super(description);
|
||||
}
|
||||
|
||||
|
@ -33,17 +33,22 @@
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Abstract interface implemented by Protocol Message objects.
|
||||
* <p>
|
||||
* See also {@link MessageLite}, which defines most of the methods that typical
|
||||
* users care about. {@link Message} adds to it methods that are not available
|
||||
* in the "lite" runtime. The biggest added features are introspection and
|
||||
* reflection -- i.e., getting descriptors for the message type and accessing
|
||||
* the field values dynamically.
|
||||
*
|
||||
* @author kenton@google.com Kenton Varda
|
||||
*/
|
||||
public interface Message {
|
||||
public interface Message extends MessageLite {
|
||||
/**
|
||||
* Get the message's type's descriptor. This differs from the
|
||||
* {@code getDescriptor()} method of generated message classes in that
|
||||
@ -53,14 +58,7 @@ public interface Message {
|
||||
*/
|
||||
Descriptors.Descriptor getDescriptorForType();
|
||||
|
||||
/**
|
||||
* Get an instance of the type with all fields set to their default values.
|
||||
* This may or may not be a singleton. This differs from the
|
||||
* {@code getDefaultInstance()} method of generated message classes in that
|
||||
* this method is an abstract method of the {@code Message} interface
|
||||
* whereas {@code getDefaultInstance()} is a static method of a specific
|
||||
* class. They return the same thing.
|
||||
*/
|
||||
// (From MessageLite, re-declared here only for return type covariance.)
|
||||
Message getDefaultInstanceForType();
|
||||
|
||||
/**
|
||||
@ -114,24 +112,6 @@ public interface Message {
|
||||
/** Get the {@link UnknownFieldSet} for this message. */
|
||||
UnknownFieldSet getUnknownFields();
|
||||
|
||||
/**
|
||||
* Returns true if all required fields in the message and all embedded
|
||||
* messages are set, false otherwise.
|
||||
*/
|
||||
boolean isInitialized();
|
||||
|
||||
/**
|
||||
* Serializes the message and writes it to {@code output}. This does not
|
||||
* flush or close the stream.
|
||||
*/
|
||||
void writeTo(CodedOutputStream output) throws IOException;
|
||||
|
||||
/**
|
||||
* Get the number of bytes required to encode this message. The result
|
||||
* is only computed on the first call and memoized after that.
|
||||
*/
|
||||
int getSerializedSize();
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Comparison and hashing
|
||||
|
||||
@ -144,6 +124,7 @@ public interface Message {
|
||||
* @param other object to be compared for equality with this message
|
||||
* @return <tt>true</tt> if the specified object is equal to this message
|
||||
*/
|
||||
@Override
|
||||
boolean equals(Object other);
|
||||
|
||||
/**
|
||||
@ -154,6 +135,7 @@ public interface Message {
|
||||
* @return the hash code value for this message
|
||||
* @see Map#hashCode()
|
||||
*/
|
||||
@Override
|
||||
int hashCode();
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
@ -163,67 +145,22 @@ public interface Message {
|
||||
* Converts the message to a string in protocol buffer text format. This is
|
||||
* just a trivial wrapper around {@link TextFormat#printToString(Message)}.
|
||||
*/
|
||||
@Override
|
||||
String toString();
|
||||
|
||||
/**
|
||||
* Serializes the message to a {@code ByteString} and returns it. This is
|
||||
* just a trivial wrapper around
|
||||
* {@link #writeTo(CodedOutputStream)}.
|
||||
*/
|
||||
ByteString toByteString();
|
||||
|
||||
/**
|
||||
* Serializes the message to a {@code byte} array and returns it. This is
|
||||
* just a trivial wrapper around
|
||||
* {@link #writeTo(CodedOutputStream)}.
|
||||
*/
|
||||
byte[] toByteArray();
|
||||
|
||||
/**
|
||||
* Serializes the message and writes it to {@code output}. This is just a
|
||||
* trivial wrapper around {@link #writeTo(CodedOutputStream)}. This does
|
||||
* not flush or close the stream.
|
||||
* <p>
|
||||
* NOTE: Protocol Buffers are not self-delimiting. Therefore, if you write
|
||||
* any more data to the stream after the message, you must somehow ensure
|
||||
* that the parser on the receiving end does not interpret this as being
|
||||
* part of the protocol message. This can be done e.g. by writing the size
|
||||
* of the message before the data, then making sure to limit the input to
|
||||
* that size on the receiving end (e.g. by wrapping the InputStream in one
|
||||
* which limits the input). Alternatively, just use
|
||||
* {@link #writeDelimitedTo(OutputStream)}.
|
||||
*/
|
||||
void writeTo(OutputStream output) throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #writeTo(OutputStream)}, but writes the size of the message
|
||||
* as a varint before writing the data. This allows more data to be written
|
||||
* to the stream after the message without the need to delimit the message
|
||||
* data yourself. Use {@link Builder#mergeDelimitedFrom(InputStream)} (or
|
||||
* the static method {@code YourMessageType.parseDelimitedFrom(InputStream)})
|
||||
* to parse messages written by this method.
|
||||
*/
|
||||
void writeDelimitedTo(OutputStream output) throws IOException;
|
||||
|
||||
// =================================================================
|
||||
// Builders
|
||||
|
||||
/**
|
||||
* Constructs a new builder for a message of the same type as this message.
|
||||
*/
|
||||
// (From MessageLite, re-declared here only for return type covariance.)
|
||||
Builder newBuilderForType();
|
||||
|
||||
/**
|
||||
* Constructs a builder initialized with the current message. Use this to
|
||||
* derive a new message from the current one.
|
||||
*/
|
||||
Builder toBuilder();
|
||||
|
||||
/**
|
||||
* Abstract interface implemented by Protocol Message builders.
|
||||
*/
|
||||
public static interface Builder extends Cloneable {
|
||||
/** Resets all fields to their default values. */
|
||||
interface Builder extends MessageLite.Builder {
|
||||
// (From MessageLite.Builder, re-declared here only for return type
|
||||
// covariance.)
|
||||
Builder clear();
|
||||
|
||||
/**
|
||||
@ -244,71 +181,14 @@ public interface Message {
|
||||
*/
|
||||
Builder mergeFrom(Message other);
|
||||
|
||||
/**
|
||||
* Construct the final message. Once this is called, the Builder is no
|
||||
* longer valid, and calling any other method may throw a
|
||||
* NullPointerException. If you need to continue working with the builder
|
||||
* after calling {@code build()}, {@code clone()} it first.
|
||||
* @throws UninitializedMessageException The message is missing one or more
|
||||
* required fields (i.e. {@link #isInitialized()} returns false).
|
||||
* Use {@link #buildPartial()} to bypass this check.
|
||||
*/
|
||||
// (From MessageLite.Builder, re-declared here only for return type
|
||||
// covariance.)
|
||||
Message build();
|
||||
|
||||
/**
|
||||
* Like {@link #build()}, but does not throw an exception if the message
|
||||
* is missing required fields. Instead, a partial message is returned.
|
||||
*/
|
||||
Message buildPartial();
|
||||
|
||||
/**
|
||||
* Clones the Builder.
|
||||
* @see Object#clone()
|
||||
*/
|
||||
Builder clone();
|
||||
|
||||
/**
|
||||
* Returns true if all required fields in the message and all embedded
|
||||
* messages are set, false otherwise.
|
||||
*/
|
||||
boolean isInitialized();
|
||||
|
||||
/**
|
||||
* Parses a message of this type from the input and merges it with this
|
||||
* message, as if using {@link Builder#mergeFrom(Message)}.
|
||||
*
|
||||
* <p>Warning: This does not verify that all required fields are present in
|
||||
* the input message. If you call {@link #build()} without setting all
|
||||
* required fields, it will throw an {@link UninitializedMessageException},
|
||||
* which is a {@code RuntimeException} and thus might not be caught. There
|
||||
* are a few good ways to deal with this:
|
||||
* <ul>
|
||||
* <li>Call {@link #isInitialized()} to verify that all required fields
|
||||
* are set before building.
|
||||
* <li>Parse the message separately using one of the static
|
||||
* {@code parseFrom} methods, then use {@link #mergeFrom(Message)}
|
||||
* to merge it with this one. {@code parseFrom} will throw an
|
||||
* {@link InvalidProtocolBufferException} (an {@code IOException})
|
||||
* if some required fields are missing.
|
||||
* <li>Use {@code buildPartial()} to build, which ignores missing
|
||||
* required fields.
|
||||
* </ul>
|
||||
*
|
||||
* <p>Note: The caller should call
|
||||
* {@link CodedInputStream#checkLastTagWas(int)} after calling this to
|
||||
* verify that the last tag seen was the appropriate end-group tag,
|
||||
* or zero for EOF.
|
||||
*/
|
||||
Builder mergeFrom(CodedInputStream input) throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link Builder#mergeFrom(CodedInputStream)}, but also
|
||||
* parses extensions. The extensions that you want to be able to parse
|
||||
* must be registered in {@code extensionRegistry}. Extensions not in
|
||||
* the registry will be treated as unknown fields.
|
||||
*/
|
||||
Builder mergeFrom(CodedInputStream input,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
@ -317,10 +197,8 @@ public interface Message {
|
||||
*/
|
||||
Descriptors.Descriptor getDescriptorForType();
|
||||
|
||||
/**
|
||||
* Get the message's type's default instance.
|
||||
* See {@link Message#getDefaultInstanceForType()}.
|
||||
*/
|
||||
// (From MessageLite.Builder, re-declared here only for return type
|
||||
// covariance.)
|
||||
Message getDefaultInstanceForType();
|
||||
|
||||
/**
|
||||
@ -399,92 +277,29 @@ public interface Message {
|
||||
// ---------------------------------------------------------------
|
||||
// Convenience methods.
|
||||
|
||||
/**
|
||||
* Parse {@code data} as a message of this type and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream)}.
|
||||
*/
|
||||
// (From MessageLite.Builder, re-declared here only for return type
|
||||
// covariance.)
|
||||
Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
|
||||
|
||||
/**
|
||||
* Parse {@code data} as a message of this type and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
|
||||
*/
|
||||
Builder mergeFrom(ByteString data,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException;
|
||||
Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
|
||||
Builder mergeFrom(byte[] data, int off, int len)
|
||||
throws InvalidProtocolBufferException;
|
||||
|
||||
/**
|
||||
* Parse {@code data} as a message of this type and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream)}.
|
||||
*/
|
||||
public Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
|
||||
|
||||
/**
|
||||
* Parse {@code data} as a message of this type and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream)}.
|
||||
*/
|
||||
public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException;
|
||||
|
||||
/**
|
||||
* Parse {@code data} as a message of this type and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
|
||||
*/
|
||||
Builder mergeFrom(byte[] data,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException;
|
||||
|
||||
/**
|
||||
* Parse {@code data} as a message of this type and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
|
||||
*/
|
||||
Builder mergeFrom(byte[] data, int off, int len,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException;
|
||||
|
||||
/**
|
||||
* Parse a message of this type from {@code input} and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream)}. Note that this method always
|
||||
* reads the <i>entire</i> input (unless it throws an exception). If you
|
||||
* want it to stop earlier, you will need to wrap your input in some
|
||||
* wrapper stream that limits reading. Or, use
|
||||
* {@link Message#writeDelimitedTo(OutputStream)} to write your message and
|
||||
* {@link #mergeDelimitedFrom(InputStream)} to read it.
|
||||
* <p>
|
||||
* Despite usually reading the entire input, this does not close the stream.
|
||||
*/
|
||||
Builder mergeFrom(InputStream input) throws IOException;
|
||||
|
||||
/**
|
||||
* Parse a message of this type from {@code input} and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
|
||||
*/
|
||||
Builder mergeFrom(InputStream input,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #mergeFrom(InputStream)}, but does not read until EOF.
|
||||
* Instead, the size of the message (encoded as a varint) is read first,
|
||||
* then the message data. Use
|
||||
* {@link Message#writeDelimitedTo(OutputStream)} to write messages in this
|
||||
* format.
|
||||
*/
|
||||
Builder mergeDelimitedFrom(InputStream input)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions.
|
||||
*/
|
||||
Builder mergeDelimitedFrom(InputStream input,
|
||||
ExtensionRegistry extensionRegistry)
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws IOException;
|
||||
}
|
||||
}
|
||||
|
331
java/src/main/java/com/google/protobuf/MessageLite.java
Normal file
331
java/src/main/java/com/google/protobuf/MessageLite.java
Normal file
@ -0,0 +1,331 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// TODO(kenton): Use generics? E.g. Builder<BuilderType extends Builder>, then
|
||||
// mergeFrom*() could return BuilderType for better type-safety.
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Abstract interface implemented by Protocol Message objects.
|
||||
*
|
||||
* <p>This interface is implemented by all protocol message objects. Most
|
||||
* users will be more interested in the Message interface, which is a subclass
|
||||
* of MessageLite. Use MessageLite instead when you only need the subset of
|
||||
* features which it supports -- namely, nothing that uses descriptors or
|
||||
* reflection. You can instruct the protocol compiler to generate classes
|
||||
* which implement only MessageLite, not the full Message interface, by adding
|
||||
* the follow line to the .proto file:
|
||||
* <pre>
|
||||
* option optimize_for = LITE_RUNTIME;
|
||||
* </pre>
|
||||
*
|
||||
* <p>This is particularly useful on resource-constrained systems where the
|
||||
* full protocol buffers runtime library is too big.
|
||||
*
|
||||
* <p>Note that on non-constrained systems (e.g. servers) when you need to link
|
||||
* in lots of protocol definitions, a better way to reduce total code footprint
|
||||
* is to use {@code optimize_for = CODE_SIZE}. This will make the generated
|
||||
* code smaller while still supporting all the same features (at the expense of
|
||||
* speed). {@code optimize_for = LITE_RUNTIME} is best when you only have a
|
||||
* small number of message types linked into your binary, in which case the
|
||||
* size of the protocol buffers runtime itself is the biggest problem.
|
||||
*
|
||||
* @author kenton@google.com Kenton Varda
|
||||
*/
|
||||
public interface MessageLite {
|
||||
/**
|
||||
* Get an instance of the type with all fields set to their default values.
|
||||
* This may or may not be a singleton. This differs from the
|
||||
* {@code getDefaultInstance()} method of generated message classes in that
|
||||
* this method is an abstract method of the {@code MessageLite} interface
|
||||
* whereas {@code getDefaultInstance()} is a static method of a specific
|
||||
* class. They return the same thing.
|
||||
*/
|
||||
MessageLite getDefaultInstanceForType();
|
||||
|
||||
/**
|
||||
* Returns true if all required fields in the message and all embedded
|
||||
* messages are set, false otherwise.
|
||||
*/
|
||||
boolean isInitialized();
|
||||
|
||||
/**
|
||||
* Serializes the message and writes it to {@code output}. This does not
|
||||
* flush or close the stream.
|
||||
*/
|
||||
void writeTo(CodedOutputStream output) throws IOException;
|
||||
|
||||
/**
|
||||
* Get the number of bytes required to encode this message. The result
|
||||
* is only computed on the first call and memoized after that.
|
||||
*/
|
||||
int getSerializedSize();
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Convenience methods.
|
||||
|
||||
/**
|
||||
* Serializes the message to a {@code ByteString} and returns it. This is
|
||||
* just a trivial wrapper around
|
||||
* {@link #writeTo(CodedOutputStream)}.
|
||||
*/
|
||||
ByteString toByteString();
|
||||
|
||||
/**
|
||||
* Serializes the message to a {@code byte} array and returns it. This is
|
||||
* just a trivial wrapper around
|
||||
* {@link #writeTo(CodedOutputStream)}.
|
||||
*/
|
||||
byte[] toByteArray();
|
||||
|
||||
/**
|
||||
* Serializes the message and writes it to {@code output}. This is just a
|
||||
* trivial wrapper around {@link #writeTo(CodedOutputStream)}. This does
|
||||
* not flush or close the stream.
|
||||
* <p>
|
||||
* NOTE: Protocol Buffers are not self-delimiting. Therefore, if you write
|
||||
* any more data to the stream after the message, you must somehow ensure
|
||||
* that the parser on the receiving end does not interpret this as being
|
||||
* part of the protocol message. This can be done e.g. by writing the size
|
||||
* of the message before the data, then making sure to limit the input to
|
||||
* that size on the receiving end (e.g. by wrapping the InputStream in one
|
||||
* which limits the input). Alternatively, just use
|
||||
* {@link #writeDelimitedTo(OutputStream)}.
|
||||
*/
|
||||
void writeTo(OutputStream output) throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #writeTo(OutputStream)}, but writes the size of the message
|
||||
* as a varint before writing the data. This allows more data to be written
|
||||
* to the stream after the message without the need to delimit the message
|
||||
* data yourself. Use {@link Builder#mergeDelimitedFrom(InputStream)} (or
|
||||
* the static method {@code YourMessageType.parseDelimitedFrom(InputStream)})
|
||||
* to parse messages written by this method.
|
||||
*/
|
||||
void writeDelimitedTo(OutputStream output) throws IOException;
|
||||
|
||||
// =================================================================
|
||||
// Builders
|
||||
|
||||
/**
|
||||
* Constructs a new builder for a message of the same type as this message.
|
||||
*/
|
||||
Builder newBuilderForType();
|
||||
|
||||
/**
|
||||
* Constructs a builder initialized with the current message. Use this to
|
||||
* derive a new message from the current one.
|
||||
*/
|
||||
Builder toBuilder();
|
||||
|
||||
/**
|
||||
* Abstract interface implemented by Protocol Message builders.
|
||||
*/
|
||||
interface Builder extends Cloneable {
|
||||
/** Resets all fields to their default values. */
|
||||
Builder clear();
|
||||
|
||||
/**
|
||||
* Construct the final message. Once this is called, the Builder is no
|
||||
* longer valid, and calling any other method will result in undefined
|
||||
* behavior and may throw a NullPointerException. If you need to continue
|
||||
* working with the builder after calling {@code build()}, {@code clone()}
|
||||
* it first.
|
||||
* @throws UninitializedMessageException The message is missing one or more
|
||||
* required fields (i.e. {@link #isInitialized()} returns false).
|
||||
* Use {@link #buildPartial()} to bypass this check.
|
||||
*/
|
||||
MessageLite build();
|
||||
|
||||
/**
|
||||
* Like {@link #build()}, but does not throw an exception if the message
|
||||
* is missing required fields. Instead, a partial message is returned.
|
||||
* Once this is called, the Builder is no longer valid, and calling any
|
||||
* will result in undefined behavior and may throw a NullPointerException.
|
||||
*
|
||||
* If you need to continue working with the builder after calling
|
||||
* {@code buildPartial()}, {@code clone()} it first.
|
||||
*/
|
||||
MessageLite buildPartial();
|
||||
|
||||
/**
|
||||
* Clones the Builder.
|
||||
* @see Object#clone()
|
||||
*/
|
||||
Builder clone();
|
||||
|
||||
/**
|
||||
* Returns true if all required fields in the message and all embedded
|
||||
* messages are set, false otherwise.
|
||||
*/
|
||||
boolean isInitialized();
|
||||
|
||||
/**
|
||||
* Parses a message of this type from the input and merges it with this
|
||||
* message, as if using {@link Builder#mergeFrom(MessageLite)}.
|
||||
*
|
||||
* <p>Warning: This does not verify that all required fields are present in
|
||||
* the input message. If you call {@link #build()} without setting all
|
||||
* required fields, it will throw an {@link UninitializedMessageException},
|
||||
* which is a {@code RuntimeException} and thus might not be caught. There
|
||||
* are a few good ways to deal with this:
|
||||
* <ul>
|
||||
* <li>Call {@link #isInitialized()} to verify that all required fields
|
||||
* are set before building.
|
||||
* <li>Parse the message separately using one of the static
|
||||
* {@code parseFrom} methods, then use {@link #mergeFrom(MessageLite)}
|
||||
* to merge it with this one. {@code parseFrom} will throw an
|
||||
* {@link InvalidProtocolBufferException} (an {@code IOException})
|
||||
* if some required fields are missing.
|
||||
* <li>Use {@code buildPartial()} to build, which ignores missing
|
||||
* required fields.
|
||||
* </ul>
|
||||
*
|
||||
* <p>Note: The caller should call
|
||||
* {@link CodedInputStream#checkLastTagWas(int)} after calling this to
|
||||
* verify that the last tag seen was the appropriate end-group tag,
|
||||
* or zero for EOF.
|
||||
*/
|
||||
Builder mergeFrom(CodedInputStream input) throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link Builder#mergeFrom(CodedInputStream)}, but also
|
||||
* parses extensions. The extensions that you want to be able to parse
|
||||
* must be registered in {@code extensionRegistry}. Extensions not in
|
||||
* the registry will be treated as unknown fields.
|
||||
*/
|
||||
Builder mergeFrom(CodedInputStream input,
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Get the message's type's default instance.
|
||||
* See {@link MessageLite#getDefaultInstanceForType()}.
|
||||
*/
|
||||
MessageLite getDefaultInstanceForType();
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Convenience methods.
|
||||
|
||||
/**
|
||||
* Parse {@code data} as a message of this type and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream)}.
|
||||
*/
|
||||
Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
|
||||
|
||||
/**
|
||||
* Parse {@code data} as a message of this type and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
|
||||
*/
|
||||
Builder mergeFrom(ByteString data,
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException;
|
||||
|
||||
/**
|
||||
* Parse {@code data} as a message of this type and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream)}.
|
||||
*/
|
||||
Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
|
||||
|
||||
/**
|
||||
* Parse {@code data} as a message of this type and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream)}.
|
||||
*/
|
||||
Builder mergeFrom(byte[] data, int off, int len)
|
||||
throws InvalidProtocolBufferException;
|
||||
|
||||
/**
|
||||
* Parse {@code data} as a message of this type and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
|
||||
*/
|
||||
Builder mergeFrom(byte[] data,
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException;
|
||||
|
||||
/**
|
||||
* Parse {@code data} as a message of this type and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
|
||||
*/
|
||||
Builder mergeFrom(byte[] data, int off, int len,
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException;
|
||||
|
||||
/**
|
||||
* Parse a message of this type from {@code input} and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream)}. Note that this method always
|
||||
* reads the <i>entire</i> input (unless it throws an exception). If you
|
||||
* want it to stop earlier, you will need to wrap your input in some
|
||||
* wrapper stream that limits reading. Or, use
|
||||
* {@link MessageLite#writeDelimitedTo(OutputStream)} to write your message
|
||||
* and {@link #mergeDelimitedFrom(InputStream)} to read it.
|
||||
* <p>
|
||||
* Despite usually reading the entire input, this does not close the stream.
|
||||
*/
|
||||
Builder mergeFrom(InputStream input) throws IOException;
|
||||
|
||||
/**
|
||||
* Parse a message of this type from {@code input} and merge it with the
|
||||
* message being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream,ExtensionRegistry)}.
|
||||
*/
|
||||
Builder mergeFrom(InputStream input,
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #mergeFrom(InputStream)}, but does not read until EOF.
|
||||
* Instead, the size of the message (encoded as a varint) is read first,
|
||||
* then the message data. Use
|
||||
* {@link MessageLite#writeDelimitedTo(OutputStream)} to write messages in
|
||||
* this format.
|
||||
*/
|
||||
Builder mergeDelimitedFrom(InputStream input)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions.
|
||||
*/
|
||||
Builder mergeDelimitedFrom(InputStream input,
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws IOException;
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor;
|
||||
* Interface of useful methods added to all enums generated by the protocol
|
||||
* compiler.
|
||||
*/
|
||||
public interface ProtocolMessageEnum {
|
||||
public interface ProtocolMessageEnum extends Internal.EnumLite {
|
||||
|
||||
/**
|
||||
* Return the value's numeric value as defined in the .proto file.
|
||||
|
@ -71,11 +71,11 @@ public final class RpcUtil {
|
||||
final Class<Type> originalClass,
|
||||
final Type defaultInstance) {
|
||||
return new RpcCallback<Message>() {
|
||||
public void run(Message parameter) {
|
||||
public void run(final Message parameter) {
|
||||
Type typedParameter;
|
||||
try {
|
||||
typedParameter = originalClass.cast(parameter);
|
||||
} catch (ClassCastException e) {
|
||||
} catch (ClassCastException ignored) {
|
||||
typedParameter = copyAsType(defaultInstance, parameter);
|
||||
}
|
||||
originalCallback.run(typedParameter);
|
||||
@ -90,7 +90,7 @@ public final class RpcUtil {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <Type extends Message> Type copyAsType(
|
||||
Type typeDefaultInstance, Message source) {
|
||||
final Type typeDefaultInstance, final Message source) {
|
||||
return (Type)typeDefaultInstance.newBuilderForType()
|
||||
.mergeFrom(source)
|
||||
.build();
|
||||
@ -106,8 +106,9 @@ public final class RpcUtil {
|
||||
RpcCallback<ParameterType> newOneTimeCallback(
|
||||
final RpcCallback<ParameterType> originalCallback) {
|
||||
return new RpcCallback<ParameterType>() {
|
||||
boolean alreadyCalled = false;
|
||||
public void run(ParameterType parameter) {
|
||||
private boolean alreadyCalled = false;
|
||||
|
||||
public void run(final ParameterType parameter) {
|
||||
synchronized(this) {
|
||||
if (alreadyCalled) {
|
||||
throw new AlreadyCalledException();
|
||||
@ -124,6 +125,8 @@ public final class RpcUtil {
|
||||
* Exception thrown when a one-time callback is called more than once.
|
||||
*/
|
||||
public static final class AlreadyCalledException extends RuntimeException {
|
||||
private static final long serialVersionUID = 5469741279507848266L;
|
||||
|
||||
public AlreadyCalledException() {
|
||||
super("This RpcCallback was already called and cannot be called " +
|
||||
"multiple times.");
|
||||
|
@ -32,11 +32,13 @@ package com.google.protobuf;
|
||||
|
||||
/**
|
||||
* Thrown by blocking RPC methods when a failure occurs.
|
||||
*
|
||||
*
|
||||
* @author cpovirk@google.com (Chris Povirk)
|
||||
*/
|
||||
public final class ServiceException extends Exception {
|
||||
public ServiceException(String message) {
|
||||
private static final long serialVersionUID = -1219262335729891920L;
|
||||
|
||||
public ServiceException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
@ -52,22 +52,25 @@ import java.util.regex.Pattern;
|
||||
* @author kenton@google.com Kenton Varda
|
||||
*/
|
||||
public final class TextFormat {
|
||||
private TextFormat() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs a textual representation of the Protocol Message supplied into
|
||||
* the parameter output. (This representation is the new version of the
|
||||
* classic "ProtocolPrinter" output from the original Protocol Buffer system)
|
||||
*/
|
||||
public static void print(Message message, Appendable output)
|
||||
public static void print(final Message message, final Appendable output)
|
||||
throws IOException {
|
||||
TextGenerator generator = new TextGenerator(output);
|
||||
final TextGenerator generator = new TextGenerator(output);
|
||||
print(message, generator);
|
||||
}
|
||||
|
||||
/** Outputs a textual representation of {@code fields} to {@code output}. */
|
||||
public static void print(UnknownFieldSet fields, Appendable output)
|
||||
public static void print(final UnknownFieldSet fields,
|
||||
final Appendable output)
|
||||
throws IOException {
|
||||
TextGenerator generator = new TextGenerator(output);
|
||||
final TextGenerator generator = new TextGenerator(output);
|
||||
printUnknownFields(fields, generator);
|
||||
}
|
||||
|
||||
@ -75,9 +78,9 @@ public final class TextFormat {
|
||||
* Like {@code print()}, but writes directly to a {@code String} and
|
||||
* returns it.
|
||||
*/
|
||||
public static String printToString(Message message) {
|
||||
public static String printToString(final Message message) {
|
||||
try {
|
||||
StringBuilder text = new StringBuilder();
|
||||
final StringBuilder text = new StringBuilder();
|
||||
print(message, text);
|
||||
return text.toString();
|
||||
} catch (IOException e) {
|
||||
@ -91,9 +94,9 @@ public final class TextFormat {
|
||||
* Like {@code print()}, but writes directly to a {@code String} and
|
||||
* returns it.
|
||||
*/
|
||||
public static String printToString(UnknownFieldSet fields) {
|
||||
public static String printToString(final UnknownFieldSet fields) {
|
||||
try {
|
||||
StringBuilder text = new StringBuilder();
|
||||
final StringBuilder text = new StringBuilder();
|
||||
print(fields, text);
|
||||
return text.toString();
|
||||
} catch (IOException e) {
|
||||
@ -103,22 +106,44 @@ public final class TextFormat {
|
||||
}
|
||||
}
|
||||
|
||||
private static void print(Message message, TextGenerator generator)
|
||||
private static void print(final Message message,
|
||||
final TextGenerator generator)
|
||||
throws IOException {
|
||||
for (Map.Entry<FieldDescriptor, Object> field :
|
||||
for (final Map.Entry<FieldDescriptor, Object> field :
|
||||
message.getAllFields().entrySet()) {
|
||||
printField(field.getKey(), field.getValue(), generator);
|
||||
}
|
||||
printUnknownFields(message.getUnknownFields(), generator);
|
||||
}
|
||||
|
||||
public static void printField(final FieldDescriptor field,
|
||||
final Object value,
|
||||
final Appendable output)
|
||||
throws IOException {
|
||||
final TextGenerator generator = new TextGenerator(output);
|
||||
printField(field, value, generator);
|
||||
}
|
||||
|
||||
public static void printField(FieldDescriptor field,
|
||||
Object value,
|
||||
TextGenerator generator)
|
||||
public static String printFieldToString(final FieldDescriptor field,
|
||||
final Object value) {
|
||||
try {
|
||||
final StringBuilder text = new StringBuilder();
|
||||
printField(field, value, text);
|
||||
return text.toString();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Writing to a StringBuilder threw an IOException (should never " +
|
||||
"happen).", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void printField(final FieldDescriptor field,
|
||||
final Object value,
|
||||
final TextGenerator generator)
|
||||
throws IOException {
|
||||
if (field.isRepeated()) {
|
||||
// Repeated field. Print each element.
|
||||
for (Object element : (List) value) {
|
||||
for (final Object element : (List) value) {
|
||||
printSingleField(field, element, generator);
|
||||
}
|
||||
} else {
|
||||
@ -126,9 +151,9 @@ public final class TextFormat {
|
||||
}
|
||||
}
|
||||
|
||||
private static void printSingleField(FieldDescriptor field,
|
||||
Object value,
|
||||
TextGenerator generator)
|
||||
private static void printSingleField(final FieldDescriptor field,
|
||||
final Object value,
|
||||
final TextGenerator generator)
|
||||
throws IOException {
|
||||
if (field.isExtension()) {
|
||||
generator.print("[");
|
||||
@ -168,9 +193,9 @@ public final class TextFormat {
|
||||
generator.print("\n");
|
||||
}
|
||||
|
||||
private static void printFieldValue(FieldDescriptor field,
|
||||
Object value,
|
||||
TextGenerator generator)
|
||||
private static void printFieldValue(final FieldDescriptor field,
|
||||
final Object value,
|
||||
final TextGenerator generator)
|
||||
throws IOException {
|
||||
switch (field.getType()) {
|
||||
case INT32:
|
||||
@ -202,17 +227,15 @@ public final class TextFormat {
|
||||
generator.print("\"");
|
||||
break;
|
||||
|
||||
case BYTES: {
|
||||
case BYTES:
|
||||
generator.print("\"");
|
||||
generator.print(escapeBytes((ByteString) value));
|
||||
generator.print("\"");
|
||||
break;
|
||||
}
|
||||
|
||||
case ENUM: {
|
||||
case ENUM:
|
||||
generator.print(((EnumValueDescriptor) value).getName());
|
||||
break;
|
||||
}
|
||||
|
||||
case MESSAGE:
|
||||
case GROUP:
|
||||
@ -221,39 +244,39 @@ public final class TextFormat {
|
||||
}
|
||||
}
|
||||
|
||||
private static void printUnknownFields(UnknownFieldSet unknownFields,
|
||||
TextGenerator generator)
|
||||
private static void printUnknownFields(final UnknownFieldSet unknownFields,
|
||||
final TextGenerator generator)
|
||||
throws IOException {
|
||||
for (Map.Entry<Integer, UnknownFieldSet.Field> entry :
|
||||
for (final Map.Entry<Integer, UnknownFieldSet.Field> entry :
|
||||
unknownFields.asMap().entrySet()) {
|
||||
String prefix = entry.getKey().toString() + ": ";
|
||||
UnknownFieldSet.Field field = entry.getValue();
|
||||
final String prefix = entry.getKey().toString() + ": ";
|
||||
final UnknownFieldSet.Field field = entry.getValue();
|
||||
|
||||
for (long value : field.getVarintList()) {
|
||||
for (final long value : field.getVarintList()) {
|
||||
generator.print(entry.getKey().toString());
|
||||
generator.print(": ");
|
||||
generator.print(unsignedToString(value));
|
||||
generator.print("\n");
|
||||
}
|
||||
for (int value : field.getFixed32List()) {
|
||||
for (final int value : field.getFixed32List()) {
|
||||
generator.print(entry.getKey().toString());
|
||||
generator.print(": ");
|
||||
generator.print(String.format((Locale) null, "0x%08x", value));
|
||||
generator.print("\n");
|
||||
}
|
||||
for (long value : field.getFixed64List()) {
|
||||
for (final long value : field.getFixed64List()) {
|
||||
generator.print(entry.getKey().toString());
|
||||
generator.print(": ");
|
||||
generator.print(String.format((Locale) null, "0x%016x", value));
|
||||
generator.print("\n");
|
||||
}
|
||||
for (ByteString value : field.getLengthDelimitedList()) {
|
||||
for (final ByteString value : field.getLengthDelimitedList()) {
|
||||
generator.print(entry.getKey().toString());
|
||||
generator.print(": \"");
|
||||
generator.print(escapeBytes(value));
|
||||
generator.print("\"\n");
|
||||
}
|
||||
for (UnknownFieldSet value : field.getGroupList()) {
|
||||
for (final UnknownFieldSet value : field.getGroupList()) {
|
||||
generator.print(entry.getKey().toString());
|
||||
generator.print(" {\n");
|
||||
generator.indent();
|
||||
@ -265,7 +288,7 @@ public final class TextFormat {
|
||||
}
|
||||
|
||||
/** Convert an unsigned 32-bit integer to a string. */
|
||||
private static String unsignedToString(int value) {
|
||||
private static String unsignedToString(final int value) {
|
||||
if (value >= 0) {
|
||||
return Integer.toString(value);
|
||||
} else {
|
||||
@ -274,7 +297,7 @@ public final class TextFormat {
|
||||
}
|
||||
|
||||
/** Convert an unsigned 64-bit integer to a string. */
|
||||
private static String unsignedToString(long value) {
|
||||
private static String unsignedToString(final long value) {
|
||||
if (value >= 0) {
|
||||
return Long.toString(value);
|
||||
} else {
|
||||
@ -288,13 +311,12 @@ public final class TextFormat {
|
||||
/**
|
||||
* An inner class for writing text to the output stream.
|
||||
*/
|
||||
static private final class TextGenerator {
|
||||
private static final class TextGenerator {
|
||||
private Appendable output;
|
||||
private boolean atStartOfLine = true;
|
||||
private final StringBuilder indent = new StringBuilder();
|
||||
|
||||
Appendable output;
|
||||
boolean atStartOfLine = true;
|
||||
StringBuilder indent = new StringBuilder();
|
||||
|
||||
public TextGenerator(Appendable output) {
|
||||
private TextGenerator(final Appendable output) {
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
@ -312,7 +334,7 @@ public final class TextFormat {
|
||||
* level is zero.
|
||||
*/
|
||||
public void outdent() {
|
||||
int length = indent.length();
|
||||
final int length = indent.length();
|
||||
if (length == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
" Outdent() without matching Indent().");
|
||||
@ -323,8 +345,8 @@ public final class TextFormat {
|
||||
/**
|
||||
* Print text to the output stream.
|
||||
*/
|
||||
public void print(CharSequence text) throws IOException {
|
||||
int size = text.length();
|
||||
public void print(final CharSequence text) throws IOException {
|
||||
final int size = text.length();
|
||||
int pos = 0;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
@ -337,7 +359,8 @@ public final class TextFormat {
|
||||
write(text.subSequence(pos, size), size - pos);
|
||||
}
|
||||
|
||||
private void write(CharSequence data, int size) throws IOException {
|
||||
private void write(final CharSequence data, final int size)
|
||||
throws IOException {
|
||||
if (size == 0) {
|
||||
return;
|
||||
}
|
||||
@ -399,27 +422,27 @@ public final class TextFormat {
|
||||
|
||||
// We use possesive quantifiers (*+ and ++) because otherwise the Java
|
||||
// regex matcher has stack overflows on large inputs.
|
||||
private static Pattern WHITESPACE =
|
||||
private static final Pattern WHITESPACE =
|
||||
Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE);
|
||||
private static Pattern TOKEN = Pattern.compile(
|
||||
private static final Pattern TOKEN = Pattern.compile(
|
||||
"[a-zA-Z_][0-9a-zA-Z_+-]*+|" + // an identifier
|
||||
"[0-9+-][0-9a-zA-Z_.+-]*+|" + // a number
|
||||
"\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" + // a double-quoted string
|
||||
"\'([^\"\n\\\\]|\\\\.)*+(\'|\\\\?$)", // a single-quoted string
|
||||
Pattern.MULTILINE);
|
||||
|
||||
private static Pattern DOUBLE_INFINITY = Pattern.compile(
|
||||
private static final Pattern DOUBLE_INFINITY = Pattern.compile(
|
||||
"-?inf(inity)?",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
private static Pattern FLOAT_INFINITY = Pattern.compile(
|
||||
private static final Pattern FLOAT_INFINITY = Pattern.compile(
|
||||
"-?inf(inity)?f?",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
private static Pattern FLOAT_NAN = Pattern.compile(
|
||||
private static final Pattern FLOAT_NAN = Pattern.compile(
|
||||
"nanf?",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/** Construct a tokenizer that parses tokens from the given text. */
|
||||
public Tokenizer(CharSequence text) {
|
||||
private Tokenizer(final CharSequence text) {
|
||||
this.text = text;
|
||||
this.matcher = WHITESPACE.matcher(text);
|
||||
skipWhitespace();
|
||||
@ -481,7 +504,7 @@ public final class TextFormat {
|
||||
* If the next token exactly matches {@code token}, consume it and return
|
||||
* {@code true}. Otherwise, return {@code false} without doing anything.
|
||||
*/
|
||||
public boolean tryConsume(String token) {
|
||||
public boolean tryConsume(final String token) {
|
||||
if (currentToken.equals(token)) {
|
||||
nextToken();
|
||||
return true;
|
||||
@ -494,7 +517,7 @@ public final class TextFormat {
|
||||
* If the next token exactly matches {@code token}, consume it. Otherwise,
|
||||
* throw a {@link ParseException}.
|
||||
*/
|
||||
public void consume(String token) throws ParseException {
|
||||
public void consume(final String token) throws ParseException {
|
||||
if (!tryConsume(token)) {
|
||||
throw parseException("Expected \"" + token + "\".");
|
||||
}
|
||||
@ -509,7 +532,7 @@ public final class TextFormat {
|
||||
return false;
|
||||
}
|
||||
|
||||
char c = currentToken.charAt(0);
|
||||
final char c = currentToken.charAt(0);
|
||||
return ('0' <= c && c <= '9') ||
|
||||
c == '-' || c == '+';
|
||||
}
|
||||
@ -520,7 +543,7 @@ public final class TextFormat {
|
||||
*/
|
||||
public String consumeIdentifier() throws ParseException {
|
||||
for (int i = 0; i < currentToken.length(); i++) {
|
||||
char c = currentToken.charAt(i);
|
||||
final char c = currentToken.charAt(i);
|
||||
if (('a' <= c && c <= 'z') ||
|
||||
('A' <= c && c <= 'Z') ||
|
||||
('0' <= c && c <= '9') ||
|
||||
@ -531,7 +554,7 @@ public final class TextFormat {
|
||||
}
|
||||
}
|
||||
|
||||
String result = currentToken;
|
||||
final String result = currentToken;
|
||||
nextToken();
|
||||
return result;
|
||||
}
|
||||
@ -542,7 +565,7 @@ public final class TextFormat {
|
||||
*/
|
||||
public int consumeInt32() throws ParseException {
|
||||
try {
|
||||
int result = parseInt32(currentToken);
|
||||
final int result = parseInt32(currentToken);
|
||||
nextToken();
|
||||
return result;
|
||||
} catch (NumberFormatException e) {
|
||||
@ -556,7 +579,7 @@ public final class TextFormat {
|
||||
*/
|
||||
public int consumeUInt32() throws ParseException {
|
||||
try {
|
||||
int result = parseUInt32(currentToken);
|
||||
final int result = parseUInt32(currentToken);
|
||||
nextToken();
|
||||
return result;
|
||||
} catch (NumberFormatException e) {
|
||||
@ -570,7 +593,7 @@ public final class TextFormat {
|
||||
*/
|
||||
public long consumeInt64() throws ParseException {
|
||||
try {
|
||||
long result = parseInt64(currentToken);
|
||||
final long result = parseInt64(currentToken);
|
||||
nextToken();
|
||||
return result;
|
||||
} catch (NumberFormatException e) {
|
||||
@ -584,7 +607,7 @@ public final class TextFormat {
|
||||
*/
|
||||
public long consumeUInt64() throws ParseException {
|
||||
try {
|
||||
long result = parseUInt64(currentToken);
|
||||
final long result = parseUInt64(currentToken);
|
||||
nextToken();
|
||||
return result;
|
||||
} catch (NumberFormatException e) {
|
||||
@ -600,7 +623,7 @@ public final class TextFormat {
|
||||
// We need to parse infinity and nan separately because
|
||||
// Double.parseDouble() does not accept "inf", "infinity", or "nan".
|
||||
if (DOUBLE_INFINITY.matcher(currentToken).matches()) {
|
||||
boolean negative = currentToken.startsWith("-");
|
||||
final boolean negative = currentToken.startsWith("-");
|
||||
nextToken();
|
||||
return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
|
||||
}
|
||||
@ -609,7 +632,7 @@ public final class TextFormat {
|
||||
return Double.NaN;
|
||||
}
|
||||
try {
|
||||
double result = Double.parseDouble(currentToken);
|
||||
final double result = Double.parseDouble(currentToken);
|
||||
nextToken();
|
||||
return result;
|
||||
} catch (NumberFormatException e) {
|
||||
@ -625,7 +648,7 @@ public final class TextFormat {
|
||||
// We need to parse infinity and nan separately because
|
||||
// Float.parseFloat() does not accept "inf", "infinity", or "nan".
|
||||
if (FLOAT_INFINITY.matcher(currentToken).matches()) {
|
||||
boolean negative = currentToken.startsWith("-");
|
||||
final boolean negative = currentToken.startsWith("-");
|
||||
nextToken();
|
||||
return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
|
||||
}
|
||||
@ -634,7 +657,7 @@ public final class TextFormat {
|
||||
return Float.NaN;
|
||||
}
|
||||
try {
|
||||
float result = Float.parseFloat(currentToken);
|
||||
final float result = Float.parseFloat(currentToken);
|
||||
nextToken();
|
||||
return result;
|
||||
} catch (NumberFormatException e) {
|
||||
@ -672,7 +695,8 @@ public final class TextFormat {
|
||||
* {@link ParseException}.
|
||||
*/
|
||||
public ByteString consumeByteString() throws ParseException {
|
||||
char quote = currentToken.length() > 0 ? currentToken.charAt(0) : '\0';
|
||||
final char quote = currentToken.length() > 0 ? currentToken.charAt(0)
|
||||
: '\0';
|
||||
if (quote != '\"' && quote != '\'') {
|
||||
throw parseException("Expected string.");
|
||||
}
|
||||
@ -683,11 +707,12 @@ public final class TextFormat {
|
||||
}
|
||||
|
||||
try {
|
||||
String escaped = currentToken.substring(1, currentToken.length() - 1);
|
||||
ByteString result = unescapeBytes(escaped);
|
||||
final String escaped =
|
||||
currentToken.substring(1, currentToken.length() - 1);
|
||||
final ByteString result = unescapeBytes(escaped);
|
||||
nextToken();
|
||||
return result;
|
||||
} catch (InvalidEscapeSequence e) {
|
||||
} catch (InvalidEscapeSequenceException e) {
|
||||
throw parseException(e.getMessage());
|
||||
}
|
||||
}
|
||||
@ -696,7 +721,7 @@ public final class TextFormat {
|
||||
* Returns a {@link ParseException} with the current line and column
|
||||
* numbers in the description, suitable for throwing.
|
||||
*/
|
||||
public ParseException parseException(String description) {
|
||||
public ParseException parseException(final String description) {
|
||||
// Note: People generally prefer one-based line and column numbers.
|
||||
return new ParseException(
|
||||
(line + 1) + ":" + (column + 1) + ": " + description);
|
||||
@ -706,7 +731,8 @@ public final class TextFormat {
|
||||
* Returns a {@link ParseException} with the line and column numbers of
|
||||
* the previous token in the description, suitable for throwing.
|
||||
*/
|
||||
public ParseException parseExceptionPreviousToken(String description) {
|
||||
public ParseException parseExceptionPreviousToken(
|
||||
final String description) {
|
||||
// Note: People generally prefer one-based line and column numbers.
|
||||
return new ParseException(
|
||||
(previousLine + 1) + ":" + (previousColumn + 1) + ": " + description);
|
||||
@ -716,7 +742,8 @@ public final class TextFormat {
|
||||
* Constructs an appropriate {@link ParseException} for the given
|
||||
* {@code NumberFormatException} when trying to parse an integer.
|
||||
*/
|
||||
private ParseException integerParseException(NumberFormatException e) {
|
||||
private ParseException integerParseException(
|
||||
final NumberFormatException e) {
|
||||
return parseException("Couldn't parse integer: " + e.getMessage());
|
||||
}
|
||||
|
||||
@ -724,14 +751,16 @@ public final class TextFormat {
|
||||
* Constructs an appropriate {@link ParseException} for the given
|
||||
* {@code NumberFormatException} when trying to parse a float or double.
|
||||
*/
|
||||
private ParseException floatParseException(NumberFormatException e) {
|
||||
private ParseException floatParseException(final NumberFormatException e) {
|
||||
return parseException("Couldn't parse number: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/** Thrown when parsing an invalid text format message. */
|
||||
public static class ParseException extends IOException {
|
||||
public ParseException(String message) {
|
||||
private static final long serialVersionUID = 3196188060225107702L;
|
||||
|
||||
public ParseException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -740,9 +769,9 @@ public final class TextFormat {
|
||||
* Parse a text-format message from {@code input} and merge the contents
|
||||
* into {@code builder}.
|
||||
*/
|
||||
public static void merge(Readable input,
|
||||
Message.Builder builder)
|
||||
throws ParseException, IOException {
|
||||
public static void merge(final Readable input,
|
||||
final Message.Builder builder)
|
||||
throws IOException {
|
||||
merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
|
||||
}
|
||||
|
||||
@ -750,8 +779,8 @@ public final class TextFormat {
|
||||
* Parse a text-format message from {@code input} and merge the contents
|
||||
* into {@code builder}.
|
||||
*/
|
||||
public static void merge(CharSequence input,
|
||||
Message.Builder builder)
|
||||
public static void merge(final CharSequence input,
|
||||
final Message.Builder builder)
|
||||
throws ParseException {
|
||||
merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
|
||||
}
|
||||
@ -761,10 +790,10 @@ public final class TextFormat {
|
||||
* into {@code builder}. Extensions will be recognized if they are
|
||||
* registered in {@code extensionRegistry}.
|
||||
*/
|
||||
public static void merge(Readable input,
|
||||
ExtensionRegistry extensionRegistry,
|
||||
Message.Builder builder)
|
||||
throws ParseException, IOException {
|
||||
public static void merge(final Readable input,
|
||||
final ExtensionRegistry extensionRegistry,
|
||||
final Message.Builder builder)
|
||||
throws IOException {
|
||||
// Read the entire input to a String then parse that.
|
||||
|
||||
// If StreamTokenizer were not quite so crippled, or if there were a kind
|
||||
@ -780,12 +809,12 @@ public final class TextFormat {
|
||||
|
||||
// TODO(chrisn): See if working around java.io.Reader#read(CharBuffer)
|
||||
// overhead is worthwhile
|
||||
private static StringBuilder toStringBuilder(Readable input)
|
||||
private static StringBuilder toStringBuilder(final Readable input)
|
||||
throws IOException {
|
||||
StringBuilder text = new StringBuilder();
|
||||
CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE);
|
||||
final StringBuilder text = new StringBuilder();
|
||||
final CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE);
|
||||
while (true) {
|
||||
int n = input.read(buffer);
|
||||
final int n = input.read(buffer);
|
||||
if (n == -1) {
|
||||
break;
|
||||
}
|
||||
@ -800,11 +829,11 @@ public final class TextFormat {
|
||||
* into {@code builder}. Extensions will be recognized if they are
|
||||
* registered in {@code extensionRegistry}.
|
||||
*/
|
||||
public static void merge(CharSequence input,
|
||||
ExtensionRegistry extensionRegistry,
|
||||
Message.Builder builder)
|
||||
public static void merge(final CharSequence input,
|
||||
final ExtensionRegistry extensionRegistry,
|
||||
final Message.Builder builder)
|
||||
throws ParseException {
|
||||
Tokenizer tokenizer = new Tokenizer(input);
|
||||
final Tokenizer tokenizer = new Tokenizer(input);
|
||||
|
||||
while (!tokenizer.atEnd()) {
|
||||
mergeField(tokenizer, extensionRegistry, builder);
|
||||
@ -815,19 +844,20 @@ public final class TextFormat {
|
||||
* Parse a single field from {@code tokenizer} and merge it into
|
||||
* {@code builder}.
|
||||
*/
|
||||
private static void mergeField(Tokenizer tokenizer,
|
||||
ExtensionRegistry extensionRegistry,
|
||||
Message.Builder builder)
|
||||
private static void mergeField(final Tokenizer tokenizer,
|
||||
final ExtensionRegistry extensionRegistry,
|
||||
final Message.Builder builder)
|
||||
throws ParseException {
|
||||
FieldDescriptor field;
|
||||
Descriptor type = builder.getDescriptorForType();
|
||||
final Descriptor type = builder.getDescriptorForType();
|
||||
ExtensionRegistry.ExtensionInfo extension = null;
|
||||
|
||||
if (tokenizer.tryConsume("[")) {
|
||||
// An extension.
|
||||
StringBuilder name = new StringBuilder(tokenizer.consumeIdentifier());
|
||||
final StringBuilder name =
|
||||
new StringBuilder(tokenizer.consumeIdentifier());
|
||||
while (tokenizer.tryConsume(".")) {
|
||||
name.append(".");
|
||||
name.append('.');
|
||||
name.append(tokenizer.consumeIdentifier());
|
||||
}
|
||||
|
||||
@ -846,7 +876,7 @@ public final class TextFormat {
|
||||
|
||||
field = extension.descriptor;
|
||||
} else {
|
||||
String name = tokenizer.consumeIdentifier();
|
||||
final String name = tokenizer.consumeIdentifier();
|
||||
field = type.findFieldByName(name);
|
||||
|
||||
// Group names are expected to be capitalized as they appear in the
|
||||
@ -855,7 +885,7 @@ public final class TextFormat {
|
||||
if (field == null) {
|
||||
// Explicitly specify US locale so that this code does not break when
|
||||
// executing in Turkey.
|
||||
String lowerName = name.toLowerCase(Locale.US);
|
||||
final String lowerName = name.toLowerCase(Locale.US);
|
||||
field = type.findFieldByName(lowerName);
|
||||
// If the case-insensitive match worked but the field is NOT a group,
|
||||
if (field != null && field.getType() != FieldDescriptor.Type.GROUP) {
|
||||
@ -880,7 +910,7 @@ public final class TextFormat {
|
||||
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
|
||||
tokenizer.tryConsume(":"); // optional
|
||||
|
||||
String endToken;
|
||||
final String endToken;
|
||||
if (tokenizer.tryConsume("<")) {
|
||||
endToken = ">";
|
||||
} else {
|
||||
@ -888,7 +918,7 @@ public final class TextFormat {
|
||||
endToken = "}";
|
||||
}
|
||||
|
||||
Message.Builder subBuilder;
|
||||
final Message.Builder subBuilder;
|
||||
if (extension == null) {
|
||||
subBuilder = builder.newBuilderForField(field);
|
||||
} else {
|
||||
@ -951,19 +981,19 @@ public final class TextFormat {
|
||||
value = tokenizer.consumeByteString();
|
||||
break;
|
||||
|
||||
case ENUM: {
|
||||
EnumDescriptor enumType = field.getEnumType();
|
||||
case ENUM:
|
||||
final EnumDescriptor enumType = field.getEnumType();
|
||||
|
||||
if (tokenizer.lookingAtInteger()) {
|
||||
int number = tokenizer.consumeInt32();
|
||||
final int number = tokenizer.consumeInt32();
|
||||
value = enumType.findValueByNumber(number);
|
||||
if (value == null) {
|
||||
throw tokenizer.parseExceptionPreviousToken(
|
||||
"Enum type \"" + enumType.getFullName() +
|
||||
"\" has no value with number " + number + ".");
|
||||
"\" has no value with number " + number + '.');
|
||||
}
|
||||
} else {
|
||||
String id = tokenizer.consumeIdentifier();
|
||||
final String id = tokenizer.consumeIdentifier();
|
||||
value = enumType.findValueByName(id);
|
||||
if (value == null) {
|
||||
throw tokenizer.parseExceptionPreviousToken(
|
||||
@ -973,7 +1003,6 @@ public final class TextFormat {
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case MESSAGE:
|
||||
case GROUP:
|
||||
@ -1002,10 +1031,10 @@ public final class TextFormat {
|
||||
* which no defined short-hand escape sequence is defined will be escaped
|
||||
* using 3-digit octal sequences.
|
||||
*/
|
||||
static String escapeBytes(ByteString input) {
|
||||
StringBuilder builder = new StringBuilder(input.size());
|
||||
static String escapeBytes(final ByteString input) {
|
||||
final StringBuilder builder = new StringBuilder(input.size());
|
||||
for (int i = 0; i < input.size(); i++) {
|
||||
byte b = input.byteAt(i);
|
||||
final byte b = input.byteAt(i);
|
||||
switch (b) {
|
||||
// Java does not recognize \a or \v, apparently.
|
||||
case 0x07: builder.append("\\a" ); break;
|
||||
@ -1038,9 +1067,9 @@ public final class TextFormat {
|
||||
* {@link #escapeBytes(ByteString)}. Two-digit hex escapes (starting with
|
||||
* "\x") are also recognized.
|
||||
*/
|
||||
static ByteString unescapeBytes(CharSequence input)
|
||||
throws InvalidEscapeSequence {
|
||||
byte[] result = new byte[input.length()];
|
||||
static ByteString unescapeBytes(final CharSequence input)
|
||||
throws InvalidEscapeSequenceException {
|
||||
final byte[] result = new byte[input.length()];
|
||||
int pos = 0;
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
char c = input.charAt(i);
|
||||
@ -1080,7 +1109,7 @@ public final class TextFormat {
|
||||
++i;
|
||||
code = digitValue(input.charAt(i));
|
||||
} else {
|
||||
throw new InvalidEscapeSequence(
|
||||
throw new InvalidEscapeSequenceException(
|
||||
"Invalid escape sequence: '\\x' with no digits");
|
||||
}
|
||||
if (i + 1 < input.length() && isHex(input.charAt(i + 1))) {
|
||||
@ -1091,12 +1120,12 @@ public final class TextFormat {
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidEscapeSequence(
|
||||
"Invalid escape sequence: '\\" + c + "'");
|
||||
throw new InvalidEscapeSequenceException(
|
||||
"Invalid escape sequence: '\\" + c + '\'');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new InvalidEscapeSequence(
|
||||
throw new InvalidEscapeSequenceException(
|
||||
"Invalid escape sequence: '\\' at end of string.");
|
||||
}
|
||||
} else {
|
||||
@ -1111,8 +1140,10 @@ public final class TextFormat {
|
||||
* Thrown by {@link TextFormat#unescapeBytes} and
|
||||
* {@link TextFormat#unescapeText} when an invalid escape sequence is seen.
|
||||
*/
|
||||
static class InvalidEscapeSequence extends IOException {
|
||||
public InvalidEscapeSequence(String description) {
|
||||
static class InvalidEscapeSequenceException extends IOException {
|
||||
private static final long serialVersionUID = -8164033650142593304L;
|
||||
|
||||
InvalidEscapeSequenceException(final String description) {
|
||||
super(description);
|
||||
}
|
||||
}
|
||||
@ -1122,7 +1153,7 @@ public final class TextFormat {
|
||||
* Non-ASCII characters are first encoded as UTF-8, then each byte is escaped
|
||||
* individually as a 3-digit octal escape. Yes, it's weird.
|
||||
*/
|
||||
static String escapeText(String input) {
|
||||
static String escapeText(final String input) {
|
||||
return escapeBytes(ByteString.copyFromUtf8(input));
|
||||
}
|
||||
|
||||
@ -1130,17 +1161,18 @@ public final class TextFormat {
|
||||
* Un-escape a text string as escaped using {@link #escapeText(String)}.
|
||||
* Two-digit hex escapes (starting with "\x") are also recognized.
|
||||
*/
|
||||
static String unescapeText(String input) throws InvalidEscapeSequence {
|
||||
static String unescapeText(final String input)
|
||||
throws InvalidEscapeSequenceException {
|
||||
return unescapeBytes(input).toStringUtf8();
|
||||
}
|
||||
|
||||
/** Is this an octal digit? */
|
||||
private static boolean isOctal(char c) {
|
||||
private static boolean isOctal(final char c) {
|
||||
return '0' <= c && c <= '7';
|
||||
}
|
||||
|
||||
/** Is this a hex digit? */
|
||||
private static boolean isHex(char c) {
|
||||
private static boolean isHex(final char c) {
|
||||
return ('0' <= c && c <= '9') ||
|
||||
('a' <= c && c <= 'f') ||
|
||||
('A' <= c && c <= 'F');
|
||||
@ -1151,7 +1183,7 @@ public final class TextFormat {
|
||||
* numeric value. This is like {@code Character.digit()} but we don't accept
|
||||
* non-ASCII digits.
|
||||
*/
|
||||
private static int digitValue(char c) {
|
||||
private static int digitValue(final char c) {
|
||||
if ('0' <= c && c <= '9') {
|
||||
return c - '0';
|
||||
} else if ('a' <= c && c <= 'z') {
|
||||
@ -1166,7 +1198,7 @@ public final class TextFormat {
|
||||
* {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
|
||||
* and "0" to signify hexidecimal and octal numbers, respectively.
|
||||
*/
|
||||
static int parseInt32(String text) throws NumberFormatException {
|
||||
static int parseInt32(final String text) throws NumberFormatException {
|
||||
return (int) parseInteger(text, true, false);
|
||||
}
|
||||
|
||||
@ -1177,7 +1209,7 @@ public final class TextFormat {
|
||||
* result is coerced to a (signed) {@code int} when returned since Java has
|
||||
* no unsigned integer type.
|
||||
*/
|
||||
static int parseUInt32(String text) throws NumberFormatException {
|
||||
static int parseUInt32(final String text) throws NumberFormatException {
|
||||
return (int) parseInteger(text, false, false);
|
||||
}
|
||||
|
||||
@ -1186,7 +1218,7 @@ public final class TextFormat {
|
||||
* {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
|
||||
* and "0" to signify hexidecimal and octal numbers, respectively.
|
||||
*/
|
||||
static long parseInt64(String text) throws NumberFormatException {
|
||||
static long parseInt64(final String text) throws NumberFormatException {
|
||||
return parseInteger(text, true, true);
|
||||
}
|
||||
|
||||
@ -1197,13 +1229,13 @@ public final class TextFormat {
|
||||
* result is coerced to a (signed) {@code long} when returned since Java has
|
||||
* no unsigned long type.
|
||||
*/
|
||||
static long parseUInt64(String text) throws NumberFormatException {
|
||||
static long parseUInt64(final String text) throws NumberFormatException {
|
||||
return parseInteger(text, false, true);
|
||||
}
|
||||
|
||||
private static long parseInteger(String text,
|
||||
boolean isSigned,
|
||||
boolean isLong)
|
||||
private static long parseInteger(final String text,
|
||||
final boolean isSigned,
|
||||
final boolean isLong)
|
||||
throws NumberFormatException {
|
||||
int pos = 0;
|
||||
|
||||
@ -1224,7 +1256,7 @@ public final class TextFormat {
|
||||
radix = 8;
|
||||
}
|
||||
|
||||
String numberText = text.substring(pos);
|
||||
final String numberText = text.substring(pos);
|
||||
|
||||
long result = 0;
|
||||
if (numberText.length() < 16) {
|
||||
|
@ -30,12 +30,8 @@
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import com.google.protobuf.Descriptors.FieldDescriptor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Thrown when attempting to build a protocol message that is missing required
|
||||
@ -51,11 +47,15 @@ import java.util.Map;
|
||||
* @author kenton@google.com Kenton Varda
|
||||
*/
|
||||
public class UninitializedMessageException extends RuntimeException {
|
||||
public UninitializedMessageException(Message message) {
|
||||
this(findMissingFields(message));
|
||||
private static final long serialVersionUID = -7466929953374883507L;
|
||||
|
||||
public UninitializedMessageException(final MessageLite message) {
|
||||
super("Message was missing required fields. (Lite runtime could not " +
|
||||
"determine which fields were missing).");
|
||||
missingFields = null;
|
||||
}
|
||||
|
||||
private UninitializedMessageException(List<String> missingFields) {
|
||||
public UninitializedMessageException(final List<String> missingFields) {
|
||||
super(buildDescription(missingFields));
|
||||
this.missingFields = missingFields;
|
||||
}
|
||||
@ -65,6 +65,8 @@ public class UninitializedMessageException extends RuntimeException {
|
||||
/**
|
||||
* Get a list of human-readable names of required fields missing from this
|
||||
* message. Each name is a full path to a field, e.g. "foo.bar[5].baz".
|
||||
* Returns null if the lite runtime was used, since it lacks the ability to
|
||||
* find missing fields.
|
||||
*/
|
||||
public List<String> getMissingFields() {
|
||||
return Collections.unmodifiableList(missingFields);
|
||||
@ -80,11 +82,11 @@ public class UninitializedMessageException extends RuntimeException {
|
||||
}
|
||||
|
||||
/** Construct the description string for this exception. */
|
||||
private static String buildDescription(List<String> missingFields) {
|
||||
StringBuilder description =
|
||||
private static String buildDescription(final List<String> missingFields) {
|
||||
final StringBuilder description =
|
||||
new StringBuilder("Message missing required fields: ");
|
||||
boolean first = true;
|
||||
for (String field : missingFields) {
|
||||
for (final String field : missingFields) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
@ -94,67 +96,4 @@ public class UninitializedMessageException extends RuntimeException {
|
||||
}
|
||||
return description.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates {@code this.missingFields} with the full "path" of each
|
||||
* missing required field in the given message.
|
||||
*/
|
||||
private static List<String> findMissingFields(Message message) {
|
||||
List<String> results = new ArrayList<String>();
|
||||
findMissingFields(message, "", results);
|
||||
return results;
|
||||
}
|
||||
|
||||
/** Recursive helper implementing {@link #findMissingFields(Message)}. */
|
||||
private static void findMissingFields(Message message, String prefix,
|
||||
List<String> results) {
|
||||
for (FieldDescriptor field : message.getDescriptorForType().getFields()) {
|
||||
if (field.isRequired() && !message.hasField(field)) {
|
||||
results.add(prefix + field.getName());
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<FieldDescriptor, Object> entry :
|
||||
message.getAllFields().entrySet()) {
|
||||
FieldDescriptor field = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
|
||||
if (field.isRepeated()) {
|
||||
int i = 0;
|
||||
for (Object element : (List) value) {
|
||||
findMissingFields((Message) element,
|
||||
subMessagePrefix(prefix, field, i++),
|
||||
results);
|
||||
}
|
||||
} else {
|
||||
if (message.hasField(field)) {
|
||||
findMissingFields((Message) value,
|
||||
subMessagePrefix(prefix, field, -1),
|
||||
results);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String subMessagePrefix(String prefix,
|
||||
FieldDescriptor field,
|
||||
int index) {
|
||||
StringBuilder result = new StringBuilder(prefix);
|
||||
if (field.isExtension()) {
|
||||
result.append('(')
|
||||
.append(field.getFullName())
|
||||
.append(')');
|
||||
} else {
|
||||
result.append(field.getName());
|
||||
}
|
||||
if (index != -1) {
|
||||
result.append('[')
|
||||
.append(index)
|
||||
.append(']');
|
||||
}
|
||||
result.append('.');
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
|
@ -30,15 +30,17 @@
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import java.io.InputStream;
|
||||
import com.google.protobuf.Internal.ThreadLocalQuickQueue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.TreeMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* {@code UnknownFieldSet} is used to keep track of fields which were seen when
|
||||
@ -48,56 +50,59 @@ import java.util.Map;
|
||||
* compiled before the new types were added.
|
||||
*
|
||||
* <p>Every {@link Message} contains an {@code UnknownFieldSet} (and every
|
||||
* {@link Message.Builder} contains an {@link UnknownFieldSet.Builder}).
|
||||
* {@link Message.Builder} contains an {@link Builder}).
|
||||
*
|
||||
* <p>Most users will never need to use this class.
|
||||
*
|
||||
* @author kenton@google.com Kenton Varda
|
||||
*/
|
||||
public final class UnknownFieldSet {
|
||||
public final class UnknownFieldSet implements MessageLite {
|
||||
private UnknownFieldSet() {}
|
||||
|
||||
/** Create a new {@link UnknownFieldSet.Builder}. */
|
||||
/** Create a new {@link Builder}. */
|
||||
public static Builder newBuilder() {
|
||||
return new Builder();
|
||||
return Builder.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link UnknownFieldSet.Builder} and initialize it to be a copy
|
||||
* Create a new {@link Builder} and initialize it to be a copy
|
||||
* of {@code copyFrom}.
|
||||
*/
|
||||
public static Builder newBuilder(UnknownFieldSet copyFrom) {
|
||||
return new Builder().mergeFrom(copyFrom);
|
||||
public static Builder newBuilder(final UnknownFieldSet copyFrom) {
|
||||
return newBuilder().mergeFrom(copyFrom);
|
||||
}
|
||||
|
||||
/** Get an empty {@code UnknownFieldSet}. */
|
||||
public static UnknownFieldSet getDefaultInstance() {
|
||||
return defaultInstance;
|
||||
}
|
||||
private static UnknownFieldSet defaultInstance =
|
||||
public UnknownFieldSet getDefaultInstanceForType() {
|
||||
return defaultInstance;
|
||||
}
|
||||
private static final UnknownFieldSet defaultInstance =
|
||||
new UnknownFieldSet(Collections.<Integer, Field>emptyMap());
|
||||
|
||||
/**
|
||||
* Construct an {@code UnknownFieldSet} around the given map. The map is
|
||||
* expected to be immutable.
|
||||
*/
|
||||
private UnknownFieldSet(Map<Integer, Field> fields) {
|
||||
private UnknownFieldSet(final Map<Integer, Field> fields) {
|
||||
this.fields = fields;
|
||||
}
|
||||
private Map<Integer, Field> fields;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
public boolean equals(final Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
return (other instanceof UnknownFieldSet) &&
|
||||
this.fields.equals(((UnknownFieldSet) other).fields);
|
||||
fields.equals(((UnknownFieldSet) other).fields);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.fields.hashCode();
|
||||
return fields.hashCode();
|
||||
}
|
||||
|
||||
/** Get a map of fields in the set by number. */
|
||||
@ -106,7 +111,7 @@ public final class UnknownFieldSet {
|
||||
}
|
||||
|
||||
/** Check if the given field number is present in the set. */
|
||||
public boolean hasField(int number) {
|
||||
public boolean hasField(final int number) {
|
||||
return fields.containsKey(number);
|
||||
}
|
||||
|
||||
@ -114,14 +119,14 @@ public final class UnknownFieldSet {
|
||||
* Get a field by number. Returns an empty field if not present. Never
|
||||
* returns {@code null}.
|
||||
*/
|
||||
public Field getField(int number) {
|
||||
Field result = fields.get(number);
|
||||
public Field getField(final int number) {
|
||||
final Field result = fields.get(number);
|
||||
return (result == null) ? Field.getDefaultInstance() : result;
|
||||
}
|
||||
|
||||
/** Serializes the set and writes it to {@code output}. */
|
||||
public void writeTo(CodedOutputStream output) throws IOException {
|
||||
for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
|
||||
public void writeTo(final CodedOutputStream output) throws IOException {
|
||||
for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
|
||||
entry.getValue().writeTo(entry.getKey(), output);
|
||||
}
|
||||
}
|
||||
@ -131,7 +136,8 @@ public final class UnknownFieldSet {
|
||||
* just a trivial wrapper around
|
||||
* {@link TextFormat#printToString(UnknownFieldSet)}.
|
||||
*/
|
||||
public final String toString() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return TextFormat.printToString(this);
|
||||
}
|
||||
|
||||
@ -139,13 +145,13 @@ public final class UnknownFieldSet {
|
||||
* Serializes the message to a {@code ByteString} and returns it. This is
|
||||
* just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
|
||||
*/
|
||||
public final ByteString toByteString() {
|
||||
public ByteString toByteString() {
|
||||
try {
|
||||
ByteString.CodedBuilder out =
|
||||
final ByteString.CodedBuilder out =
|
||||
ByteString.newCodedBuilder(getSerializedSize());
|
||||
writeTo(out.getCodedOutput());
|
||||
return out.build();
|
||||
} catch (IOException e) {
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Serializing to a ByteString threw an IOException (should " +
|
||||
"never happen).", e);
|
||||
@ -156,14 +162,14 @@ public final class UnknownFieldSet {
|
||||
* Serializes the message to a {@code byte} array and returns it. This is
|
||||
* just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
|
||||
*/
|
||||
public final byte[] toByteArray() {
|
||||
public byte[] toByteArray() {
|
||||
try {
|
||||
byte[] result = new byte[getSerializedSize()];
|
||||
CodedOutputStream output = CodedOutputStream.newInstance(result);
|
||||
final byte[] result = new byte[getSerializedSize()];
|
||||
final CodedOutputStream output = CodedOutputStream.newInstance(result);
|
||||
writeTo(output);
|
||||
output.checkNoSpaceLeft();
|
||||
return result;
|
||||
} catch (IOException e) {
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Serializing to a byte array threw an IOException " +
|
||||
"(should never happen).", e);
|
||||
@ -174,8 +180,15 @@ public final class UnknownFieldSet {
|
||||
* Serializes the message and writes it to {@code output}. This is just a
|
||||
* trivial wrapper around {@link #writeTo(CodedOutputStream)}.
|
||||
*/
|
||||
public final void writeTo(OutputStream output) throws IOException {
|
||||
CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
|
||||
public void writeTo(final OutputStream output) throws IOException {
|
||||
final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
|
||||
writeTo(codedOutput);
|
||||
codedOutput.flush();
|
||||
}
|
||||
|
||||
public void writeDelimitedTo(OutputStream output) throws IOException {
|
||||
final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
|
||||
codedOutput.writeRawVarint32(getSerializedSize());
|
||||
writeTo(codedOutput);
|
||||
codedOutput.flush();
|
||||
}
|
||||
@ -183,7 +196,7 @@ public final class UnknownFieldSet {
|
||||
/** Get the number of bytes required to encode this set. */
|
||||
public int getSerializedSize() {
|
||||
int result = 0;
|
||||
for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
|
||||
for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
|
||||
result += entry.getValue().getSerializedSize(entry.getKey());
|
||||
}
|
||||
return result;
|
||||
@ -193,9 +206,9 @@ public final class UnknownFieldSet {
|
||||
* Serializes the set and writes it to {@code output} using
|
||||
* {@code MessageSet} wire format.
|
||||
*/
|
||||
public void writeAsMessageSetTo(CodedOutputStream output)
|
||||
public void writeAsMessageSetTo(final CodedOutputStream output)
|
||||
throws IOException {
|
||||
for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
|
||||
for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
|
||||
entry.getValue().writeAsMessageSetExtensionTo(
|
||||
entry.getKey(), output);
|
||||
}
|
||||
@ -207,37 +220,51 @@ public final class UnknownFieldSet {
|
||||
*/
|
||||
public int getSerializedSizeAsMessageSet() {
|
||||
int result = 0;
|
||||
for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
|
||||
for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
|
||||
result += entry.getValue().getSerializedSizeAsMessageSetExtension(
|
||||
entry.getKey());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
// UnknownFieldSets do not have required fields, so they are always
|
||||
// initialized.
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Parse an {@code UnknownFieldSet} from the given input stream. */
|
||||
static public UnknownFieldSet parseFrom(CodedInputStream input)
|
||||
public static UnknownFieldSet parseFrom(final CodedInputStream input)
|
||||
throws IOException {
|
||||
return newBuilder().mergeFrom(input).build();
|
||||
}
|
||||
|
||||
/** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
|
||||
public static UnknownFieldSet parseFrom(ByteString data)
|
||||
public static UnknownFieldSet parseFrom(final ByteString data)
|
||||
throws InvalidProtocolBufferException {
|
||||
return newBuilder().mergeFrom(data).build();
|
||||
}
|
||||
|
||||
/** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
|
||||
public static UnknownFieldSet parseFrom(byte[] data)
|
||||
public static UnknownFieldSet parseFrom(final byte[] data)
|
||||
throws InvalidProtocolBufferException {
|
||||
return newBuilder().mergeFrom(data).build();
|
||||
}
|
||||
|
||||
/** Parse an {@code UnknownFieldSet} from {@code input} and return it. */
|
||||
public static UnknownFieldSet parseFrom(InputStream input)
|
||||
public static UnknownFieldSet parseFrom(final InputStream input)
|
||||
throws IOException {
|
||||
return newBuilder().mergeFrom(input).build();
|
||||
}
|
||||
|
||||
public Builder newBuilderForType() {
|
||||
return newBuilder();
|
||||
}
|
||||
|
||||
public Builder toBuilder() {
|
||||
return newBuilder().mergeFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for {@link UnknownFieldSet}s.
|
||||
*
|
||||
@ -250,21 +277,35 @@ public final class UnknownFieldSet {
|
||||
*
|
||||
* <p>Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}.
|
||||
*/
|
||||
public static final class Builder {
|
||||
public static final class Builder implements MessageLite.Builder {
|
||||
private static ThreadLocalQuickQueue<Builder> builders =
|
||||
new ThreadLocalQuickQueue<Builder>();
|
||||
|
||||
// This constructor should never be called directly (except from 'create').
|
||||
private Builder() {}
|
||||
private Map<Integer, Field> fields = new TreeMap<Integer, Field>();
|
||||
|
||||
private Map<Integer, Field> fields;
|
||||
|
||||
// Optimization: We keep around a builder for the last field that was
|
||||
// modified so that we can efficiently add to it multiple times in a
|
||||
// row (important when parsing an unknown repeated field).
|
||||
int lastFieldNumber = 0;
|
||||
Field.Builder lastField = null;
|
||||
private int lastFieldNumber;
|
||||
private Field.Builder lastField;
|
||||
|
||||
private static Builder create() {
|
||||
Builder builder = builders.get().poll();
|
||||
if (builder == null) {
|
||||
builder = new Builder();
|
||||
}
|
||||
builder.reinitialize();
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a field builder for the given field number which includes any
|
||||
* values that already exist.
|
||||
*/
|
||||
private Field.Builder getFieldBuilder(int number) {
|
||||
private Field.Builder getFieldBuilder(final int number) {
|
||||
if (lastField != null) {
|
||||
if (number == lastFieldNumber) {
|
||||
return lastField;
|
||||
@ -275,7 +316,7 @@ public final class UnknownFieldSet {
|
||||
if (number == 0) {
|
||||
return null;
|
||||
} else {
|
||||
Field existing = fields.get(number);
|
||||
final Field existing = fields.get(number);
|
||||
lastFieldNumber = number;
|
||||
lastField = Field.newBuilder();
|
||||
if (existing != null) {
|
||||
@ -289,26 +330,48 @@ public final class UnknownFieldSet {
|
||||
* Build the {@link UnknownFieldSet} and return it.
|
||||
*
|
||||
* <p>Once {@code build()} has been called, the {@code Builder} will no
|
||||
* longer be usable. Calling any method after {@code build()} will throw
|
||||
* {@code NullPointerException}.
|
||||
* longer be usable. Calling any method after {@code build()} will result
|
||||
* in undefined behavior and can cause a {@code NullPointerException} to be
|
||||
* thrown.
|
||||
*/
|
||||
public UnknownFieldSet build() {
|
||||
getFieldBuilder(0); // Force lastField to be built.
|
||||
UnknownFieldSet result;
|
||||
final UnknownFieldSet result;
|
||||
if (fields.isEmpty()) {
|
||||
result = getDefaultInstance();
|
||||
} else {
|
||||
result = new UnknownFieldSet(Collections.unmodifiableMap(fields));
|
||||
}
|
||||
fields = null;
|
||||
builders.get().offer(this);
|
||||
return result;
|
||||
}
|
||||
|
||||
public UnknownFieldSet buildPartial() {
|
||||
// No required fields, so this is the same as build().
|
||||
return build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder clone() {
|
||||
getFieldBuilder(0); // Force lastField to be built.
|
||||
return UnknownFieldSet.newBuilder().mergeFrom(
|
||||
new UnknownFieldSet(fields));
|
||||
}
|
||||
|
||||
public UnknownFieldSet getDefaultInstanceForType() {
|
||||
return UnknownFieldSet.getDefaultInstance();
|
||||
}
|
||||
|
||||
private void reinitialize() {
|
||||
fields = Collections.emptyMap();
|
||||
lastFieldNumber = 0;
|
||||
lastField = null;
|
||||
}
|
||||
|
||||
/** Reset the builder to an empty set. */
|
||||
public Builder clear() {
|
||||
fields = new TreeMap<Integer, Field>();
|
||||
lastFieldNumber = 0;
|
||||
lastField = null;
|
||||
reinitialize();
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -317,9 +380,9 @@ public final class UnknownFieldSet {
|
||||
* exists in both sets, {@code other}'s values for that field will be
|
||||
* appended to the values in this set.
|
||||
*/
|
||||
public Builder mergeFrom(UnknownFieldSet other) {
|
||||
public Builder mergeFrom(final UnknownFieldSet other) {
|
||||
if (other != getDefaultInstance()) {
|
||||
for (Map.Entry<Integer, Field> entry : other.fields.entrySet()) {
|
||||
for (final Map.Entry<Integer, Field> entry : other.fields.entrySet()) {
|
||||
mergeField(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
@ -330,7 +393,7 @@ public final class UnknownFieldSet {
|
||||
* Add a field to the {@code UnknownFieldSet}. If a field with the same
|
||||
* number already exists, the two are merged.
|
||||
*/
|
||||
public Builder mergeField(int number, Field field) {
|
||||
public Builder mergeField(final int number, final Field field) {
|
||||
if (number == 0) {
|
||||
throw new IllegalArgumentException("Zero is not a valid field number.");
|
||||
}
|
||||
@ -350,7 +413,7 @@ public final class UnknownFieldSet {
|
||||
* value. This is used in particular when an unknown enum value is
|
||||
* encountered.
|
||||
*/
|
||||
public Builder mergeVarintField(int number, int value) {
|
||||
public Builder mergeVarintField(final int number, final int value) {
|
||||
if (number == 0) {
|
||||
throw new IllegalArgumentException("Zero is not a valid field number.");
|
||||
}
|
||||
@ -359,7 +422,7 @@ public final class UnknownFieldSet {
|
||||
}
|
||||
|
||||
/** Check if the given field number is present in the set. */
|
||||
public boolean hasField(int number) {
|
||||
public boolean hasField(final int number) {
|
||||
if (number == 0) {
|
||||
throw new IllegalArgumentException("Zero is not a valid field number.");
|
||||
}
|
||||
@ -370,7 +433,7 @@ public final class UnknownFieldSet {
|
||||
* Add a field to the {@code UnknownFieldSet}. If a field with the same
|
||||
* number already exists, it is removed.
|
||||
*/
|
||||
public Builder addField(int number, Field field) {
|
||||
public Builder addField(final int number, final Field field) {
|
||||
if (number == 0) {
|
||||
throw new IllegalArgumentException("Zero is not a valid field number.");
|
||||
}
|
||||
@ -379,6 +442,9 @@ public final class UnknownFieldSet {
|
||||
lastField = null;
|
||||
lastFieldNumber = 0;
|
||||
}
|
||||
if (fields.isEmpty()) {
|
||||
fields = new TreeMap<Integer,Field>();
|
||||
}
|
||||
fields.put(number, field);
|
||||
return this;
|
||||
}
|
||||
@ -396,9 +462,9 @@ public final class UnknownFieldSet {
|
||||
* Parse an entire message from {@code input} and merge its fields into
|
||||
* this set.
|
||||
*/
|
||||
public Builder mergeFrom(CodedInputStream input) throws IOException {
|
||||
public Builder mergeFrom(final CodedInputStream input) throws IOException {
|
||||
while (true) {
|
||||
int tag = input.readTag();
|
||||
final int tag = input.readTag();
|
||||
if (tag == 0 || !mergeFieldFrom(tag, input)) {
|
||||
break;
|
||||
}
|
||||
@ -411,9 +477,9 @@ public final class UnknownFieldSet {
|
||||
* @param tag The field's tag number, which was already parsed.
|
||||
* @return {@code false} if the tag is an engroup tag.
|
||||
*/
|
||||
public boolean mergeFieldFrom(int tag, CodedInputStream input)
|
||||
public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
|
||||
throws IOException {
|
||||
int number = WireFormat.getTagFieldNumber(tag);
|
||||
final int number = WireFormat.getTagFieldNumber(tag);
|
||||
switch (WireFormat.getTagWireType(tag)) {
|
||||
case WireFormat.WIRETYPE_VARINT:
|
||||
getFieldBuilder(number).addVarint(input.readInt64());
|
||||
@ -424,12 +490,12 @@ public final class UnknownFieldSet {
|
||||
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
|
||||
getFieldBuilder(number).addLengthDelimited(input.readBytes());
|
||||
return true;
|
||||
case WireFormat.WIRETYPE_START_GROUP: {
|
||||
UnknownFieldSet.Builder subBuilder = UnknownFieldSet.newBuilder();
|
||||
input.readUnknownGroup(number, subBuilder);
|
||||
case WireFormat.WIRETYPE_START_GROUP:
|
||||
final Builder subBuilder = newBuilder();
|
||||
input.readGroup(number, subBuilder,
|
||||
ExtensionRegistry.getEmptyRegistry());
|
||||
getFieldBuilder(number).addGroup(subBuilder.build());
|
||||
return true;
|
||||
}
|
||||
case WireFormat.WIRETYPE_END_GROUP:
|
||||
return false;
|
||||
case WireFormat.WIRETYPE_FIXED32:
|
||||
@ -445,16 +511,16 @@ public final class UnknownFieldSet {
|
||||
* set being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream)}.
|
||||
*/
|
||||
public Builder mergeFrom(ByteString data)
|
||||
public Builder mergeFrom(final ByteString data)
|
||||
throws InvalidProtocolBufferException {
|
||||
try {
|
||||
CodedInputStream input = data.newCodedInput();
|
||||
final CodedInputStream input = data.newCodedInput();
|
||||
mergeFrom(input);
|
||||
input.checkLastTagWas(0);
|
||||
return this;
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
} catch (final InvalidProtocolBufferException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Reading from a ByteString threw an IOException (should " +
|
||||
"never happen).", e);
|
||||
@ -466,10 +532,69 @@ public final class UnknownFieldSet {
|
||||
* set being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream)}.
|
||||
*/
|
||||
public Builder mergeFrom(byte[] data)
|
||||
public Builder mergeFrom(final byte[] data)
|
||||
throws InvalidProtocolBufferException {
|
||||
try {
|
||||
CodedInputStream input = CodedInputStream.newInstance(data);
|
||||
final CodedInputStream input = CodedInputStream.newInstance(data);
|
||||
mergeFrom(input);
|
||||
input.checkLastTagWas(0);
|
||||
return this;
|
||||
} catch (final InvalidProtocolBufferException e) {
|
||||
throw e;
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(
|
||||
"Reading from a byte array threw an IOException (should " +
|
||||
"never happen).", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an {@code UnknownFieldSet} from {@code input} and merge it with the
|
||||
* set being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream)}.
|
||||
*/
|
||||
public Builder mergeFrom(final InputStream input) throws IOException {
|
||||
final CodedInputStream codedInput = CodedInputStream.newInstance(input);
|
||||
mergeFrom(codedInput);
|
||||
codedInput.checkLastTagWas(0);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder mergeDelimitedFrom(InputStream input)
|
||||
throws IOException {
|
||||
final int size = CodedInputStream.readRawVarint32(input);
|
||||
final InputStream limitedInput =
|
||||
new AbstractMessage.Builder.LimitedInputStream(input, size);
|
||||
return mergeFrom(limitedInput, null);
|
||||
}
|
||||
|
||||
public Builder mergeDelimitedFrom(
|
||||
InputStream input,
|
||||
ExtensionRegistryLite extensionRegistry) throws IOException {
|
||||
// UnknownFieldSet has no extensions.
|
||||
return mergeFrom(input);
|
||||
}
|
||||
|
||||
public Builder mergeFrom(
|
||||
CodedInputStream input,
|
||||
ExtensionRegistryLite extensionRegistry) throws IOException {
|
||||
// UnknownFieldSet has no extensions.
|
||||
return mergeFrom(input);
|
||||
}
|
||||
|
||||
public Builder mergeFrom(
|
||||
ByteString data,
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException {
|
||||
// UnknownFieldSet has no extensions.
|
||||
return mergeFrom(data);
|
||||
}
|
||||
|
||||
public Builder mergeFrom(byte[] data, int off, int len)
|
||||
throws InvalidProtocolBufferException {
|
||||
try {
|
||||
final CodedInputStream input =
|
||||
CodedInputStream.newInstance(data, off, len);
|
||||
mergeFrom(input);
|
||||
input.checkLastTagWas(0);
|
||||
return this;
|
||||
@ -482,16 +607,33 @@ public final class UnknownFieldSet {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an {@code UnknownFieldSet} from {@code input} and merge it with the
|
||||
* set being built. This is just a small wrapper around
|
||||
* {@link #mergeFrom(CodedInputStream)}.
|
||||
*/
|
||||
public Builder mergeFrom(InputStream input) throws IOException {
|
||||
CodedInputStream codedInput = CodedInputStream.newInstance(input);
|
||||
mergeFrom(codedInput);
|
||||
codedInput.checkLastTagWas(0);
|
||||
return this;
|
||||
public Builder mergeFrom(
|
||||
byte[] data,
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException {
|
||||
// UnknownFieldSet has no extensions.
|
||||
return mergeFrom(data);
|
||||
}
|
||||
|
||||
public Builder mergeFrom(
|
||||
byte[] data, int off, int len,
|
||||
ExtensionRegistryLite extensionRegistry)
|
||||
throws InvalidProtocolBufferException {
|
||||
// UnknownFieldSet has no extensions.
|
||||
return mergeFrom(data, off, len);
|
||||
}
|
||||
|
||||
public Builder mergeFrom(
|
||||
InputStream input,
|
||||
ExtensionRegistryLite extensionRegistry) throws IOException {
|
||||
// UnknownFieldSet has no extensions.
|
||||
return mergeFrom(input);
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
// UnknownFieldSets do not have required fields, so they are always
|
||||
// initialized.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -510,7 +652,7 @@ public final class UnknownFieldSet {
|
||||
* wire types.
|
||||
*
|
||||
* <p>{@code Field} is an immutable class. To construct one, you must use a
|
||||
* {@link Field.Builder}.
|
||||
* {@link Builder}.
|
||||
*
|
||||
* @see UnknownFieldSet
|
||||
*/
|
||||
@ -519,22 +661,22 @@ public final class UnknownFieldSet {
|
||||
|
||||
/** Construct a new {@link Builder}. */
|
||||
public static Builder newBuilder() {
|
||||
return new Builder();
|
||||
return Builder.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new {@link Builder} and initialize it to a copy of
|
||||
* {@code copyFrom}.
|
||||
*/
|
||||
public static Builder newBuilder(Field copyFrom) {
|
||||
return new Builder().mergeFrom(copyFrom);
|
||||
public static Builder newBuilder(final Field copyFrom) {
|
||||
return newBuilder().mergeFrom(copyFrom);
|
||||
}
|
||||
|
||||
/** Get an empty {@code Field}. */
|
||||
public static Field getDefaultInstance() {
|
||||
return defaultInstance;
|
||||
return fieldDefaultInstance;
|
||||
}
|
||||
private static Field defaultInstance = newBuilder().build();
|
||||
private static final Field fieldDefaultInstance = newBuilder().build();
|
||||
|
||||
/** Get the list of varint values for this field. */
|
||||
public List<Long> getVarintList() { return varint; }
|
||||
@ -556,14 +698,14 @@ public final class UnknownFieldSet {
|
||||
public List<UnknownFieldSet> getGroupList() { return group; }
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
public boolean equals(final Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof Field)) {
|
||||
return false;
|
||||
}
|
||||
return Arrays.equals(this.getIdentityArray(),
|
||||
return Arrays.equals(getIdentityArray(),
|
||||
((Field) other).getIdentityArray());
|
||||
}
|
||||
|
||||
@ -574,37 +716,37 @@ public final class UnknownFieldSet {
|
||||
|
||||
/**
|
||||
* Returns the array of objects to be used to uniquely identify this
|
||||
* {@link UnknownFieldSet.Field} instance.
|
||||
* {@link Field} instance.
|
||||
*/
|
||||
private Object[] getIdentityArray() {
|
||||
return new Object[] {
|
||||
this.varint,
|
||||
this.fixed32,
|
||||
this.fixed64,
|
||||
this.lengthDelimited,
|
||||
this.group};
|
||||
varint,
|
||||
fixed32,
|
||||
fixed64,
|
||||
lengthDelimited,
|
||||
group};
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the field, including field number, and writes it to
|
||||
* {@code output}.
|
||||
*/
|
||||
public void writeTo(int fieldNumber, CodedOutputStream output)
|
||||
public void writeTo(final int fieldNumber, final CodedOutputStream output)
|
||||
throws IOException {
|
||||
for (long value : varint) {
|
||||
for (final long value : varint) {
|
||||
output.writeUInt64(fieldNumber, value);
|
||||
}
|
||||
for (int value : fixed32) {
|
||||
for (final int value : fixed32) {
|
||||
output.writeFixed32(fieldNumber, value);
|
||||
}
|
||||
for (long value : fixed64) {
|
||||
for (final long value : fixed64) {
|
||||
output.writeFixed64(fieldNumber, value);
|
||||
}
|
||||
for (ByteString value : lengthDelimited) {
|
||||
for (final ByteString value : lengthDelimited) {
|
||||
output.writeBytes(fieldNumber, value);
|
||||
}
|
||||
for (UnknownFieldSet value : group) {
|
||||
output.writeUnknownGroup(fieldNumber, value);
|
||||
for (final UnknownFieldSet value : group) {
|
||||
output.writeGroup(fieldNumber, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -612,22 +754,22 @@ public final class UnknownFieldSet {
|
||||
* Get the number of bytes required to encode this field, including field
|
||||
* number.
|
||||
*/
|
||||
public int getSerializedSize(int fieldNumber) {
|
||||
public int getSerializedSize(final int fieldNumber) {
|
||||
int result = 0;
|
||||
for (long value : varint) {
|
||||
for (final long value : varint) {
|
||||
result += CodedOutputStream.computeUInt64Size(fieldNumber, value);
|
||||
}
|
||||
for (int value : fixed32) {
|
||||
for (final int value : fixed32) {
|
||||
result += CodedOutputStream.computeFixed32Size(fieldNumber, value);
|
||||
}
|
||||
for (long value : fixed64) {
|
||||
for (final long value : fixed64) {
|
||||
result += CodedOutputStream.computeFixed64Size(fieldNumber, value);
|
||||
}
|
||||
for (ByteString value : lengthDelimited) {
|
||||
for (final ByteString value : lengthDelimited) {
|
||||
result += CodedOutputStream.computeBytesSize(fieldNumber, value);
|
||||
}
|
||||
for (UnknownFieldSet value : group) {
|
||||
result += CodedOutputStream.computeUnknownGroupSize(fieldNumber, value);
|
||||
for (final UnknownFieldSet value : group) {
|
||||
result += CodedOutputStream.computeGroupSize(fieldNumber, value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -637,10 +779,10 @@ public final class UnknownFieldSet {
|
||||
* {@code output}, using {@code MessageSet} wire format.
|
||||
*/
|
||||
public void writeAsMessageSetExtensionTo(
|
||||
int fieldNumber,
|
||||
CodedOutputStream output)
|
||||
final int fieldNumber,
|
||||
final CodedOutputStream output)
|
||||
throws IOException {
|
||||
for (ByteString value : lengthDelimited) {
|
||||
for (final ByteString value : lengthDelimited) {
|
||||
output.writeRawMessageSetExtension(fieldNumber, value);
|
||||
}
|
||||
}
|
||||
@ -649,9 +791,9 @@ public final class UnknownFieldSet {
|
||||
* Get the number of bytes required to encode this field, including field
|
||||
* number, using {@code MessageSet} wire format.
|
||||
*/
|
||||
public int getSerializedSizeAsMessageSetExtension(int fieldNumber) {
|
||||
public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) {
|
||||
int result = 0;
|
||||
for (ByteString value : lengthDelimited) {
|
||||
for (final ByteString value : lengthDelimited) {
|
||||
result += CodedOutputStream.computeRawMessageSetExtensionSize(
|
||||
fieldNumber, value);
|
||||
}
|
||||
@ -670,13 +812,29 @@ public final class UnknownFieldSet {
|
||||
* <p>Use {@link Field#newBuilder()} to construct a {@code Builder}.
|
||||
*/
|
||||
public static final class Builder {
|
||||
private static ThreadLocalQuickQueue<Builder> builders =
|
||||
new ThreadLocalQuickQueue<Builder>();
|
||||
|
||||
// This constructor should never be called directly (except from 'create').
|
||||
private Builder() {}
|
||||
private Field result = new Field();
|
||||
|
||||
private static Builder create() {
|
||||
Builder builder = builders.get().poll();
|
||||
if (builder == null) {
|
||||
builder = new Builder();
|
||||
}
|
||||
|
||||
builder.result = new Field();
|
||||
return builder;
|
||||
}
|
||||
|
||||
private Field result;
|
||||
|
||||
/**
|
||||
* Build the field. After {@code build()} has been called, the
|
||||
* {@code Builder} is no longer usable. Calling any other method will
|
||||
* throw a {@code NullPointerException}.
|
||||
* result in undefined behavior and can cause a
|
||||
* {@code NullPointerException} to be thrown.
|
||||
*/
|
||||
public Field build() {
|
||||
if (result.varint == null) {
|
||||
@ -706,8 +864,9 @@ public final class UnknownFieldSet {
|
||||
result.group = Collections.unmodifiableList(result.group);
|
||||
}
|
||||
|
||||
Field returnMe = result;
|
||||
final Field returnMe = result;
|
||||
result = null;
|
||||
builders.get().offer(this);
|
||||
return returnMe;
|
||||
}
|
||||
|
||||
@ -722,7 +881,7 @@ public final class UnknownFieldSet {
|
||||
* of values, {@code other}'s values are append to the ones in this
|
||||
* field.
|
||||
*/
|
||||
public Builder mergeFrom(Field other) {
|
||||
public Builder mergeFrom(final Field other) {
|
||||
if (!other.varint.isEmpty()) {
|
||||
if (result.varint == null) {
|
||||
result.varint = new ArrayList<Long>();
|
||||
@ -757,7 +916,7 @@ public final class UnknownFieldSet {
|
||||
}
|
||||
|
||||
/** Add a varint value. */
|
||||
public Builder addVarint(long value) {
|
||||
public Builder addVarint(final long value) {
|
||||
if (result.varint == null) {
|
||||
result.varint = new ArrayList<Long>();
|
||||
}
|
||||
@ -766,7 +925,7 @@ public final class UnknownFieldSet {
|
||||
}
|
||||
|
||||
/** Add a fixed32 value. */
|
||||
public Builder addFixed32(int value) {
|
||||
public Builder addFixed32(final int value) {
|
||||
if (result.fixed32 == null) {
|
||||
result.fixed32 = new ArrayList<Integer>();
|
||||
}
|
||||
@ -775,7 +934,7 @@ public final class UnknownFieldSet {
|
||||
}
|
||||
|
||||
/** Add a fixed64 value. */
|
||||
public Builder addFixed64(long value) {
|
||||
public Builder addFixed64(final long value) {
|
||||
if (result.fixed64 == null) {
|
||||
result.fixed64 = new ArrayList<Long>();
|
||||
}
|
||||
@ -784,7 +943,7 @@ public final class UnknownFieldSet {
|
||||
}
|
||||
|
||||
/** Add a length-delimited value. */
|
||||
public Builder addLengthDelimited(ByteString value) {
|
||||
public Builder addLengthDelimited(final ByteString value) {
|
||||
if (result.lengthDelimited == null) {
|
||||
result.lengthDelimited = new ArrayList<ByteString>();
|
||||
}
|
||||
@ -793,7 +952,7 @@ public final class UnknownFieldSet {
|
||||
}
|
||||
|
||||
/** Add an embedded group. */
|
||||
public Builder addGroup(UnknownFieldSet value) {
|
||||
public Builder addGroup(final UnknownFieldSet value) {
|
||||
if (result.group == null) {
|
||||
result.group = new ArrayList<UnknownFieldSet>();
|
||||
}
|
||||
|
@ -56,54 +56,84 @@ public final class WireFormat {
|
||||
static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
|
||||
|
||||
/** Given a tag value, determines the wire type (the lower 3 bits). */
|
||||
static int getTagWireType(int tag) {
|
||||
static int getTagWireType(final int tag) {
|
||||
return tag & TAG_TYPE_MASK;
|
||||
}
|
||||
|
||||
/** Given a tag value, determines the field number (the upper 29 bits). */
|
||||
public static int getTagFieldNumber(int tag) {
|
||||
public static int getTagFieldNumber(final int tag) {
|
||||
return tag >>> TAG_TYPE_BITS;
|
||||
}
|
||||
|
||||
/** Makes a tag value given a field number and wire type. */
|
||||
static int makeTag(int fieldNumber, int wireType) {
|
||||
static int makeTag(final int fieldNumber, final int wireType) {
|
||||
return (fieldNumber << TAG_TYPE_BITS) | wireType;
|
||||
}
|
||||
|
||||
static int getWireFormatForFieldType(Descriptors.FieldDescriptor.Type type) {
|
||||
switch (type) {
|
||||
case DOUBLE : return WIRETYPE_FIXED64;
|
||||
case FLOAT : return WIRETYPE_FIXED32;
|
||||
case INT64 : return WIRETYPE_VARINT;
|
||||
case UINT64 : return WIRETYPE_VARINT;
|
||||
case INT32 : return WIRETYPE_VARINT;
|
||||
case FIXED64 : return WIRETYPE_FIXED64;
|
||||
case FIXED32 : return WIRETYPE_FIXED32;
|
||||
case BOOL : return WIRETYPE_VARINT;
|
||||
case STRING : return WIRETYPE_LENGTH_DELIMITED;
|
||||
case GROUP : return WIRETYPE_START_GROUP;
|
||||
case MESSAGE : return WIRETYPE_LENGTH_DELIMITED;
|
||||
case BYTES : return WIRETYPE_LENGTH_DELIMITED;
|
||||
case UINT32 : return WIRETYPE_VARINT;
|
||||
case ENUM : return WIRETYPE_VARINT;
|
||||
case SFIXED32: return WIRETYPE_FIXED32;
|
||||
case SFIXED64: return WIRETYPE_FIXED64;
|
||||
case SINT32 : return WIRETYPE_VARINT;
|
||||
case SINT64 : return WIRETYPE_VARINT;
|
||||
/**
|
||||
* Lite equivalent to {@link Descriptors.FieldDescriptor.JavaType}. This is
|
||||
* only here to support the lite runtime and should not be used by users.
|
||||
*/
|
||||
public enum JavaType {
|
||||
INT(0),
|
||||
LONG(0L),
|
||||
FLOAT(0F),
|
||||
DOUBLE(0D),
|
||||
BOOLEAN(false),
|
||||
STRING(""),
|
||||
BYTE_STRING(ByteString.EMPTY),
|
||||
ENUM(null),
|
||||
MESSAGE(null);
|
||||
|
||||
JavaType(final Object defaultDefault) {
|
||||
this.defaultDefault = defaultDefault;
|
||||
}
|
||||
|
||||
throw new RuntimeException(
|
||||
"There is no way to get here, but the compiler thinks otherwise.");
|
||||
/**
|
||||
* The default default value for fields of this type, if it's a primitive
|
||||
* type.
|
||||
*/
|
||||
Object getDefaultDefault() {
|
||||
return defaultDefault;
|
||||
}
|
||||
|
||||
private final Object defaultDefault;
|
||||
}
|
||||
|
||||
/** Given a field descriptor, returns the wire type. This differs from
|
||||
* getWireFormatForFieldType for packed repeated fields. */
|
||||
static int getWireFormatForField(Descriptors.FieldDescriptor descriptor) {
|
||||
if (descriptor.getOptions().getPacked()) {
|
||||
return WIRETYPE_LENGTH_DELIMITED;
|
||||
} else {
|
||||
return getWireFormatForFieldType(descriptor.getType());
|
||||
/**
|
||||
* Lite equivalent to {@link Descriptors.FieldDescriptor.Type}. This is
|
||||
* only here to support the lite runtime and should not be used by users.
|
||||
*/
|
||||
public enum FieldType {
|
||||
DOUBLE (JavaType.DOUBLE , WIRETYPE_FIXED64 ),
|
||||
FLOAT (JavaType.FLOAT , WIRETYPE_FIXED32 ),
|
||||
INT64 (JavaType.LONG , WIRETYPE_VARINT ),
|
||||
UINT64 (JavaType.LONG , WIRETYPE_VARINT ),
|
||||
INT32 (JavaType.INT , WIRETYPE_VARINT ),
|
||||
FIXED64 (JavaType.LONG , WIRETYPE_FIXED64 ),
|
||||
FIXED32 (JavaType.INT , WIRETYPE_FIXED32 ),
|
||||
BOOL (JavaType.BOOLEAN , WIRETYPE_VARINT ),
|
||||
STRING (JavaType.STRING , WIRETYPE_LENGTH_DELIMITED),
|
||||
GROUP (JavaType.MESSAGE , WIRETYPE_START_GROUP ),
|
||||
MESSAGE (JavaType.MESSAGE , WIRETYPE_LENGTH_DELIMITED),
|
||||
BYTES (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED),
|
||||
UINT32 (JavaType.INT , WIRETYPE_VARINT ),
|
||||
ENUM (JavaType.ENUM , WIRETYPE_VARINT ),
|
||||
SFIXED32(JavaType.INT , WIRETYPE_FIXED32 ),
|
||||
SFIXED64(JavaType.LONG , WIRETYPE_FIXED64 ),
|
||||
SINT32 (JavaType.INT , WIRETYPE_VARINT ),
|
||||
SINT64 (JavaType.LONG , WIRETYPE_VARINT );
|
||||
|
||||
FieldType(final JavaType javaType, final int wireType) {
|
||||
this.javaType = javaType;
|
||||
this.wireType = wireType;
|
||||
}
|
||||
|
||||
private final JavaType javaType;
|
||||
private final int wireType;
|
||||
|
||||
public JavaType getJavaType() { return javaType; }
|
||||
public int getWireType() { return wireType; }
|
||||
}
|
||||
|
||||
// Field numbers for feilds in MessageSet wire format.
|
||||
|
@ -367,4 +367,34 @@ public class DescriptorsTest extends TestCase {
|
||||
assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
|
||||
method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the FieldDescriptor.Type enum is the same as the
|
||||
* WireFormat.FieldType enum.
|
||||
*/
|
||||
public void testFieldTypeTablesMatch() throws Exception {
|
||||
FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values();
|
||||
WireFormat.FieldType[] values2 = WireFormat.FieldType.values();
|
||||
|
||||
assertEquals(values1.length, values2.length);
|
||||
|
||||
for (int i = 0; i < values1.length; i++) {
|
||||
assertEquals(values1[i].toString(), values2[i].toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the FieldDescriptor.JavaType enum is the same as the
|
||||
* WireFormat.JavaType enum.
|
||||
*/
|
||||
public void testJavaTypeTablesMatch() throws Exception {
|
||||
FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values();
|
||||
WireFormat.JavaType[] values2 = WireFormat.JavaType.values();
|
||||
|
||||
assertEquals(values1.length, values2.length);
|
||||
|
||||
for (int i = 0; i < values1.length; i++) {
|
||||
assertEquals(values1[i].toString(), values2[i].toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,6 +73,18 @@ public class DynamicMessageTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testClearAfterBuildError() throws Exception {
|
||||
Message.Builder builder =
|
||||
DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
|
||||
builder.build();
|
||||
try {
|
||||
builder.clear();
|
||||
fail("Should have thrown exception.");
|
||||
} catch (IllegalStateException e) {
|
||||
// Success.
|
||||
}
|
||||
}
|
||||
|
||||
public void testDynamicMessageSettersRejectNull() throws Exception {
|
||||
Message.Builder builder =
|
||||
DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
|
||||
|
@ -43,6 +43,8 @@ import protobuf_unittest.MultipleFilesTestProto;
|
||||
import protobuf_unittest.MessageWithNoOuter;
|
||||
import protobuf_unittest.EnumWithNoOuter;
|
||||
import protobuf_unittest.ServiceWithNoOuter;
|
||||
import com.google.protobuf.UnittestLite;
|
||||
import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import java.util.Arrays;
|
||||
@ -82,6 +84,17 @@ public class GeneratedMessageTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testClearAfterBuildError() throws Exception {
|
||||
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
||||
builder.build();
|
||||
try {
|
||||
builder.clear();
|
||||
fail("Should have thrown exception.");
|
||||
} catch (IllegalStateException e) {
|
||||
// Success.
|
||||
}
|
||||
}
|
||||
|
||||
public void testSettersRejectNull() throws Exception {
|
||||
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
|
||||
try {
|
||||
@ -338,6 +351,16 @@ public class GeneratedMessageTest extends TestCase {
|
||||
instanceof ProtocolMessageEnum);
|
||||
}
|
||||
|
||||
public void testEnumMap() throws Exception {
|
||||
Internal.EnumLiteMap<ForeignEnum> map = ForeignEnum.internalGetValueMap();
|
||||
|
||||
for (ForeignEnum value : ForeignEnum.values()) {
|
||||
assertEquals(value, map.findValueByNumber(value.getNumber()));
|
||||
}
|
||||
|
||||
assertTrue(map.findValueByNumber(12345) == null);
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Extensions.
|
||||
|
||||
@ -420,6 +443,12 @@ public class GeneratedMessageTest extends TestCase {
|
||||
.getExtensionCount(UnittestProto.repeatedInt32Extension));
|
||||
}
|
||||
|
||||
public void testExtensionCopy() throws Exception {
|
||||
TestAllExtensions original = TestUtil.getAllExtensionsSet();
|
||||
TestAllExtensions copy = TestAllExtensions.newBuilder(original).build();
|
||||
TestUtil.assertAllExtensionsSet(copy);
|
||||
}
|
||||
|
||||
public void testExtensionMergeFrom() throws Exception {
|
||||
TestAllExtensions original =
|
||||
TestAllExtensions.newBuilder()
|
||||
@ -431,6 +460,66 @@ public class GeneratedMessageTest extends TestCase {
|
||||
1, (int) merged.getExtension(UnittestProto.optionalInt32Extension));
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Lite Extensions.
|
||||
|
||||
// We test lite extensions directly because they have a separate
|
||||
// implementation from full extensions. In contrast, we do not test
|
||||
// lite fields directly since they are implemented exactly the same as
|
||||
// regular fields.
|
||||
|
||||
public void testLiteExtensionAccessors() throws Exception {
|
||||
TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
|
||||
TestUtil.setAllExtensions(builder);
|
||||
TestAllExtensionsLite message = builder.build();
|
||||
TestUtil.assertAllExtensionsSet(message);
|
||||
}
|
||||
|
||||
public void testLiteExtensionRepeatedSetters() throws Exception {
|
||||
TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
|
||||
TestUtil.setAllExtensions(builder);
|
||||
TestUtil.modifyRepeatedExtensions(builder);
|
||||
TestAllExtensionsLite message = builder.build();
|
||||
TestUtil.assertRepeatedExtensionsModified(message);
|
||||
}
|
||||
|
||||
public void testLiteExtensionDefaults() throws Exception {
|
||||
TestUtil.assertExtensionsClear(TestAllExtensionsLite.getDefaultInstance());
|
||||
TestUtil.assertExtensionsClear(TestAllExtensionsLite.newBuilder().build());
|
||||
}
|
||||
|
||||
public void testClearLiteExtension() throws Exception {
|
||||
// clearExtension() is not actually used in TestUtil, so try it manually.
|
||||
assertFalse(
|
||||
TestAllExtensionsLite.newBuilder()
|
||||
.setExtension(UnittestLite.optionalInt32ExtensionLite, 1)
|
||||
.clearExtension(UnittestLite.optionalInt32ExtensionLite)
|
||||
.hasExtension(UnittestLite.optionalInt32ExtensionLite));
|
||||
assertEquals(0,
|
||||
TestAllExtensionsLite.newBuilder()
|
||||
.addExtension(UnittestLite.repeatedInt32ExtensionLite, 1)
|
||||
.clearExtension(UnittestLite.repeatedInt32ExtensionLite)
|
||||
.getExtensionCount(UnittestLite.repeatedInt32ExtensionLite));
|
||||
}
|
||||
|
||||
public void testLiteExtensionCopy() throws Exception {
|
||||
TestAllExtensionsLite original = TestUtil.getAllLiteExtensionsSet();
|
||||
TestAllExtensionsLite copy =
|
||||
TestAllExtensionsLite.newBuilder(original).build();
|
||||
TestUtil.assertAllExtensionsSet(copy);
|
||||
}
|
||||
|
||||
public void testLiteExtensionMergeFrom() throws Exception {
|
||||
TestAllExtensionsLite original =
|
||||
TestAllExtensionsLite.newBuilder()
|
||||
.setExtension(UnittestLite.optionalInt32ExtensionLite, 1).build();
|
||||
TestAllExtensionsLite merged =
|
||||
TestAllExtensionsLite.newBuilder().mergeFrom(original).build();
|
||||
assertTrue(merged.hasExtension(UnittestLite.optionalInt32ExtensionLite));
|
||||
assertEquals(
|
||||
1, (int) merged.getExtension(UnittestLite.optionalInt32ExtensionLite));
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// multiple_files_test
|
||||
|
||||
|
114
java/src/test/java/com/google/protobuf/LiteTest.java
Normal file
114
java/src/test/java/com/google/protobuf/LiteTest.java
Normal file
@ -0,0 +1,114 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import com.google.protobuf.UnittestLite;
|
||||
import com.google.protobuf.UnittestLite.TestAllTypesLite;
|
||||
import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
|
||||
import com.google.protobuf.UnittestLite.TestNestedExtensionLite;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Test lite runtime.
|
||||
*
|
||||
* @author kenton@google.com Kenton Varda
|
||||
*/
|
||||
public class LiteTest extends TestCase {
|
||||
public void setUp() throws Exception {
|
||||
// Test that nested extensions are initialized correctly even if the outer
|
||||
// class has not been accessed directly. This was once a bug with lite
|
||||
// messages.
|
||||
//
|
||||
// We put this in setUp() rather than in its own test method because we
|
||||
// need to make sure it runs before any actual tests.
|
||||
assertTrue(TestNestedExtensionLite.nestedExtension != null);
|
||||
}
|
||||
|
||||
public void testLite() throws Exception {
|
||||
// Since lite messages are a subset of regular messages, we can mostly
|
||||
// assume that the functionality of lite messages is already thoroughly
|
||||
// tested by the regular tests. All this test really verifies is that
|
||||
// a proto with optimize_for = LITE_RUNTIME compiles correctly when
|
||||
// linked only against the lite library. That is all tested at compile
|
||||
// time, leaving not much to do in this method. Let's just do some random
|
||||
// stuff to make sure the lite message is actually here and usable.
|
||||
|
||||
TestAllTypesLite message =
|
||||
TestAllTypesLite.newBuilder()
|
||||
.setOptionalInt32(123)
|
||||
.addRepeatedString("hello")
|
||||
.setOptionalNestedMessage(
|
||||
TestAllTypesLite.NestedMessage.newBuilder().setBb(7))
|
||||
.build();
|
||||
|
||||
ByteString data = message.toByteString();
|
||||
|
||||
TestAllTypesLite message2 = TestAllTypesLite.parseFrom(data);
|
||||
|
||||
assertEquals(123, message2.getOptionalInt32());
|
||||
assertEquals(1, message2.getRepeatedStringCount());
|
||||
assertEquals("hello", message2.getRepeatedString(0));
|
||||
assertEquals(7, message2.getOptionalNestedMessage().getBb());
|
||||
}
|
||||
|
||||
public void testLiteExtensions() throws Exception {
|
||||
// TODO(kenton): Unlike other features of the lite library, extensions are
|
||||
// implemented completely differently from the regular library. We
|
||||
// need to test them more thoroughly, once they are fully-implemented.
|
||||
|
||||
TestAllExtensionsLite message =
|
||||
TestAllExtensionsLite.newBuilder()
|
||||
.setExtension(UnittestLite.optionalInt32ExtensionLite, 123)
|
||||
.addExtension(UnittestLite.repeatedStringExtensionLite, "hello")
|
||||
.setExtension(UnittestLite.optionalNestedEnumExtensionLite,
|
||||
TestAllTypesLite.NestedEnum.BAZ)
|
||||
.setExtension(UnittestLite.optionalNestedMessageExtensionLite,
|
||||
TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build())
|
||||
.build();
|
||||
|
||||
// Test copying a message, since coping extensions actually does use a
|
||||
// different code path between lite and regular libraries, and as of this
|
||||
// writing, parsing hasn't been implemented yet.
|
||||
TestAllExtensionsLite message2 = message.toBuilder().build();
|
||||
|
||||
assertEquals(123, (int) message2.getExtension(
|
||||
UnittestLite.optionalInt32ExtensionLite));
|
||||
assertEquals(1, message2.getExtensionCount(
|
||||
UnittestLite.repeatedStringExtensionLite));
|
||||
assertEquals("hello", message2.getExtension(
|
||||
UnittestLite.repeatedStringExtensionLite, 0));
|
||||
assertEquals(TestAllTypesLite.NestedEnum.BAZ, message2.getExtension(
|
||||
UnittestLite.optionalNestedEnumExtensionLite));
|
||||
assertEquals(7, message2.getExtension(
|
||||
UnittestLite.optionalNestedMessageExtensionLite).getBb());
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -30,9 +30,12 @@
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import com.google.protobuf.Descriptors.FieldDescriptor;
|
||||
import protobuf_unittest.UnittestProto.OneString;
|
||||
import protobuf_unittest.UnittestProto.TestAllTypes;
|
||||
import protobuf_unittest.UnittestProto.TestAllExtensions;
|
||||
import protobuf_unittest.UnittestProto.TestEmptyMessage;
|
||||
import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
|
||||
import protobuf_unittest.UnittestMset.TestMessageSet;
|
||||
import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
|
||||
import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
|
||||
@ -173,6 +176,22 @@ public class TextFormatTest extends TestCase {
|
||||
TextFormat.printToString(message));
|
||||
}
|
||||
|
||||
public void testPrintField() throws Exception {
|
||||
final FieldDescriptor dataField =
|
||||
OneString.getDescriptor().findFieldByName("data");
|
||||
assertEquals(
|
||||
"data: \"test data\"\n",
|
||||
TextFormat.printFieldToString(dataField, "test data"));
|
||||
|
||||
final FieldDescriptor optionalField =
|
||||
TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
|
||||
final Object value = NestedMessage.newBuilder().setBb(42).build();
|
||||
|
||||
assertEquals(
|
||||
"optional_nested_message {\n bb: 42\n}\n",
|
||||
TextFormat.printFieldToString(optionalField, value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to construct a ByteString from a String containing only 8-bit
|
||||
* characters. The characters are converted directly to bytes, *not*
|
||||
@ -450,21 +469,21 @@ public class TextFormatTest extends TestCase {
|
||||
try {
|
||||
TextFormat.unescapeText("\\x");
|
||||
fail("Should have thrown an exception.");
|
||||
} catch (TextFormat.InvalidEscapeSequence e) {
|
||||
} catch (TextFormat.InvalidEscapeSequenceException e) {
|
||||
// success
|
||||
}
|
||||
|
||||
try {
|
||||
TextFormat.unescapeText("\\z");
|
||||
fail("Should have thrown an exception.");
|
||||
} catch (TextFormat.InvalidEscapeSequence e) {
|
||||
} catch (TextFormat.InvalidEscapeSequenceException e) {
|
||||
// success
|
||||
}
|
||||
|
||||
try {
|
||||
TextFormat.unescapeText("\\");
|
||||
fail("Should have thrown an exception.");
|
||||
} catch (TextFormat.InvalidEscapeSequence e) {
|
||||
} catch (TextFormat.InvalidEscapeSequenceException e) {
|
||||
// success
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ import protobuf_unittest.UnittestMset.TestMessageSet;
|
||||
import protobuf_unittest.UnittestMset.RawMessageSet;
|
||||
import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
|
||||
import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
|
||||
import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
|
||||
import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
|
||||
|
||||
/**
|
||||
* Tests related to parsing and serialization.
|
||||
@ -100,6 +102,32 @@ public class WireFormatTest extends TestCase {
|
||||
assertEquals(rawBytes, rawBytes2);
|
||||
}
|
||||
|
||||
public void testSerializeExtensionsLite() throws Exception {
|
||||
// TestAllTypes and TestAllExtensions should have compatible wire formats,
|
||||
// so if we serialize a TestAllExtensions then parse it as TestAllTypes
|
||||
// it should work.
|
||||
|
||||
TestAllExtensionsLite message = TestUtil.getAllLiteExtensionsSet();
|
||||
ByteString rawBytes = message.toByteString();
|
||||
assertEquals(rawBytes.size(), message.getSerializedSize());
|
||||
|
||||
TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
|
||||
|
||||
TestUtil.assertAllFieldsSet(message2);
|
||||
}
|
||||
|
||||
public void testSerializePackedExtensionsLite() throws Exception {
|
||||
// TestPackedTypes and TestPackedExtensions should have compatible wire
|
||||
// formats; check that they serialize to the same string.
|
||||
TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet();
|
||||
ByteString rawBytes = message.toByteString();
|
||||
|
||||
TestPackedTypes message2 = TestUtil.getPackedSet();
|
||||
ByteString rawBytes2 = message2.toByteString();
|
||||
|
||||
assertEquals(rawBytes, rawBytes2);
|
||||
}
|
||||
|
||||
public void testParseExtensions() throws Exception {
|
||||
// TestAllTypes and TestAllExtensions should have compatible wire formats,
|
||||
// so if we serialize a TestAllTypes then parse it as TestAllExtensions
|
||||
@ -129,6 +157,43 @@ public class WireFormatTest extends TestCase {
|
||||
TestUtil.assertPackedExtensionsSet(message2);
|
||||
}
|
||||
|
||||
public void testParseExtensionsLite() throws Exception {
|
||||
// TestAllTypes and TestAllExtensions should have compatible wire formats,
|
||||
// so if we serialize a TestAllTypes then parse it as TestAllExtensions
|
||||
// it should work.
|
||||
|
||||
TestAllTypes message = TestUtil.getAllSet();
|
||||
ByteString rawBytes = message.toByteString();
|
||||
|
||||
ExtensionRegistryLite registry_lite = TestUtil.getExtensionRegistryLite();
|
||||
|
||||
TestAllExtensionsLite message2 =
|
||||
TestAllExtensionsLite.parseFrom(rawBytes, registry_lite);
|
||||
|
||||
TestUtil.assertAllExtensionsSet(message2);
|
||||
|
||||
// Try again using a full extension registry.
|
||||
ExtensionRegistry registry = TestUtil.getExtensionRegistry();
|
||||
|
||||
TestAllExtensionsLite message3 =
|
||||
TestAllExtensionsLite.parseFrom(rawBytes, registry);
|
||||
|
||||
TestUtil.assertAllExtensionsSet(message3);
|
||||
}
|
||||
|
||||
public void testParsePackedExtensionsLite() throws Exception {
|
||||
// Ensure that packed extensions can be properly parsed.
|
||||
TestPackedExtensionsLite message = TestUtil.getLitePackedExtensionsSet();
|
||||
ByteString rawBytes = message.toByteString();
|
||||
|
||||
ExtensionRegistryLite registry = TestUtil.getExtensionRegistryLite();
|
||||
|
||||
TestPackedExtensionsLite message2 =
|
||||
TestPackedExtensionsLite.parseFrom(rawBytes, registry);
|
||||
|
||||
TestUtil.assertPackedExtensionsSet(message2);
|
||||
}
|
||||
|
||||
public void testExtensionsSerializedSize() throws Exception {
|
||||
assertEquals(TestUtil.getAllSet().getSerializedSize(),
|
||||
TestUtil.getAllExtensionsSet().getSerializedSize());
|
||||
|
@ -112,9 +112,11 @@ class RepeatedScalarFieldContainer(BaseContainer):
|
||||
return
|
||||
|
||||
orig_empty = len(self._values) == 0
|
||||
new_values = []
|
||||
for elem in elem_seq:
|
||||
self._type_checker.CheckValue(elem)
|
||||
self._values.extend(elem_seq)
|
||||
new_values.append(elem)
|
||||
self._values.extend(new_values)
|
||||
self._message_listener.ByteSizeDirty()
|
||||
if orig_empty:
|
||||
self._message_listener.TransitionToNonempty()
|
||||
@ -139,9 +141,11 @@ class RepeatedScalarFieldContainer(BaseContainer):
|
||||
|
||||
def __setslice__(self, start, stop, values):
|
||||
"""Sets the subset of items from between the specified indices."""
|
||||
new_values = []
|
||||
for value in values:
|
||||
self._type_checker.CheckValue(value)
|
||||
self._values[start:stop] = list(values)
|
||||
new_values.append(value)
|
||||
self._values[start:stop] = new_values
|
||||
self._message_listener.ByteSizeDirty()
|
||||
|
||||
def __delitem__(self, key):
|
||||
|
@ -135,12 +135,12 @@ class Decoder(object):
|
||||
def ReadFloat(self):
|
||||
"""Reads and returns a 4-byte floating-point number."""
|
||||
serialized = self._stream.ReadBytes(4)
|
||||
return struct.unpack('f', serialized)[0]
|
||||
return struct.unpack(wire_format.FORMAT_FLOAT_LITTLE_ENDIAN, serialized)[0]
|
||||
|
||||
def ReadDouble(self):
|
||||
"""Reads and returns an 8-byte floating-point number."""
|
||||
serialized = self._stream.ReadBytes(8)
|
||||
return struct.unpack('d', serialized)[0]
|
||||
return struct.unpack(wire_format.FORMAT_DOUBLE_LITTLE_ENDIAN, serialized)[0]
|
||||
|
||||
def ReadBool(self):
|
||||
"""Reads and returns a bool."""
|
||||
|
@ -36,12 +36,12 @@ __author__ = 'robinson@google.com (Will Robinson)'
|
||||
|
||||
import struct
|
||||
import unittest
|
||||
from google.protobuf.internal import wire_format
|
||||
from google.protobuf.internal import encoder
|
||||
from google.protobuf.internal import decoder
|
||||
import logging
|
||||
from google.protobuf.internal import encoder
|
||||
from google.protobuf.internal import input_stream
|
||||
from google.protobuf.internal import wire_format
|
||||
from google.protobuf import message
|
||||
import logging
|
||||
import mox
|
||||
|
||||
|
||||
@ -110,6 +110,10 @@ class DecoderTest(unittest.TestCase):
|
||||
self.mox.VerifyAll()
|
||||
self.mox.ResetAll()
|
||||
|
||||
VAL = 1.125 # Perfectly representable as a float (no rounding error).
|
||||
LITTLE_FLOAT_VAL = '\x00\x00\x90?'
|
||||
LITTLE_DOUBLE_VAL = '\x00\x00\x00\x00\x00\x00\xf2?'
|
||||
|
||||
def testReadScalars(self):
|
||||
test_string = 'I can feel myself getting sutpider.'
|
||||
scalar_tests = [
|
||||
@ -125,10 +129,10 @@ class DecoderTest(unittest.TestCase):
|
||||
'ReadLittleEndian32', long(0xffffffff)],
|
||||
['sfixed64', decoder.Decoder.ReadSFixed64, long(-1),
|
||||
'ReadLittleEndian64', 0xffffffffffffffff],
|
||||
['float', decoder.Decoder.ReadFloat, 0.0,
|
||||
'ReadBytes', struct.pack('f', 0.0), 4],
|
||||
['double', decoder.Decoder.ReadDouble, 0.0,
|
||||
'ReadBytes', struct.pack('d', 0.0), 8],
|
||||
['float', decoder.Decoder.ReadFloat, self.VAL,
|
||||
'ReadBytes', self.LITTLE_FLOAT_VAL, 4],
|
||||
['double', decoder.Decoder.ReadDouble, self.VAL,
|
||||
'ReadBytes', self.LITTLE_DOUBLE_VAL, 8],
|
||||
['bool', decoder.Decoder.ReadBool, True, 'ReadVarUInt32', 1],
|
||||
['enum', decoder.Decoder.ReadEnum, 23, 'ReadVarUInt32', 23],
|
||||
['string', decoder.Decoder.ReadString,
|
||||
|
@ -123,11 +123,13 @@ class Encoder(object):
|
||||
|
||||
def AppendFloatNoTag(self, value):
|
||||
"""Appends a floating-point number to our buffer."""
|
||||
self._stream.AppendRawBytes(struct.pack('f', value))
|
||||
self._stream.AppendRawBytes(
|
||||
struct.pack(wire_format.FORMAT_FLOAT_LITTLE_ENDIAN, value))
|
||||
|
||||
def AppendDoubleNoTag(self, value):
|
||||
"""Appends a double-precision floating-point number to our buffer."""
|
||||
self._stream.AppendRawBytes(struct.pack('d', value))
|
||||
self._stream.AppendRawBytes(
|
||||
struct.pack(wire_format.FORMAT_DOUBLE_LITTLE_ENDIAN, value))
|
||||
|
||||
def AppendBoolNoTag(self, value):
|
||||
"""Appends a boolean to our buffer."""
|
||||
|
@ -123,6 +123,10 @@ class EncoderTest(unittest.TestCase):
|
||||
self.mox.VerifyAll()
|
||||
self.mox.ResetAll()
|
||||
|
||||
VAL = 1.125 # Perfectly representable as a float (no rounding error).
|
||||
LITTLE_FLOAT_VAL = '\x00\x00\x90?'
|
||||
LITTLE_DOUBLE_VAL = '\x00\x00\x00\x00\x00\x00\xf2?'
|
||||
|
||||
def testAppendScalars(self):
|
||||
utf8_bytes = '\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82'
|
||||
utf8_string = unicode(utf8_bytes, 'utf-8')
|
||||
@ -144,9 +148,9 @@ class EncoderTest(unittest.TestCase):
|
||||
['sfixed64', self.encoder.AppendSFixed64, 'AppendLittleEndian64',
|
||||
wire_format.WIRETYPE_FIXED64, -1, 0xffffffffffffffff],
|
||||
['float', self.encoder.AppendFloat, 'AppendRawBytes',
|
||||
wire_format.WIRETYPE_FIXED32, 0.0, struct.pack('f', 0.0)],
|
||||
wire_format.WIRETYPE_FIXED32, self.VAL, self.LITTLE_FLOAT_VAL],
|
||||
['double', self.encoder.AppendDouble, 'AppendRawBytes',
|
||||
wire_format.WIRETYPE_FIXED64, 0.0, struct.pack('d', 0.0)],
|
||||
wire_format.WIRETYPE_FIXED64, self.VAL, self.LITTLE_DOUBLE_VAL],
|
||||
['bool', self.encoder.AppendBool, 'AppendVarint32',
|
||||
wire_format.WIRETYPE_VARINT, False],
|
||||
['enum', self.encoder.AppendEnum, 'AppendVarint32',
|
||||
@ -185,9 +189,9 @@ class EncoderTest(unittest.TestCase):
|
||||
['sfixed64', self.encoder.AppendSFixed64NoTag,
|
||||
'AppendLittleEndian64', None, 0],
|
||||
['float', self.encoder.AppendFloatNoTag,
|
||||
'AppendRawBytes', None, 0.0, struct.pack('f', 0.0)],
|
||||
'AppendRawBytes', None, self.VAL, self.LITTLE_FLOAT_VAL],
|
||||
['double', self.encoder.AppendDoubleNoTag,
|
||||
'AppendRawBytes', None, 0.0, struct.pack('d', 0.0)],
|
||||
'AppendRawBytes', None, self.VAL, self.LITTLE_DOUBLE_VAL],
|
||||
['bool', self.encoder.AppendBoolNoTag, 'AppendVarint32', None, 0],
|
||||
['enum', self.encoder.AppendEnumNoTag, 'AppendVarint32', None, 0],
|
||||
['sint32', self.encoder.AppendSInt32NoTag,
|
||||
|
53
python/google/protobuf/internal/message_test.py
Executable file
53
python/google/protobuf/internal/message_test.py
Executable file
@ -0,0 +1,53 @@
|
||||
#! /usr/bin/python
|
||||
#
|
||||
# Protocol Buffers - Google's data interchange format
|
||||
# Copyright 2008 Google Inc. All rights reserved.
|
||||
# http://code.google.com/p/protobuf/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""Tests python protocol buffers against the golden message."""
|
||||
|
||||
__author__ = 'gps@google.com (Gregory P. Smith)'
|
||||
|
||||
import unittest
|
||||
from google.protobuf import unittest_import_pb2
|
||||
from google.protobuf import unittest_pb2
|
||||
from google.protobuf.internal import test_util
|
||||
|
||||
|
||||
class MessageTest(test_util.GoldenMessageTestCase):
|
||||
|
||||
def testGoldenMessage(self):
|
||||
golden_data = test_util.GoldenFile('golden_message').read()
|
||||
golden_message = unittest_pb2.TestAllTypes()
|
||||
golden_message.ParseFromString(golden_data)
|
||||
self.ExpectAllFieldsSet(golden_message)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -232,13 +232,14 @@ class ReflectionTest(unittest.TestCase):
|
||||
proto.repeated_string.extend(['foo', 'bar'])
|
||||
proto.repeated_string.extend([])
|
||||
proto.repeated_string.append('baz')
|
||||
proto.repeated_string.extend(str(x) for x in xrange(2))
|
||||
proto.optional_int32 = 21
|
||||
self.assertEqual(
|
||||
[ (proto.DESCRIPTOR.fields_by_name['optional_int32' ], 21),
|
||||
(proto.DESCRIPTOR.fields_by_name['repeated_int32' ], [5, 11]),
|
||||
(proto.DESCRIPTOR.fields_by_name['repeated_fixed32'], [1]),
|
||||
(proto.DESCRIPTOR.fields_by_name['repeated_string' ],
|
||||
['foo', 'bar', 'baz']) ],
|
||||
['foo', 'bar', 'baz', '0', '1']) ],
|
||||
proto.ListFields())
|
||||
|
||||
def testSingularListExtensions(self):
|
||||
@ -447,6 +448,10 @@ class ReflectionTest(unittest.TestCase):
|
||||
self.assertEqual([25, 20, 15], proto.repeated_int32[1:4])
|
||||
self.assertEqual([5, 25, 20, 15, 30], proto.repeated_int32[:])
|
||||
|
||||
# Test slice assignment with an iterator
|
||||
proto.repeated_int32[1:4] = (i for i in xrange(3))
|
||||
self.assertEqual([5, 0, 1, 2, 30], proto.repeated_int32)
|
||||
|
||||
# Test slice assignment.
|
||||
proto.repeated_int32[1:4] = [35, 40, 45]
|
||||
self.assertEqual([5, 35, 40, 45, 30], proto.repeated_int32)
|
||||
@ -1739,13 +1744,14 @@ class SerializationTest(unittest.TestCase):
|
||||
self.assertEqual(2, proto2.b)
|
||||
self.assertEqual(3, proto2.c)
|
||||
|
||||
def testSerializedAllPackedFields(self):
|
||||
def testSerializeAllPackedFields(self):
|
||||
first_proto = unittest_pb2.TestPackedTypes()
|
||||
second_proto = unittest_pb2.TestPackedTypes()
|
||||
test_util.SetAllPackedFields(first_proto)
|
||||
serialized = first_proto.SerializeToString()
|
||||
self.assertEqual(first_proto.ByteSize(), len(serialized))
|
||||
second_proto.MergeFromString(serialized)
|
||||
bytes_read = second_proto.MergeFromString(serialized)
|
||||
self.assertEqual(second_proto.ByteSize(), bytes_read)
|
||||
self.assertEqual(first_proto, second_proto)
|
||||
|
||||
def testSerializeAllPackedExtensions(self):
|
||||
@ -1753,7 +1759,8 @@ class SerializationTest(unittest.TestCase):
|
||||
second_proto = unittest_pb2.TestPackedExtensions()
|
||||
test_util.SetAllPackedExtensions(first_proto)
|
||||
serialized = first_proto.SerializeToString()
|
||||
second_proto.MergeFromString(serialized)
|
||||
bytes_read = second_proto.MergeFromString(serialized)
|
||||
self.assertEqual(second_proto.ByteSize(), bytes_read)
|
||||
self.assertEqual(first_proto, second_proto)
|
||||
|
||||
def testMergePackedFromStringWhenSomeFieldsAlreadySet(self):
|
||||
@ -1838,6 +1845,79 @@ class SerializationTest(unittest.TestCase):
|
||||
self.assertEqual(unittest_pb2.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER,
|
||||
51)
|
||||
|
||||
def testInitKwargs(self):
|
||||
proto = unittest_pb2.TestAllTypes(
|
||||
optional_int32=1,
|
||||
optional_string='foo',
|
||||
optional_bool=True,
|
||||
optional_bytes='bar',
|
||||
optional_nested_message=unittest_pb2.TestAllTypes.NestedMessage(bb=1),
|
||||
optional_foreign_message=unittest_pb2.ForeignMessage(c=1),
|
||||
optional_nested_enum=unittest_pb2.TestAllTypes.FOO,
|
||||
optional_foreign_enum=unittest_pb2.FOREIGN_FOO,
|
||||
repeated_int32=[1, 2, 3])
|
||||
self.assertTrue(proto.IsInitialized())
|
||||
self.assertTrue(proto.HasField('optional_int32'))
|
||||
self.assertTrue(proto.HasField('optional_string'))
|
||||
self.assertTrue(proto.HasField('optional_bool'))
|
||||
self.assertTrue(proto.HasField('optional_bytes'))
|
||||
self.assertTrue(proto.HasField('optional_nested_message'))
|
||||
self.assertTrue(proto.HasField('optional_foreign_message'))
|
||||
self.assertTrue(proto.HasField('optional_nested_enum'))
|
||||
self.assertTrue(proto.HasField('optional_foreign_enum'))
|
||||
self.assertEqual(1, proto.optional_int32)
|
||||
self.assertEqual('foo', proto.optional_string)
|
||||
self.assertEqual(True, proto.optional_bool)
|
||||
self.assertEqual('bar', proto.optional_bytes)
|
||||
self.assertEqual(1, proto.optional_nested_message.bb)
|
||||
self.assertEqual(1, proto.optional_foreign_message.c)
|
||||
self.assertEqual(unittest_pb2.TestAllTypes.FOO,
|
||||
proto.optional_nested_enum)
|
||||
self.assertEqual(unittest_pb2.FOREIGN_FOO, proto.optional_foreign_enum)
|
||||
self.assertEqual([1, 2, 3], proto.repeated_int32)
|
||||
|
||||
def testInitArgsUnknownFieldName(self):
|
||||
def InitalizeEmptyMessageWithExtraKeywordArg():
|
||||
unused_proto = unittest_pb2.TestEmptyMessage(unknown='unknown')
|
||||
self._CheckRaises(ValueError,
|
||||
InitalizeEmptyMessageWithExtraKeywordArg,
|
||||
'Protocol message has no "unknown" field.')
|
||||
|
||||
def testInitRequiredKwargs(self):
|
||||
proto = unittest_pb2.TestRequired(a=1, b=1, c=1)
|
||||
self.assertTrue(proto.IsInitialized())
|
||||
self.assertTrue(proto.HasField('a'))
|
||||
self.assertTrue(proto.HasField('b'))
|
||||
self.assertTrue(proto.HasField('c'))
|
||||
self.assertTrue(not proto.HasField('dummy2'))
|
||||
self.assertEqual(1, proto.a)
|
||||
self.assertEqual(1, proto.b)
|
||||
self.assertEqual(1, proto.c)
|
||||
|
||||
def testInitRequiredForeignKwargs(self):
|
||||
proto = unittest_pb2.TestRequiredForeign(
|
||||
optional_message=unittest_pb2.TestRequired(a=1, b=1, c=1))
|
||||
self.assertTrue(proto.IsInitialized())
|
||||
self.assertTrue(proto.HasField('optional_message'))
|
||||
self.assertTrue(proto.optional_message.IsInitialized())
|
||||
self.assertTrue(proto.optional_message.HasField('a'))
|
||||
self.assertTrue(proto.optional_message.HasField('b'))
|
||||
self.assertTrue(proto.optional_message.HasField('c'))
|
||||
self.assertTrue(not proto.optional_message.HasField('dummy2'))
|
||||
self.assertEqual(unittest_pb2.TestRequired(a=1, b=1, c=1),
|
||||
proto.optional_message)
|
||||
self.assertEqual(1, proto.optional_message.a)
|
||||
self.assertEqual(1, proto.optional_message.b)
|
||||
self.assertEqual(1, proto.optional_message.c)
|
||||
|
||||
def testInitRepeatedKwargs(self):
|
||||
proto = unittest_pb2.TestAllTypes(repeated_int32=[1, 2, 3])
|
||||
self.assertTrue(proto.IsInitialized())
|
||||
self.assertEqual(1, proto.repeated_int32[0])
|
||||
self.assertEqual(2, proto.repeated_int32[1])
|
||||
self.assertEqual(3, proto.repeated_int32[2])
|
||||
|
||||
|
||||
class OptionsTest(unittest.TestCase):
|
||||
|
||||
def testMessageOptions(self):
|
||||
|
@ -38,6 +38,7 @@ __author__ = 'robinson@google.com (Will Robinson)'
|
||||
|
||||
import os.path
|
||||
|
||||
import unittest
|
||||
from google.protobuf import unittest_import_pb2
|
||||
from google.protobuf import unittest_pb2
|
||||
|
||||
@ -351,6 +352,200 @@ def ExpectAllFieldsAndExtensionsInOrder(serialized):
|
||||
if expected != serialized:
|
||||
raise ValueError('Expected %r, found %r' % (expected, serialized))
|
||||
|
||||
|
||||
class GoldenMessageTestCase(unittest.TestCase):
|
||||
"""This adds methods to TestCase useful for verifying our Golden Message."""
|
||||
|
||||
def ExpectAllFieldsSet(self, message):
|
||||
"""Check all fields for correct values have after Set*Fields() is called."""
|
||||
self.assertTrue(message.HasField('optional_int32'))
|
||||
self.assertTrue(message.HasField('optional_int64'))
|
||||
self.assertTrue(message.HasField('optional_uint32'))
|
||||
self.assertTrue(message.HasField('optional_uint64'))
|
||||
self.assertTrue(message.HasField('optional_sint32'))
|
||||
self.assertTrue(message.HasField('optional_sint64'))
|
||||
self.assertTrue(message.HasField('optional_fixed32'))
|
||||
self.assertTrue(message.HasField('optional_fixed64'))
|
||||
self.assertTrue(message.HasField('optional_sfixed32'))
|
||||
self.assertTrue(message.HasField('optional_sfixed64'))
|
||||
self.assertTrue(message.HasField('optional_float'))
|
||||
self.assertTrue(message.HasField('optional_double'))
|
||||
self.assertTrue(message.HasField('optional_bool'))
|
||||
self.assertTrue(message.HasField('optional_string'))
|
||||
self.assertTrue(message.HasField('optional_bytes'))
|
||||
|
||||
self.assertTrue(message.HasField('optionalgroup'))
|
||||
self.assertTrue(message.HasField('optional_nested_message'))
|
||||
self.assertTrue(message.HasField('optional_foreign_message'))
|
||||
self.assertTrue(message.HasField('optional_import_message'))
|
||||
|
||||
self.assertTrue(message.optionalgroup.HasField('a'))
|
||||
self.assertTrue(message.optional_nested_message.HasField('bb'))
|
||||
self.assertTrue(message.optional_foreign_message.HasField('c'))
|
||||
self.assertTrue(message.optional_import_message.HasField('d'))
|
||||
|
||||
self.assertTrue(message.HasField('optional_nested_enum'))
|
||||
self.assertTrue(message.HasField('optional_foreign_enum'))
|
||||
self.assertTrue(message.HasField('optional_import_enum'))
|
||||
|
||||
self.assertTrue(message.HasField('optional_string_piece'))
|
||||
self.assertTrue(message.HasField('optional_cord'))
|
||||
|
||||
self.assertEqual(101, message.optional_int32)
|
||||
self.assertEqual(102, message.optional_int64)
|
||||
self.assertEqual(103, message.optional_uint32)
|
||||
self.assertEqual(104, message.optional_uint64)
|
||||
self.assertEqual(105, message.optional_sint32)
|
||||
self.assertEqual(106, message.optional_sint64)
|
||||
self.assertEqual(107, message.optional_fixed32)
|
||||
self.assertEqual(108, message.optional_fixed64)
|
||||
self.assertEqual(109, message.optional_sfixed32)
|
||||
self.assertEqual(110, message.optional_sfixed64)
|
||||
self.assertEqual(111, message.optional_float)
|
||||
self.assertEqual(112, message.optional_double)
|
||||
self.assertEqual(True, message.optional_bool)
|
||||
self.assertEqual('115', message.optional_string)
|
||||
self.assertEqual('116', message.optional_bytes)
|
||||
|
||||
self.assertEqual(117, message.optionalgroup.a);
|
||||
self.assertEqual(118, message.optional_nested_message.bb)
|
||||
self.assertEqual(119, message.optional_foreign_message.c)
|
||||
self.assertEqual(120, message.optional_import_message.d)
|
||||
|
||||
self.assertEqual(unittest_pb2.TestAllTypes.BAZ,
|
||||
message.optional_nested_enum)
|
||||
self.assertEqual(unittest_pb2.FOREIGN_BAZ, message.optional_foreign_enum)
|
||||
self.assertEqual(unittest_import_pb2.IMPORT_BAZ,
|
||||
message.optional_import_enum)
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
self.assertEqual(2, len(message.repeated_int32))
|
||||
self.assertEqual(2, len(message.repeated_int64))
|
||||
self.assertEqual(2, len(message.repeated_uint32))
|
||||
self.assertEqual(2, len(message.repeated_uint64))
|
||||
self.assertEqual(2, len(message.repeated_sint32))
|
||||
self.assertEqual(2, len(message.repeated_sint64))
|
||||
self.assertEqual(2, len(message.repeated_fixed32))
|
||||
self.assertEqual(2, len(message.repeated_fixed64))
|
||||
self.assertEqual(2, len(message.repeated_sfixed32))
|
||||
self.assertEqual(2, len(message.repeated_sfixed64))
|
||||
self.assertEqual(2, len(message.repeated_float))
|
||||
self.assertEqual(2, len(message.repeated_double))
|
||||
self.assertEqual(2, len(message.repeated_bool))
|
||||
self.assertEqual(2, len(message.repeated_string))
|
||||
self.assertEqual(2, len(message.repeated_bytes))
|
||||
|
||||
self.assertEqual(2, len(message.repeatedgroup))
|
||||
self.assertEqual(2, len(message.repeated_nested_message))
|
||||
self.assertEqual(2, len(message.repeated_foreign_message))
|
||||
self.assertEqual(2, len(message.repeated_import_message))
|
||||
self.assertEqual(2, len(message.repeated_nested_enum))
|
||||
self.assertEqual(2, len(message.repeated_foreign_enum))
|
||||
self.assertEqual(2, len(message.repeated_import_enum))
|
||||
|
||||
self.assertEqual(2, len(message.repeated_string_piece))
|
||||
self.assertEqual(2, len(message.repeated_cord))
|
||||
|
||||
self.assertEqual(201, message.repeated_int32[0])
|
||||
self.assertEqual(202, message.repeated_int64[0])
|
||||
self.assertEqual(203, message.repeated_uint32[0])
|
||||
self.assertEqual(204, message.repeated_uint64[0])
|
||||
self.assertEqual(205, message.repeated_sint32[0])
|
||||
self.assertEqual(206, message.repeated_sint64[0])
|
||||
self.assertEqual(207, message.repeated_fixed32[0])
|
||||
self.assertEqual(208, message.repeated_fixed64[0])
|
||||
self.assertEqual(209, message.repeated_sfixed32[0])
|
||||
self.assertEqual(210, message.repeated_sfixed64[0])
|
||||
self.assertEqual(211, message.repeated_float[0])
|
||||
self.assertEqual(212, message.repeated_double[0])
|
||||
self.assertEqual(True, message.repeated_bool[0])
|
||||
self.assertEqual('215', message.repeated_string[0])
|
||||
self.assertEqual('216', message.repeated_bytes[0])
|
||||
|
||||
self.assertEqual(217, message.repeatedgroup[0].a)
|
||||
self.assertEqual(218, message.repeated_nested_message[0].bb)
|
||||
self.assertEqual(219, message.repeated_foreign_message[0].c)
|
||||
self.assertEqual(220, message.repeated_import_message[0].d)
|
||||
|
||||
self.assertEqual(unittest_pb2.TestAllTypes.BAR,
|
||||
message.repeated_nested_enum[0])
|
||||
self.assertEqual(unittest_pb2.FOREIGN_BAR,
|
||||
message.repeated_foreign_enum[0])
|
||||
self.assertEqual(unittest_import_pb2.IMPORT_BAR,
|
||||
message.repeated_import_enum[0])
|
||||
|
||||
self.assertEqual(301, message.repeated_int32[1])
|
||||
self.assertEqual(302, message.repeated_int64[1])
|
||||
self.assertEqual(303, message.repeated_uint32[1])
|
||||
self.assertEqual(304, message.repeated_uint64[1])
|
||||
self.assertEqual(305, message.repeated_sint32[1])
|
||||
self.assertEqual(306, message.repeated_sint64[1])
|
||||
self.assertEqual(307, message.repeated_fixed32[1])
|
||||
self.assertEqual(308, message.repeated_fixed64[1])
|
||||
self.assertEqual(309, message.repeated_sfixed32[1])
|
||||
self.assertEqual(310, message.repeated_sfixed64[1])
|
||||
self.assertEqual(311, message.repeated_float[1])
|
||||
self.assertEqual(312, message.repeated_double[1])
|
||||
self.assertEqual(False, message.repeated_bool[1])
|
||||
self.assertEqual('315', message.repeated_string[1])
|
||||
self.assertEqual('316', message.repeated_bytes[1])
|
||||
|
||||
self.assertEqual(317, message.repeatedgroup[1].a)
|
||||
self.assertEqual(318, message.repeated_nested_message[1].bb)
|
||||
self.assertEqual(319, message.repeated_foreign_message[1].c)
|
||||
self.assertEqual(320, message.repeated_import_message[1].d)
|
||||
|
||||
self.assertEqual(unittest_pb2.TestAllTypes.BAZ,
|
||||
message.repeated_nested_enum[1])
|
||||
self.assertEqual(unittest_pb2.FOREIGN_BAZ,
|
||||
message.repeated_foreign_enum[1])
|
||||
self.assertEqual(unittest_import_pb2.IMPORT_BAZ,
|
||||
message.repeated_import_enum[1])
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
|
||||
self.assertTrue(message.HasField('default_int32'))
|
||||
self.assertTrue(message.HasField('default_int64'))
|
||||
self.assertTrue(message.HasField('default_uint32'))
|
||||
self.assertTrue(message.HasField('default_uint64'))
|
||||
self.assertTrue(message.HasField('default_sint32'))
|
||||
self.assertTrue(message.HasField('default_sint64'))
|
||||
self.assertTrue(message.HasField('default_fixed32'))
|
||||
self.assertTrue(message.HasField('default_fixed64'))
|
||||
self.assertTrue(message.HasField('default_sfixed32'))
|
||||
self.assertTrue(message.HasField('default_sfixed64'))
|
||||
self.assertTrue(message.HasField('default_float'))
|
||||
self.assertTrue(message.HasField('default_double'))
|
||||
self.assertTrue(message.HasField('default_bool'))
|
||||
self.assertTrue(message.HasField('default_string'))
|
||||
self.assertTrue(message.HasField('default_bytes'))
|
||||
|
||||
self.assertTrue(message.HasField('default_nested_enum'))
|
||||
self.assertTrue(message.HasField('default_foreign_enum'))
|
||||
self.assertTrue(message.HasField('default_import_enum'))
|
||||
|
||||
self.assertEqual(401, message.default_int32)
|
||||
self.assertEqual(402, message.default_int64)
|
||||
self.assertEqual(403, message.default_uint32)
|
||||
self.assertEqual(404, message.default_uint64)
|
||||
self.assertEqual(405, message.default_sint32)
|
||||
self.assertEqual(406, message.default_sint64)
|
||||
self.assertEqual(407, message.default_fixed32)
|
||||
self.assertEqual(408, message.default_fixed64)
|
||||
self.assertEqual(409, message.default_sfixed32)
|
||||
self.assertEqual(410, message.default_sfixed64)
|
||||
self.assertEqual(411, message.default_float)
|
||||
self.assertEqual(412, message.default_double)
|
||||
self.assertEqual(False, message.default_bool)
|
||||
self.assertEqual('415', message.default_string)
|
||||
self.assertEqual('416', message.default_bytes)
|
||||
|
||||
self.assertEqual(unittest_pb2.TestAllTypes.FOO, message.default_nested_enum)
|
||||
self.assertEqual(unittest_pb2.FOREIGN_FOO, message.default_foreign_enum)
|
||||
self.assertEqual(unittest_import_pb2.IMPORT_FOO,
|
||||
message.default_import_enum)
|
||||
|
||||
def GoldenFile(filename):
|
||||
"""Finds the given golden file and returns a file object representing it."""
|
||||
|
||||
@ -359,7 +554,8 @@ def GoldenFile(filename):
|
||||
while os.path.exists(path):
|
||||
if os.path.exists(os.path.join(path, 'src/google/protobuf')):
|
||||
# Found it. Load the golden file from the testdata directory.
|
||||
return file(os.path.join(path, 'src/google/protobuf/testdata', filename))
|
||||
full_path = os.path.join(path, 'src/google/protobuf/testdata', filename)
|
||||
return open(full_path, 'rb')
|
||||
path = os.path.join(path, '..')
|
||||
|
||||
raise RuntimeError(
|
||||
|
@ -42,11 +42,16 @@ from google.protobuf.internal import test_util
|
||||
from google.protobuf import unittest_pb2
|
||||
from google.protobuf import unittest_mset_pb2
|
||||
|
||||
class TextFormatTest(unittest.TestCase):
|
||||
def CompareToGoldenFile(self, text, golden_filename):
|
||||
|
||||
class TextFormatTest(test_util.GoldenMessageTestCase):
|
||||
def ReadGolden(self, golden_filename):
|
||||
f = test_util.GoldenFile(golden_filename)
|
||||
golden_lines = f.readlines()
|
||||
f.close()
|
||||
return golden_lines
|
||||
|
||||
def CompareToGoldenFile(self, text, golden_filename):
|
||||
golden_lines = self.ReadGolden(golden_filename)
|
||||
self.CompareToGoldenLines(text, golden_lines)
|
||||
|
||||
def CompareToGoldenText(self, text, golden_text):
|
||||
@ -117,6 +122,276 @@ class TextFormatTest(unittest.TestCase):
|
||||
return text.replace('e+0','e+').replace('e+0','e+') \
|
||||
.replace('e-0','e-').replace('e-0','e-')
|
||||
|
||||
def testMergeGolden(self):
|
||||
golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt'))
|
||||
parsed_message = unittest_pb2.TestAllTypes()
|
||||
text_format.Merge(golden_text, parsed_message)
|
||||
|
||||
message = unittest_pb2.TestAllTypes()
|
||||
test_util.SetAllFields(message)
|
||||
self.assertEquals(message, parsed_message)
|
||||
|
||||
def testMergeGoldenExtensions(self):
|
||||
golden_text = '\n'.join(self.ReadGolden(
|
||||
'text_format_unittest_extensions_data.txt'))
|
||||
parsed_message = unittest_pb2.TestAllExtensions()
|
||||
text_format.Merge(golden_text, parsed_message)
|
||||
|
||||
message = unittest_pb2.TestAllExtensions()
|
||||
test_util.SetAllExtensions(message)
|
||||
self.assertEquals(message, parsed_message)
|
||||
|
||||
def testMergeAllFields(self):
|
||||
message = unittest_pb2.TestAllTypes()
|
||||
test_util.SetAllFields(message)
|
||||
ascii_text = text_format.MessageToString(message)
|
||||
|
||||
parsed_message = unittest_pb2.TestAllTypes()
|
||||
text_format.Merge(ascii_text, parsed_message)
|
||||
self.assertEqual(message, parsed_message)
|
||||
self.ExpectAllFieldsSet(message)
|
||||
|
||||
def testMergeAllExtensions(self):
|
||||
message = unittest_pb2.TestAllExtensions()
|
||||
test_util.SetAllExtensions(message)
|
||||
ascii_text = text_format.MessageToString(message)
|
||||
|
||||
parsed_message = unittest_pb2.TestAllExtensions()
|
||||
text_format.Merge(ascii_text, parsed_message)
|
||||
self.assertEqual(message, parsed_message)
|
||||
|
||||
def testMergeMessageSet(self):
|
||||
message = unittest_pb2.TestAllTypes()
|
||||
text = ('repeated_uint64: 1\n'
|
||||
'repeated_uint64: 2\n')
|
||||
text_format.Merge(text, message)
|
||||
self.assertEqual(1, message.repeated_uint64[0])
|
||||
self.assertEqual(2, message.repeated_uint64[1])
|
||||
|
||||
message = unittest_mset_pb2.TestMessageSetContainer()
|
||||
text = ('message_set {\n'
|
||||
' [protobuf_unittest.TestMessageSetExtension1] {\n'
|
||||
' i: 23\n'
|
||||
' }\n'
|
||||
' [protobuf_unittest.TestMessageSetExtension2] {\n'
|
||||
' str: \"foo\"\n'
|
||||
' }\n'
|
||||
'}\n')
|
||||
text_format.Merge(text, message)
|
||||
ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
|
||||
ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
|
||||
self.assertEquals(23, message.message_set.Extensions[ext1].i)
|
||||
self.assertEquals('foo', message.message_set.Extensions[ext2].str)
|
||||
|
||||
def testMergeExotic(self):
|
||||
message = unittest_pb2.TestAllTypes()
|
||||
text = ('repeated_int64: -9223372036854775808\n'
|
||||
'repeated_uint64: 18446744073709551615\n'
|
||||
'repeated_double: 123.456\n'
|
||||
'repeated_double: 1.23e+22\n'
|
||||
'repeated_double: 1.23e-18\n'
|
||||
'repeated_string: \n'
|
||||
'\"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\\"\"\n')
|
||||
text_format.Merge(text, message)
|
||||
|
||||
self.assertEqual(-9223372036854775808, message.repeated_int64[0])
|
||||
self.assertEqual(18446744073709551615, message.repeated_uint64[0])
|
||||
self.assertEqual(123.456, message.repeated_double[0])
|
||||
self.assertEqual(1.23e22, message.repeated_double[1])
|
||||
self.assertEqual(1.23e-18, message.repeated_double[2])
|
||||
self.assertEqual(
|
||||
'\000\001\a\b\f\n\r\t\v\\\'\"', message.repeated_string[0])
|
||||
|
||||
def testMergeUnknownField(self):
|
||||
message = unittest_pb2.TestAllTypes()
|
||||
text = 'unknown_field: 8\n'
|
||||
self.assertRaisesWithMessage(
|
||||
text_format.ParseError,
|
||||
('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named '
|
||||
'"unknown_field".'),
|
||||
text_format.Merge, text, message)
|
||||
|
||||
def testMergeBadExtension(self):
|
||||
message = unittest_pb2.TestAllTypes()
|
||||
text = '[unknown_extension]: 8\n'
|
||||
self.assertRaisesWithMessage(
|
||||
text_format.ParseError,
|
||||
'1:2 : Extension "unknown_extension" not registered.',
|
||||
text_format.Merge, text, message)
|
||||
|
||||
def testMergeGroupNotClosed(self):
|
||||
message = unittest_pb2.TestAllTypes()
|
||||
text = 'RepeatedGroup: <'
|
||||
self.assertRaisesWithMessage(
|
||||
text_format.ParseError, '1:16 : Expected ">".',
|
||||
text_format.Merge, text, message)
|
||||
|
||||
text = 'RepeatedGroup: {'
|
||||
self.assertRaisesWithMessage(
|
||||
text_format.ParseError, '1:16 : Expected "}".',
|
||||
text_format.Merge, text, message)
|
||||
|
||||
def testMergeBadEnumValue(self):
|
||||
message = unittest_pb2.TestAllTypes()
|
||||
text = 'optional_nested_enum: BARR'
|
||||
self.assertRaisesWithMessage(
|
||||
text_format.ParseError,
|
||||
('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" '
|
||||
'has no value named BARR.'),
|
||||
text_format.Merge, text, message)
|
||||
|
||||
message = unittest_pb2.TestAllTypes()
|
||||
text = 'optional_nested_enum: 100'
|
||||
self.assertRaisesWithMessage(
|
||||
text_format.ParseError,
|
||||
('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" '
|
||||
'has no value with number 100.'),
|
||||
text_format.Merge, text, message)
|
||||
|
||||
def assertRaisesWithMessage(self, e_class, e, func, *args, **kwargs):
|
||||
"""Same as assertRaises, but also compares the exception message."""
|
||||
if hasattr(e_class, '__name__'):
|
||||
exc_name = e_class.__name__
|
||||
else:
|
||||
exc_name = str(e_class)
|
||||
|
||||
try:
|
||||
func(*args, **kwargs)
|
||||
except e_class, expr:
|
||||
if str(expr) != e:
|
||||
msg = '%s raised, but with wrong message: "%s" instead of "%s"'
|
||||
raise self.failureException(msg % (exc_name,
|
||||
str(expr).encode('string_escape'),
|
||||
e.encode('string_escape')))
|
||||
return
|
||||
else:
|
||||
raise self.failureException('%s not raised' % exc_name)
|
||||
|
||||
|
||||
class TokenizerTest(unittest.TestCase):
|
||||
|
||||
def testSimpleTokenCases(self):
|
||||
text = ('identifier1:"string1"\n \n\n'
|
||||
'identifier2 : \n \n123 \n identifier3 :\'string\'\n'
|
||||
'identifiER_4 : 1.1e+2 ID5:-0.23 ID6:\'aaaa\\\'bbbb\'\n'
|
||||
'ID7 : "aa\\"bb"\n\n\n\n ID8: {A:inf B:-inf C:true D:false}\n'
|
||||
'ID9: 22 ID10: -111111111111111111 ID11: -22\n'
|
||||
'ID12: 2222222222222222222')
|
||||
tokenizer = text_format._Tokenizer(text)
|
||||
methods = [(tokenizer.ConsumeIdentifier, 'identifier1'),
|
||||
':',
|
||||
(tokenizer.ConsumeString, 'string1'),
|
||||
(tokenizer.ConsumeIdentifier, 'identifier2'),
|
||||
':',
|
||||
(tokenizer.ConsumeInt32, 123),
|
||||
(tokenizer.ConsumeIdentifier, 'identifier3'),
|
||||
':',
|
||||
(tokenizer.ConsumeString, 'string'),
|
||||
(tokenizer.ConsumeIdentifier, 'identifiER_4'),
|
||||
':',
|
||||
(tokenizer.ConsumeFloat, 1.1e+2),
|
||||
(tokenizer.ConsumeIdentifier, 'ID5'),
|
||||
':',
|
||||
(tokenizer.ConsumeFloat, -0.23),
|
||||
(tokenizer.ConsumeIdentifier, 'ID6'),
|
||||
':',
|
||||
(tokenizer.ConsumeString, 'aaaa\'bbbb'),
|
||||
(tokenizer.ConsumeIdentifier, 'ID7'),
|
||||
':',
|
||||
(tokenizer.ConsumeString, 'aa\"bb'),
|
||||
(tokenizer.ConsumeIdentifier, 'ID8'),
|
||||
':',
|
||||
'{',
|
||||
(tokenizer.ConsumeIdentifier, 'A'),
|
||||
':',
|
||||
(tokenizer.ConsumeFloat, float('inf')),
|
||||
(tokenizer.ConsumeIdentifier, 'B'),
|
||||
':',
|
||||
(tokenizer.ConsumeFloat, float('-inf')),
|
||||
(tokenizer.ConsumeIdentifier, 'C'),
|
||||
':',
|
||||
(tokenizer.ConsumeBool, True),
|
||||
(tokenizer.ConsumeIdentifier, 'D'),
|
||||
':',
|
||||
(tokenizer.ConsumeBool, False),
|
||||
'}',
|
||||
(tokenizer.ConsumeIdentifier, 'ID9'),
|
||||
':',
|
||||
(tokenizer.ConsumeUint32, 22),
|
||||
(tokenizer.ConsumeIdentifier, 'ID10'),
|
||||
':',
|
||||
(tokenizer.ConsumeInt64, -111111111111111111),
|
||||
(tokenizer.ConsumeIdentifier, 'ID11'),
|
||||
':',
|
||||
(tokenizer.ConsumeInt32, -22),
|
||||
(tokenizer.ConsumeIdentifier, 'ID12'),
|
||||
':',
|
||||
(tokenizer.ConsumeUint64, 2222222222222222222)]
|
||||
|
||||
i = 0
|
||||
while not tokenizer.AtEnd():
|
||||
m = methods[i]
|
||||
if type(m) == str:
|
||||
token = tokenizer.token
|
||||
self.assertEqual(token, m)
|
||||
tokenizer.NextToken()
|
||||
else:
|
||||
self.assertEqual(m[1], m[0]())
|
||||
i += 1
|
||||
|
||||
def testConsumeIntegers(self):
|
||||
# This test only tests the failures in the integer parsing methods as well
|
||||
# as the '0' special cases.
|
||||
int64_max = (1 << 63) - 1
|
||||
uint32_max = (1 << 32) - 1
|
||||
text = '-1 %d %d' % (uint32_max + 1, int64_max + 1)
|
||||
tokenizer = text_format._Tokenizer(text)
|
||||
self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint32)
|
||||
self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint64)
|
||||
self.assertEqual(-1, tokenizer.ConsumeInt32())
|
||||
|
||||
self.assertRaises(text_format.ParseError, tokenizer.ConsumeUint32)
|
||||
self.assertRaises(text_format.ParseError, tokenizer.ConsumeInt32)
|
||||
self.assertEqual(uint32_max + 1, tokenizer.ConsumeInt64())
|
||||
|
||||
self.assertRaises(text_format.ParseError, tokenizer.ConsumeInt64)
|
||||
self.assertEqual(int64_max + 1, tokenizer.ConsumeUint64())
|
||||
self.assertTrue(tokenizer.AtEnd())
|
||||
|
||||
text = '-0 -0 0 0'
|
||||
tokenizer = text_format._Tokenizer(text)
|
||||
self.assertEqual(0, tokenizer.ConsumeUint32())
|
||||
self.assertEqual(0, tokenizer.ConsumeUint64())
|
||||
self.assertEqual(0, tokenizer.ConsumeUint32())
|
||||
self.assertEqual(0, tokenizer.ConsumeUint64())
|
||||
self.assertTrue(tokenizer.AtEnd())
|
||||
|
||||
def testConsumeByteString(self):
|
||||
text = '"string1\''
|
||||
tokenizer = text_format._Tokenizer(text)
|
||||
self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
|
||||
|
||||
text = 'string1"'
|
||||
tokenizer = text_format._Tokenizer(text)
|
||||
self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
|
||||
|
||||
text = '\n"\\xt"'
|
||||
tokenizer = text_format._Tokenizer(text)
|
||||
self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
|
||||
|
||||
text = '\n"\\"'
|
||||
tokenizer = text_format._Tokenizer(text)
|
||||
self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
|
||||
|
||||
text = '\n"\\x"'
|
||||
tokenizer = text_format._Tokenizer(text)
|
||||
self.assertRaises(text_format.ParseError, tokenizer.ConsumeByteString)
|
||||
|
||||
def testConsumeBool(self):
|
||||
text = 'not-a-bool'
|
||||
tokenizer = text_format._Tokenizer(text)
|
||||
self.assertRaises(text_format.ParseError, tokenizer.ConsumeBool)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
|
@ -122,8 +122,10 @@ class UnicodeValueChecker(object):
|
||||
try:
|
||||
unicode(proposed_value, 'ascii')
|
||||
except UnicodeDecodeError:
|
||||
raise ValueError('%.1024r isn\'t in 7-bit ASCII encoding.'
|
||||
% (proposed_value))
|
||||
raise ValueError('%.1024r has type str, but isn\'t in 7-bit ASCII '
|
||||
'encoding. Non-ASCII strings must be converted to '
|
||||
'unicode objects before being added.' %
|
||||
(proposed_value))
|
||||
|
||||
|
||||
class Int32ValueChecker(IntValueChecker):
|
||||
|
@ -64,6 +64,8 @@ UINT64_MAX = (1 << 64) - 1
|
||||
# "struct" format strings that will encode/decode the specified formats.
|
||||
FORMAT_UINT32_LITTLE_ENDIAN = '<I'
|
||||
FORMAT_UINT64_LITTLE_ENDIAN = '<Q'
|
||||
FORMAT_FLOAT_LITTLE_ENDIAN = '<f'
|
||||
FORMAT_DOUBLE_LITTLE_ENDIAN = '<d'
|
||||
|
||||
|
||||
# We'll have to provide alternate implementations of AppendLittleEndian*() on
|
||||
|
@ -36,7 +36,6 @@
|
||||
|
||||
__author__ = 'robinson@google.com (Will Robinson)'
|
||||
|
||||
from google.protobuf import text_format
|
||||
|
||||
class Error(Exception): pass
|
||||
class DecodeError(Error): pass
|
||||
@ -76,7 +75,7 @@ class Message(object):
|
||||
return not self == other_msg
|
||||
|
||||
def __str__(self):
|
||||
return text_format.MessageToString(self)
|
||||
raise NotImplementedError
|
||||
|
||||
def MergeFrom(self, other_msg):
|
||||
"""Merges the contents of the specified message into current message.
|
||||
|
@ -62,6 +62,7 @@ from google.protobuf.internal import type_checkers
|
||||
from google.protobuf.internal import wire_format
|
||||
from google.protobuf import descriptor as descriptor_mod
|
||||
from google.protobuf import message as message_mod
|
||||
from google.protobuf import text_format
|
||||
|
||||
_FieldDescriptor = descriptor_mod.FieldDescriptor
|
||||
|
||||
@ -291,7 +292,7 @@ def _DefaultValueForField(message, field):
|
||||
def _AddInitMethod(message_descriptor, cls):
|
||||
"""Adds an __init__ method to cls."""
|
||||
fields = message_descriptor.fields
|
||||
def init(self):
|
||||
def init(self, **kwargs):
|
||||
self._cached_byte_size = 0
|
||||
self._cached_byte_size_dirty = False
|
||||
self._listener = message_listener_mod.NullMessageListener()
|
||||
@ -306,12 +307,30 @@ def _AddInitMethod(message_descriptor, cls):
|
||||
if field.label != _FieldDescriptor.LABEL_REPEATED:
|
||||
setattr(self, _HasFieldName(field.name), False)
|
||||
self.Extensions = _ExtensionDict(self, cls._known_extensions)
|
||||
for field_name, field_value in kwargs.iteritems():
|
||||
field = _GetFieldByName(message_descriptor, field_name)
|
||||
_MergeFieldOrExtension(self, field, field_value)
|
||||
|
||||
init.__module__ = None
|
||||
init.__doc__ = None
|
||||
cls.__init__ = init
|
||||
|
||||
|
||||
def _GetFieldByName(message_descriptor, field_name):
|
||||
"""Returns a field descriptor by field name.
|
||||
|
||||
Args:
|
||||
message_descriptor: A Descriptor describing all fields in message.
|
||||
field_name: The name of the field to retrieve.
|
||||
Returns:
|
||||
The field descriptor associated with the field name.
|
||||
"""
|
||||
try:
|
||||
return message_descriptor.fields_by_name[field_name]
|
||||
except KeyError:
|
||||
raise ValueError('Protocol message has no "%s" field.' % field_name)
|
||||
|
||||
|
||||
def _AddPropertiesForFields(descriptor, cls):
|
||||
"""Adds properties for all fields in this protocol message type."""
|
||||
for field in descriptor.fields:
|
||||
@ -543,10 +562,7 @@ def _AddHasFieldMethod(cls):
|
||||
def _AddClearFieldMethod(cls):
|
||||
"""Helper for _AddMessageMethods()."""
|
||||
def ClearField(self, field_name):
|
||||
try:
|
||||
field = self.DESCRIPTOR.fields_by_name[field_name]
|
||||
except KeyError:
|
||||
raise ValueError('Protocol message has no "%s" field.' % field_name)
|
||||
field = _GetFieldByName(self.DESCRIPTOR, field_name)
|
||||
proto_field_name = field.name
|
||||
python_field_name = _ValueFieldName(proto_field_name)
|
||||
has_field_name = _HasFieldName(proto_field_name)
|
||||
@ -629,6 +645,13 @@ def _AddEqualsMethod(message_descriptor, cls):
|
||||
cls.__eq__ = __eq__
|
||||
|
||||
|
||||
def _AddStrMethod(message_descriptor, cls):
|
||||
"""Helper for _AddMessageMethods()."""
|
||||
def __str__(self):
|
||||
return text_format.MessageToString(self)
|
||||
cls.__str__ = __str__
|
||||
|
||||
|
||||
def _AddSetListenerMethod(cls):
|
||||
"""Helper for _AddMessageMethods()."""
|
||||
def SetListener(self, listener):
|
||||
@ -1090,7 +1113,7 @@ def _DeserializeOneEntity(message_descriptor, message, decoder):
|
||||
content_start = decoder.Position()
|
||||
while decoder.Position() - content_start < length:
|
||||
element_list.append(_DeserializeScalarFromDecoder(field_type, decoder))
|
||||
return decoder.Position() - content_start
|
||||
return decoder.Position() - initial_position
|
||||
else:
|
||||
# Repeated composite.
|
||||
composite = element_list.add()
|
||||
@ -1275,6 +1298,7 @@ def _AddMessageMethods(message_descriptor, cls):
|
||||
_AddClearMethod(cls)
|
||||
_AddHasExtensionMethod(cls)
|
||||
_AddEqualsMethod(message_descriptor, cls)
|
||||
_AddStrMethod(message_descriptor, cls)
|
||||
_AddSetListenerMethod(cls)
|
||||
_AddByteSizeMethod(message_descriptor, cls)
|
||||
_AddSerializeToStringMethod(message_descriptor, cls)
|
||||
@ -1436,6 +1460,20 @@ class _ExtensionDict(object):
|
||||
if extension.label != _FieldDescriptor.LABEL_REPEATED)
|
||||
self._has_bits = dict.fromkeys(keys, False)
|
||||
|
||||
self._extensions_by_number = dict(
|
||||
(f.number, f) for f in self._known_extensions.itervalues())
|
||||
|
||||
self._extensions_by_name = {}
|
||||
for extension in self._known_extensions.itervalues():
|
||||
if (extension.containing_type.GetOptions().message_set_wire_format and
|
||||
extension.type == descriptor_mod.FieldDescriptor.TYPE_MESSAGE and
|
||||
extension.message_type == extension.extension_scope and
|
||||
extension.label == descriptor_mod.FieldDescriptor.LABEL_OPTIONAL):
|
||||
extension_name = extension.message_type.full_name
|
||||
else:
|
||||
extension_name = extension.full_name
|
||||
self._extensions_by_name[extension_name] = extension
|
||||
|
||||
def __getitem__(self, extension_handle):
|
||||
"""Returns the current value of the given extension handle."""
|
||||
# We don't care as much about keeping critical sections short in the
|
||||
@ -1609,7 +1647,15 @@ class _ExtensionDict(object):
|
||||
Returns: A dict mapping field_number to (handle, field_descriptor),
|
||||
for *all* registered extensions for this dict.
|
||||
"""
|
||||
# TODO(robinson): Precompute and store this away. Note that we'll have to
|
||||
# be careful when we move away from having _known_extensions as a
|
||||
# deep-copied member of this object.
|
||||
return dict((f.number, f) for f in self._known_extensions.itervalues())
|
||||
return self._extensions_by_number
|
||||
|
||||
def _FindExtensionByName(self, name):
|
||||
"""Tries to find a known extension with the specified name.
|
||||
|
||||
Args:
|
||||
name: Extension full name.
|
||||
|
||||
Returns:
|
||||
Extension field descriptor.
|
||||
"""
|
||||
return self._extensions_by_name.get(name, None)
|
||||
|
@ -67,8 +67,6 @@ class Service(object):
|
||||
and "done" will later be called with the response value.
|
||||
|
||||
In the blocking case, RpcException will be raised on error.
|
||||
Asynchronous calls must check status via the Failed method of the
|
||||
RpcController.
|
||||
|
||||
Preconditions:
|
||||
* method_descriptor.service == GetDescriptor
|
||||
@ -82,6 +80,9 @@ class Service(object):
|
||||
Postconditions:
|
||||
* "done" will be called when the method is complete. This may be
|
||||
before CallMethod() returns or it may be at some point in the future.
|
||||
* If the RPC failed, the response value passed to "done" will be None.
|
||||
Further details about the failure can be found by querying the
|
||||
RpcController.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
@ -33,10 +33,19 @@
|
||||
__author__ = 'kenton@google.com (Kenton Varda)'
|
||||
|
||||
import cStringIO
|
||||
import re
|
||||
|
||||
from collections import deque
|
||||
from google.protobuf.internal import type_checkers
|
||||
from google.protobuf import descriptor
|
||||
|
||||
__all__ = [ 'MessageToString', 'PrintMessage', 'PrintField', 'PrintFieldValue' ]
|
||||
__all__ = [ 'MessageToString', 'PrintMessage', 'PrintField',
|
||||
'PrintFieldValue', 'Merge' ]
|
||||
|
||||
|
||||
class ParseError(Exception):
|
||||
"""Thrown in case of ASCII parsing error."""
|
||||
|
||||
|
||||
def MessageToString(message):
|
||||
out = cStringIO.StringIO()
|
||||
@ -45,6 +54,7 @@ def MessageToString(message):
|
||||
out.close()
|
||||
return result
|
||||
|
||||
|
||||
def PrintMessage(message, out, indent = 0):
|
||||
for field, value in message.ListFields():
|
||||
if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
|
||||
@ -53,6 +63,7 @@ def PrintMessage(message, out, indent = 0):
|
||||
else:
|
||||
PrintField(field, value, out, indent)
|
||||
|
||||
|
||||
def PrintField(field, value, out, indent = 0):
|
||||
"""Print a single field name/value pair. For repeated fields, the value
|
||||
should be a single element."""
|
||||
@ -82,6 +93,7 @@ def PrintField(field, value, out, indent = 0):
|
||||
PrintFieldValue(field, value, out, indent)
|
||||
out.write('\n')
|
||||
|
||||
|
||||
def PrintFieldValue(field, value, out, indent = 0):
|
||||
"""Print a single field value (not including name). For repeated fields,
|
||||
the value should be a single element."""
|
||||
@ -104,6 +116,507 @@ def PrintFieldValue(field, value, out, indent = 0):
|
||||
else:
|
||||
out.write(str(value))
|
||||
|
||||
|
||||
def Merge(text, message):
|
||||
"""Merges an ASCII representation of a protocol message into a message.
|
||||
|
||||
Args:
|
||||
text: Message ASCII representation.
|
||||
message: A protocol buffer message to merge into.
|
||||
|
||||
Raises:
|
||||
ParseError: On ASCII parsing problems.
|
||||
"""
|
||||
tokenizer = _Tokenizer(text)
|
||||
while not tokenizer.AtEnd():
|
||||
_MergeField(tokenizer, message)
|
||||
|
||||
|
||||
def _MergeField(tokenizer, message):
|
||||
"""Merges a single protocol message field into a message.
|
||||
|
||||
Args:
|
||||
tokenizer: A tokenizer to parse the field name and values.
|
||||
message: A protocol message to record the data.
|
||||
|
||||
Raises:
|
||||
ParseError: In case of ASCII parsing problems.
|
||||
"""
|
||||
message_descriptor = message.DESCRIPTOR
|
||||
if tokenizer.TryConsume('['):
|
||||
name = [tokenizer.ConsumeIdentifier()]
|
||||
while tokenizer.TryConsume('.'):
|
||||
name.append(tokenizer.ConsumeIdentifier())
|
||||
name = '.'.join(name)
|
||||
|
||||
field = message.Extensions._FindExtensionByName(name)
|
||||
if not field:
|
||||
raise tokenizer.ParseErrorPreviousToken(
|
||||
'Extension "%s" not registered.' % name)
|
||||
elif message_descriptor != field.containing_type:
|
||||
raise tokenizer.ParseErrorPreviousToken(
|
||||
'Extension "%s" does not extend message type "%s".' % (
|
||||
name, message_descriptor.full_name))
|
||||
tokenizer.Consume(']')
|
||||
else:
|
||||
name = tokenizer.ConsumeIdentifier()
|
||||
field = message_descriptor.fields_by_name.get(name, None)
|
||||
|
||||
# Group names are expected to be capitalized as they appear in the
|
||||
# .proto file, which actually matches their type names, not their field
|
||||
# names.
|
||||
if not field:
|
||||
field = message_descriptor.fields_by_name.get(name.lower(), None)
|
||||
if field and field.type != descriptor.FieldDescriptor.TYPE_GROUP:
|
||||
field = None
|
||||
|
||||
if (field and field.type == descriptor.FieldDescriptor.TYPE_GROUP and
|
||||
field.message_type.name != name):
|
||||
field = None
|
||||
|
||||
if not field:
|
||||
raise tokenizer.ParseErrorPreviousToken(
|
||||
'Message type "%s" has no field named "%s".' % (
|
||||
message_descriptor.full_name, name))
|
||||
|
||||
if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
|
||||
tokenizer.TryConsume(':')
|
||||
|
||||
if tokenizer.TryConsume('<'):
|
||||
end_token = '>'
|
||||
else:
|
||||
tokenizer.Consume('{')
|
||||
end_token = '}'
|
||||
|
||||
if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
|
||||
if field.is_extension:
|
||||
sub_message = message.Extensions[field].add()
|
||||
else:
|
||||
sub_message = getattr(message, field.name).add()
|
||||
else:
|
||||
if field.is_extension:
|
||||
sub_message = message.Extensions[field]
|
||||
else:
|
||||
sub_message = getattr(message, field.name)
|
||||
|
||||
while not tokenizer.TryConsume(end_token):
|
||||
if tokenizer.AtEnd():
|
||||
raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token))
|
||||
_MergeField(tokenizer, sub_message)
|
||||
else:
|
||||
_MergeScalarField(tokenizer, message, field)
|
||||
|
||||
|
||||
def _MergeScalarField(tokenizer, message, field):
|
||||
"""Merges a single protocol message scalar field into a message.
|
||||
|
||||
Args:
|
||||
tokenizer: A tokenizer to parse the field value.
|
||||
message: A protocol message to record the data.
|
||||
field: The descriptor of the field to be merged.
|
||||
|
||||
Raises:
|
||||
ParseError: In case of ASCII parsing problems.
|
||||
RuntimeError: On runtime errors.
|
||||
"""
|
||||
tokenizer.Consume(':')
|
||||
value = None
|
||||
|
||||
if field.type in (descriptor.FieldDescriptor.TYPE_INT32,
|
||||
descriptor.FieldDescriptor.TYPE_SINT32,
|
||||
descriptor.FieldDescriptor.TYPE_SFIXED32):
|
||||
value = tokenizer.ConsumeInt32()
|
||||
elif field.type in (descriptor.FieldDescriptor.TYPE_INT64,
|
||||
descriptor.FieldDescriptor.TYPE_SINT64,
|
||||
descriptor.FieldDescriptor.TYPE_SFIXED64):
|
||||
value = tokenizer.ConsumeInt64()
|
||||
elif field.type in (descriptor.FieldDescriptor.TYPE_UINT32,
|
||||
descriptor.FieldDescriptor.TYPE_FIXED32):
|
||||
value = tokenizer.ConsumeUint32()
|
||||
elif field.type in (descriptor.FieldDescriptor.TYPE_UINT64,
|
||||
descriptor.FieldDescriptor.TYPE_FIXED64):
|
||||
value = tokenizer.ConsumeUint64()
|
||||
elif field.type in (descriptor.FieldDescriptor.TYPE_FLOAT,
|
||||
descriptor.FieldDescriptor.TYPE_DOUBLE):
|
||||
value = tokenizer.ConsumeFloat()
|
||||
elif field.type == descriptor.FieldDescriptor.TYPE_BOOL:
|
||||
value = tokenizer.ConsumeBool()
|
||||
elif field.type == descriptor.FieldDescriptor.TYPE_STRING:
|
||||
value = tokenizer.ConsumeString()
|
||||
elif field.type == descriptor.FieldDescriptor.TYPE_BYTES:
|
||||
value = tokenizer.ConsumeByteString()
|
||||
elif field.type == descriptor.FieldDescriptor.TYPE_ENUM:
|
||||
# Enum can be specified by a number (the enum value), or by
|
||||
# a string literal (the enum name).
|
||||
enum_descriptor = field.enum_type
|
||||
if tokenizer.LookingAtInteger():
|
||||
number = tokenizer.ConsumeInt32()
|
||||
enum_value = enum_descriptor.values_by_number.get(number, None)
|
||||
if enum_value is None:
|
||||
raise tokenizer.ParseErrorPreviousToken(
|
||||
'Enum type "%s" has no value with number %d.' % (
|
||||
enum_descriptor.full_name, number))
|
||||
else:
|
||||
identifier = tokenizer.ConsumeIdentifier()
|
||||
enum_value = enum_descriptor.values_by_name.get(identifier, None)
|
||||
if enum_value is None:
|
||||
raise tokenizer.ParseErrorPreviousToken(
|
||||
'Enum type "%s" has no value named %s.' % (
|
||||
enum_descriptor.full_name, identifier))
|
||||
value = enum_value.number
|
||||
else:
|
||||
raise RuntimeError('Unknown field type %d' % field.type)
|
||||
|
||||
if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
|
||||
if field.is_extension:
|
||||
message.Extensions[field].append(value)
|
||||
else:
|
||||
getattr(message, field.name).append(value)
|
||||
else:
|
||||
if field.is_extension:
|
||||
message.Extensions[field] = value
|
||||
else:
|
||||
setattr(message, field.name, value)
|
||||
|
||||
|
||||
class _Tokenizer(object):
|
||||
"""Protocol buffer ASCII representation tokenizer.
|
||||
|
||||
This class handles the lower level string parsing by splitting it into
|
||||
meaningful tokens.
|
||||
|
||||
It was directly ported from the Java protocol buffer API.
|
||||
"""
|
||||
|
||||
_WHITESPACE = re.compile('(\\s|(#.*$))+', re.MULTILINE)
|
||||
_TOKEN = re.compile(
|
||||
'[a-zA-Z_][0-9a-zA-Z_+-]*|' # an identifier
|
||||
'[0-9+-][0-9a-zA-Z_.+-]*|' # a number
|
||||
'\"([^\"\n\\\\]|\\\\.)*(\"|\\\\?$)|' # a double-quoted string
|
||||
'\'([^\"\n\\\\]|\\\\.)*(\'|\\\\?$)') # a single-quoted string
|
||||
_IDENTIFIER = re.compile('\w+')
|
||||
_INTEGER_CHECKERS = [type_checkers.Uint32ValueChecker(),
|
||||
type_checkers.Int32ValueChecker(),
|
||||
type_checkers.Uint64ValueChecker(),
|
||||
type_checkers.Int64ValueChecker()]
|
||||
_FLOAT_INFINITY = re.compile('-?inf(inity)?f?', re.IGNORECASE)
|
||||
_FLOAT_NAN = re.compile("nanf?", re.IGNORECASE)
|
||||
|
||||
def __init__(self, text_message):
|
||||
self._text_message = text_message
|
||||
|
||||
self._position = 0
|
||||
self._line = -1
|
||||
self._column = 0
|
||||
self._token_start = None
|
||||
self.token = ''
|
||||
self._lines = deque(text_message.split('\n'))
|
||||
self._current_line = ''
|
||||
self._previous_line = 0
|
||||
self._previous_column = 0
|
||||
self._SkipWhitespace()
|
||||
self.NextToken()
|
||||
|
||||
def AtEnd(self):
|
||||
"""Checks the end of the text was reached.
|
||||
|
||||
Returns:
|
||||
True iff the end was reached.
|
||||
"""
|
||||
return not self._lines and not self._current_line
|
||||
|
||||
def _PopLine(self):
|
||||
while not self._current_line:
|
||||
if not self._lines:
|
||||
self._current_line = ''
|
||||
return
|
||||
self._line += 1
|
||||
self._column = 0
|
||||
self._current_line = self._lines.popleft()
|
||||
|
||||
def _SkipWhitespace(self):
|
||||
while True:
|
||||
self._PopLine()
|
||||
match = re.match(self._WHITESPACE, self._current_line)
|
||||
if not match:
|
||||
break
|
||||
length = len(match.group(0))
|
||||
self._current_line = self._current_line[length:]
|
||||
self._column += length
|
||||
|
||||
def TryConsume(self, token):
|
||||
"""Tries to consume a given piece of text.
|
||||
|
||||
Args:
|
||||
token: Text to consume.
|
||||
|
||||
Returns:
|
||||
True iff the text was consumed.
|
||||
"""
|
||||
if self.token == token:
|
||||
self.NextToken()
|
||||
return True
|
||||
return False
|
||||
|
||||
def Consume(self, token):
|
||||
"""Consumes a piece of text.
|
||||
|
||||
Args:
|
||||
token: Text to consume.
|
||||
|
||||
Raises:
|
||||
ParseError: If the text couldn't be consumed.
|
||||
"""
|
||||
if not self.TryConsume(token):
|
||||
raise self._ParseError('Expected "%s".' % token)
|
||||
|
||||
def LookingAtInteger(self):
|
||||
"""Checks if the current token is an integer.
|
||||
|
||||
Returns:
|
||||
True iff the current token is an integer.
|
||||
"""
|
||||
if not self.token:
|
||||
return False
|
||||
c = self.token[0]
|
||||
return (c >= '0' and c <= '9') or c == '-' or c == '+'
|
||||
|
||||
def ConsumeIdentifier(self):
|
||||
"""Consumes protocol message field identifier.
|
||||
|
||||
Returns:
|
||||
Identifier string.
|
||||
|
||||
Raises:
|
||||
ParseError: If an identifier couldn't be consumed.
|
||||
"""
|
||||
result = self.token
|
||||
if not re.match(self._IDENTIFIER, result):
|
||||
raise self._ParseError('Expected identifier.')
|
||||
self.NextToken()
|
||||
return result
|
||||
|
||||
def ConsumeInt32(self):
|
||||
"""Consumes a signed 32bit integer number.
|
||||
|
||||
Returns:
|
||||
The integer parsed.
|
||||
|
||||
Raises:
|
||||
ParseError: If a signed 32bit integer couldn't be consumed.
|
||||
"""
|
||||
try:
|
||||
result = self._ParseInteger(self.token, is_signed=True, is_long=False)
|
||||
except ValueError, e:
|
||||
raise self._IntegerParseError(e)
|
||||
self.NextToken()
|
||||
return result
|
||||
|
||||
def ConsumeUint32(self):
|
||||
"""Consumes an unsigned 32bit integer number.
|
||||
|
||||
Returns:
|
||||
The integer parsed.
|
||||
|
||||
Raises:
|
||||
ParseError: If an unsigned 32bit integer couldn't be consumed.
|
||||
"""
|
||||
try:
|
||||
result = self._ParseInteger(self.token, is_signed=False, is_long=False)
|
||||
except ValueError, e:
|
||||
raise self._IntegerParseError(e)
|
||||
self.NextToken()
|
||||
return result
|
||||
|
||||
def ConsumeInt64(self):
|
||||
"""Consumes a signed 64bit integer number.
|
||||
|
||||
Returns:
|
||||
The integer parsed.
|
||||
|
||||
Raises:
|
||||
ParseError: If a signed 64bit integer couldn't be consumed.
|
||||
"""
|
||||
try:
|
||||
result = self._ParseInteger(self.token, is_signed=True, is_long=True)
|
||||
except ValueError, e:
|
||||
raise self._IntegerParseError(e)
|
||||
self.NextToken()
|
||||
return result
|
||||
|
||||
def ConsumeUint64(self):
|
||||
"""Consumes an unsigned 64bit integer number.
|
||||
|
||||
Returns:
|
||||
The integer parsed.
|
||||
|
||||
Raises:
|
||||
ParseError: If an unsigned 64bit integer couldn't be consumed.
|
||||
"""
|
||||
try:
|
||||
result = self._ParseInteger(self.token, is_signed=False, is_long=True)
|
||||
except ValueError, e:
|
||||
raise self._IntegerParseError(e)
|
||||
self.NextToken()
|
||||
return result
|
||||
|
||||
def ConsumeFloat(self):
|
||||
"""Consumes an floating point number.
|
||||
|
||||
Returns:
|
||||
The number parsed.
|
||||
|
||||
Raises:
|
||||
ParseError: If a floating point number couldn't be consumed.
|
||||
"""
|
||||
text = self.token
|
||||
if re.match(self._FLOAT_INFINITY, text):
|
||||
self.NextToken()
|
||||
if text.startswith('-'):
|
||||
return float('-inf')
|
||||
return float('inf')
|
||||
|
||||
if re.match(self._FLOAT_NAN, text):
|
||||
self.NextToken()
|
||||
return float('nan')
|
||||
|
||||
try:
|
||||
result = float(text)
|
||||
except ValueError, e:
|
||||
raise self._FloatParseError(e)
|
||||
self.NextToken()
|
||||
return result
|
||||
|
||||
def ConsumeBool(self):
|
||||
"""Consumes a boolean value.
|
||||
|
||||
Returns:
|
||||
The bool parsed.
|
||||
|
||||
Raises:
|
||||
ParseError: If a boolean value couldn't be consumed.
|
||||
"""
|
||||
if self.token == 'true':
|
||||
self.NextToken()
|
||||
return True
|
||||
elif self.token == 'false':
|
||||
self.NextToken()
|
||||
return False
|
||||
else:
|
||||
raise self._ParseError('Expected "true" or "false".')
|
||||
|
||||
def ConsumeString(self):
|
||||
"""Consumes a string value.
|
||||
|
||||
Returns:
|
||||
The string parsed.
|
||||
|
||||
Raises:
|
||||
ParseError: If a string value couldn't be consumed.
|
||||
"""
|
||||
return unicode(self.ConsumeByteString(), 'utf-8')
|
||||
|
||||
def ConsumeByteString(self):
|
||||
"""Consumes a byte array value.
|
||||
|
||||
Returns:
|
||||
The array parsed (as a string).
|
||||
|
||||
Raises:
|
||||
ParseError: If a byte array value couldn't be consumed.
|
||||
"""
|
||||
text = self.token
|
||||
if len(text) < 1 or text[0] not in ('\'', '"'):
|
||||
raise self._ParseError('Exptected string.')
|
||||
|
||||
if len(text) < 2 or text[-1] != text[0]:
|
||||
raise self._ParseError('String missing ending quote.')
|
||||
|
||||
try:
|
||||
result = _CUnescape(text[1:-1])
|
||||
except ValueError, e:
|
||||
raise self._ParseError(str(e))
|
||||
self.NextToken()
|
||||
return result
|
||||
|
||||
def _ParseInteger(self, text, is_signed=False, is_long=False):
|
||||
"""Parses an integer.
|
||||
|
||||
Args:
|
||||
text: The text to parse.
|
||||
is_signed: True if a signed integer must be parsed.
|
||||
is_long: True if a long integer must be parsed.
|
||||
|
||||
Returns:
|
||||
The integer value.
|
||||
|
||||
Raises:
|
||||
ValueError: Thrown Iff the text is not a valid integer.
|
||||
"""
|
||||
pos = 0
|
||||
if text.startswith('-'):
|
||||
pos += 1
|
||||
|
||||
base = 10
|
||||
if text.startswith('0x', pos) or text.startswith('0X', pos):
|
||||
base = 16
|
||||
elif text.startswith('0', pos):
|
||||
base = 8
|
||||
|
||||
# Do the actual parsing. Exception handling is propagated to caller.
|
||||
result = int(text, base)
|
||||
|
||||
# Check if the integer is sane. Exceptions handled by callers.
|
||||
checker = self._INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)]
|
||||
checker.CheckValue(result)
|
||||
return result
|
||||
|
||||
def ParseErrorPreviousToken(self, message):
|
||||
"""Creates and *returns* a ParseError for the previously read token.
|
||||
|
||||
Args:
|
||||
message: A message to set for the exception.
|
||||
|
||||
Returns:
|
||||
A ParseError instance.
|
||||
"""
|
||||
return ParseError('%d:%d : %s' % (
|
||||
self._previous_line + 1, self._previous_column + 1, message))
|
||||
|
||||
def _ParseError(self, message):
|
||||
"""Creates and *returns* a ParseError for the current token."""
|
||||
return ParseError('%d:%d : %s' % (
|
||||
self._line + 1, self._column + 1, message))
|
||||
|
||||
def _IntegerParseError(self, e):
|
||||
return self._ParseError('Couldn\'t parse integer: ' + str(e))
|
||||
|
||||
def _FloatParseError(self, e):
|
||||
return self._ParseError('Couldn\'t parse number: ' + str(e))
|
||||
|
||||
def NextToken(self):
|
||||
"""Reads the next meaningful token."""
|
||||
self._previous_line = self._line
|
||||
self._previous_column = self._column
|
||||
if self.AtEnd():
|
||||
self.token = ''
|
||||
return
|
||||
self._column += len(self.token)
|
||||
|
||||
# Make sure there is data to work on.
|
||||
self._PopLine()
|
||||
|
||||
match = re.match(self._TOKEN, self._current_line)
|
||||
if match:
|
||||
token = match.group(0)
|
||||
self._current_line = self._current_line[len(token):]
|
||||
self.token = token
|
||||
else:
|
||||
self.token = self._current_line[0]
|
||||
self._current_line = self._current_line[1:]
|
||||
self._SkipWhitespace()
|
||||
|
||||
|
||||
# text.encode('string_escape') does not seem to satisfy our needs as it
|
||||
# encodes unprintable characters using two-digit hex escapes whereas our
|
||||
# C++ unescaping function allows hex escapes to be any length. So,
|
||||
@ -123,3 +636,15 @@ def _CEscape(text):
|
||||
if o >= 127 or o < 32: return "\\%03o" % o # necessary escapes
|
||||
return c
|
||||
return "".join([escape(c) for c in text])
|
||||
|
||||
|
||||
_CUNESCAPE_HEX = re.compile('\\\\x([0-9a-fA-F]{2}|[0-9a-f-A-F])')
|
||||
|
||||
|
||||
def _CUnescape(text):
|
||||
def ReplaceHex(m):
|
||||
return chr(int(m.group(0)[2:], 16))
|
||||
# This is required because the 'string_escape' encoding doesn't
|
||||
# allow single-digit hex escapes (like '\xf').
|
||||
result = _CUNESCAPE_HEX.sub(ReplaceHex, text)
|
||||
return result.decode('string_escape')
|
||||
|
@ -43,21 +43,25 @@ nobase_include_HEADERS = \
|
||||
google/protobuf/descriptor_database.h \
|
||||
google/protobuf/dynamic_message.h \
|
||||
google/protobuf/extension_set.h \
|
||||
google/protobuf/generated_message_util.h \
|
||||
google/protobuf/generated_message_reflection.h \
|
||||
google/protobuf/message.h \
|
||||
google/protobuf/message_lite.h \
|
||||
google/protobuf/reflection_ops.h \
|
||||
google/protobuf/repeated_field.h \
|
||||
google/protobuf/service.h \
|
||||
google/protobuf/text_format.h \
|
||||
google/protobuf/unknown_field_set.h \
|
||||
google/protobuf/wire_format.h \
|
||||
google/protobuf/wire_format_inl.h \
|
||||
google/protobuf/wire_format_lite.h \
|
||||
google/protobuf/wire_format_lite_inl.h \
|
||||
google/protobuf/io/coded_stream.h \
|
||||
$(GZHEADERS) \
|
||||
google/protobuf/io/printer.h \
|
||||
google/protobuf/io/tokenizer.h \
|
||||
google/protobuf/io/zero_copy_stream.h \
|
||||
google/protobuf/io/zero_copy_stream_impl.h \
|
||||
google/protobuf/io/zero_copy_stream_impl_lite.h \
|
||||
google/protobuf/compiler/code_generator.h \
|
||||
google/protobuf/compiler/command_line_interface.h \
|
||||
google/protobuf/compiler/importer.h \
|
||||
@ -68,6 +72,8 @@ nobase_include_HEADERS = \
|
||||
|
||||
lib_LTLIBRARIES = libprotobuf.la libprotoc.la
|
||||
|
||||
# TODO(kenton): Separate lite and full libraries. Also make sure lite_unittest
|
||||
# only links against the lite lib.
|
||||
libprotobuf_la_LIBADD = $(PTHREAD_LIBS)
|
||||
libprotobuf_la_LDFLAGS = -version-info 3:0:0
|
||||
libprotobuf_la_SOURCES = \
|
||||
@ -89,20 +95,25 @@ libprotobuf_la_SOURCES = \
|
||||
google/protobuf/descriptor_database.cc \
|
||||
google/protobuf/dynamic_message.cc \
|
||||
google/protobuf/extension_set.cc \
|
||||
google/protobuf/extension_set_heavy.cc \
|
||||
google/protobuf/generated_message_util.cc \
|
||||
google/protobuf/generated_message_reflection.cc \
|
||||
google/protobuf/message.cc \
|
||||
google/protobuf/message_lite.cc \
|
||||
google/protobuf/reflection_ops.cc \
|
||||
google/protobuf/repeated_field.cc \
|
||||
google/protobuf/service.cc \
|
||||
google/protobuf/text_format.cc \
|
||||
google/protobuf/unknown_field_set.cc \
|
||||
google/protobuf/wire_format.cc \
|
||||
google/protobuf/wire_format_lite.cc \
|
||||
google/protobuf/io/coded_stream.cc \
|
||||
google/protobuf/io/gzip_stream.cc \
|
||||
google/protobuf/io/printer.cc \
|
||||
google/protobuf/io/tokenizer.cc \
|
||||
google/protobuf/io/zero_copy_stream.cc \
|
||||
google/protobuf/io/zero_copy_stream_impl.cc \
|
||||
google/protobuf/io/zero_copy_stream_impl_lite.cc \
|
||||
google/protobuf/compiler/importer.cc \
|
||||
google/protobuf/compiler/parser.cc
|
||||
|
||||
@ -171,6 +182,9 @@ protoc_inputs = \
|
||||
google/protobuf/unittest_optimize_for.proto \
|
||||
google/protobuf/unittest_embed_optimize_for.proto \
|
||||
google/protobuf/unittest_custom_options.proto \
|
||||
google/protobuf/unittest_lite.proto \
|
||||
google/protobuf/unittest_import_lite.proto \
|
||||
google/protobuf/unittest_lite_imports_nonlite.proto \
|
||||
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
|
||||
|
||||
EXTRA_DIST = \
|
||||
@ -186,7 +200,14 @@ EXTRA_DIST = \
|
||||
google/protobuf/io/package_info.h \
|
||||
google/protobuf/compiler/package_info.h
|
||||
|
||||
protoc_lite_outputs = \
|
||||
google/protobuf/unittest_lite.pb.cc \
|
||||
google/protobuf/unittest_lite.pb.h \
|
||||
google/protobuf/unittest_import_lite.pb.cc \
|
||||
google/protobuf/unittest_import_lite.pb.h
|
||||
|
||||
protoc_outputs = \
|
||||
$(protoc_lite_outputs) \
|
||||
google/protobuf/unittest.pb.cc \
|
||||
google/protobuf/unittest.pb.h \
|
||||
google/protobuf/unittest_empty.pb.cc \
|
||||
@ -201,6 +222,8 @@ protoc_outputs = \
|
||||
google/protobuf/unittest_embed_optimize_for.pb.h \
|
||||
google/protobuf/unittest_custom_options.pb.cc \
|
||||
google/protobuf/unittest_custom_options.pb.h \
|
||||
google/protobuf/unittest_lite_imports_nonlite.pb.cc \
|
||||
google/protobuf/unittest_lite_imports_nonlite.pb.h \
|
||||
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \
|
||||
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h
|
||||
|
||||
@ -240,7 +263,7 @@ COMMON_TEST_SOURCES = \
|
||||
google/protobuf/testing/file.cc \
|
||||
google/protobuf/testing/file.h
|
||||
|
||||
check_PROGRAMS = protobuf-test protobuf-lazy-descriptor-test $(GZCHECKPROGRAMS)
|
||||
check_PROGRAMS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test $(GZCHECKPROGRAMS)
|
||||
protobuf_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
|
||||
$(top_builddir)/gtest/lib/libgtest.la \
|
||||
$(top_builddir)/gtest/lib/libgtest_main.la
|
||||
@ -290,6 +313,14 @@ protobuf_lazy_descriptor_test_SOURCES = \
|
||||
$(COMMON_TEST_SOURCES)
|
||||
nodist_protobuf_lazy_descriptor_test_SOURCES = $(protoc_outputs)
|
||||
|
||||
# Build lite_unittest separately, since it doesn't use gtest.
|
||||
protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la
|
||||
protobuf_lite_test_SOURCES = \
|
||||
google/protobuf/lite_unittest.cc \
|
||||
google/protobuf/test_util_lite.cc \
|
||||
google/protobuf/test_util_lite.h
|
||||
nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs)
|
||||
|
||||
if HAVE_ZLIB
|
||||
zcgzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
|
||||
zcgzip_SOURCES = google/protobuf/testing/zcgzip.cc
|
||||
@ -298,4 +329,4 @@ zcgunzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
|
||||
zcgunzip_SOURCES = google/protobuf/testing/zcgunzip.cc
|
||||
endif
|
||||
|
||||
TESTS = protobuf-test protobuf-lazy-descriptor-test $(GZTESTS)
|
||||
TESTS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test $(GZTESTS)
|
||||
|
@ -34,6 +34,8 @@
|
||||
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
@ -41,6 +43,26 @@ namespace compiler {
|
||||
CodeGenerator::~CodeGenerator() {}
|
||||
OutputDirectory::~OutputDirectory() {}
|
||||
|
||||
// Parses a set of comma-delimited name/value pairs.
|
||||
void ParseGeneratorParameter(const string& text,
|
||||
vector<pair<string, string> >* output) {
|
||||
vector<string> parts;
|
||||
SplitStringUsing(text, ",", &parts);
|
||||
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
string::size_type equals_pos = parts[i].find_first_of('=');
|
||||
pair<string, string> value;
|
||||
if (equals_pos == string::npos) {
|
||||
value.first = parts[i];
|
||||
value.second = "";
|
||||
} else {
|
||||
value.first = parts[i].substr(0, equals_pos);
|
||||
value.second = parts[i].substr(equals_pos + 1);
|
||||
}
|
||||
output->push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
@ -40,6 +40,8 @@
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
@ -105,6 +107,15 @@ class LIBPROTOC_EXPORT OutputDirectory {
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OutputDirectory);
|
||||
};
|
||||
|
||||
// Several code generators treat the parameter argument as holding a
|
||||
// list of options separated by commas. This helper function parses
|
||||
// a set of comma-delimited name/value pairs: e.g.,
|
||||
// "foo=bar,baz,qux=corge"
|
||||
// parses to the pairs:
|
||||
// ("foo", "bar"), ("baz", ""), ("qux", "corge")
|
||||
extern void ParseGeneratorParameter(const string&,
|
||||
vector<pair<string, string> >*);
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
||||
|
@ -95,24 +95,39 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
"$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n"
|
||||
"$dllexport$bool $classname$_IsValid(int value);\n"
|
||||
"const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
|
||||
"const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"
|
||||
"\n");
|
||||
|
||||
// The _Name and _Parse methods
|
||||
printer->Print(vars,
|
||||
"inline const ::std::string& $classname$_Name($classname$ value) {\n"
|
||||
" return ::google::protobuf::internal::NameOfEnum(\n"
|
||||
" $classname$_descriptor(), value);\n"
|
||||
"}\n");
|
||||
printer->Print(vars,
|
||||
"inline bool $classname$_Parse(\n"
|
||||
" const ::std::string& name, $classname$* value) {\n"
|
||||
" return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n"
|
||||
" $classname$_descriptor(), name, value);\n"
|
||||
"}\n");
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
printer->Print(vars,
|
||||
"$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n");
|
||||
// The _Name and _Parse methods
|
||||
printer->Print(vars,
|
||||
"inline const ::std::string& $classname$_Name($classname$ value) {\n"
|
||||
" return ::google::protobuf::internal::NameOfEnum(\n"
|
||||
" $classname$_descriptor(), value);\n"
|
||||
"}\n");
|
||||
printer->Print(vars,
|
||||
"inline bool $classname$_Parse(\n"
|
||||
" const ::std::string& name, $classname$* value) {\n"
|
||||
" return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n"
|
||||
" $classname$_descriptor(), name, value);\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void EnumGenerator::
|
||||
GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
printer->Print(
|
||||
"template <>\n"
|
||||
"inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
|
||||
" return $classname$_descriptor();\n"
|
||||
"}\n",
|
||||
"classname", ClassName(descriptor_, true));
|
||||
}
|
||||
}
|
||||
|
||||
void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
|
||||
@ -128,24 +143,28 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
"static inline const ::google::protobuf::EnumDescriptor*\n"
|
||||
"$nested_name$_descriptor() {\n"
|
||||
" return $classname$_descriptor();\n"
|
||||
"}\n"
|
||||
"static inline bool $nested_name$_IsValid(int value) {\n"
|
||||
" return $classname$_IsValid(value);\n"
|
||||
"}\n"
|
||||
"static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
|
||||
" return $classname$_Name(value);\n"
|
||||
"}\n"
|
||||
"static inline bool $nested_name$_Parse(const ::std::string& name,\n"
|
||||
" $nested_name$* value) {\n"
|
||||
" return $classname$_Parse(name, value);\n"
|
||||
"}\n"
|
||||
"static const $nested_name$ $nested_name$_MIN =\n"
|
||||
" $classname$_$nested_name$_MIN;\n"
|
||||
"static const $nested_name$ $nested_name$_MAX =\n"
|
||||
" $classname$_$nested_name$_MAX;\n");
|
||||
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
printer->Print(vars,
|
||||
"static inline const ::google::protobuf::EnumDescriptor*\n"
|
||||
"$nested_name$_descriptor() {\n"
|
||||
" return $classname$_descriptor();\n"
|
||||
"}\n"
|
||||
"static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n"
|
||||
" return $classname$_Name(value);\n"
|
||||
"}\n"
|
||||
"static inline bool $nested_name$_Parse(const ::std::string& name,\n"
|
||||
" $nested_name$* value) {\n"
|
||||
" return $classname$_Parse(name, value);\n"
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void EnumGenerator::GenerateDescriptorInitializer(
|
||||
@ -168,11 +187,15 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) {
|
||||
map<string, string> vars;
|
||||
vars["classname"] = classname_;
|
||||
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
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 $classname$_descriptor_;\n"
|
||||
"}\n"
|
||||
"bool $classname$_IsValid(int value) {\n"
|
||||
" switch(value) {\n");
|
||||
|
||||
|
@ -63,6 +63,10 @@ class EnumGenerator {
|
||||
// nested enums.
|
||||
void GenerateDefinition(io::Printer* printer);
|
||||
|
||||
// Generate specialization of GetEnumDescriptor<MyEnum>().
|
||||
// Precondition: in ::google::protobuf namespace.
|
||||
void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
|
||||
|
||||
// For enums nested within a message, generate code to import all the enum's
|
||||
// symbols (e.g. the enum type name, all its values, etc.) into the class's
|
||||
// namespace. This should be placed inside the class definition in the
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/wire_format_inl.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
@ -43,24 +43,14 @@ namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
using internal::WireFormat;
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
|
||||
// repeat code between this and the other field types.
|
||||
void SetEnumVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables) {
|
||||
SetCommonFieldVariables(descriptor, variables);
|
||||
const EnumValueDescriptor* default_value = descriptor->default_value_enum();
|
||||
|
||||
(*variables)["name"] = FieldName(descriptor);
|
||||
(*variables)["type"] = ClassName(descriptor->enum_type(), true);
|
||||
(*variables)["default"] = SimpleItoa(default_value->number());
|
||||
(*variables)["index"] = SimpleItoa(descriptor->index());
|
||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||
(*variables)["classname"] = ClassName(FieldScope(descriptor), false);
|
||||
(*variables)["tag_size"] = SimpleItoa(
|
||||
WireFormat::TagSize(descriptor->number(), descriptor->type()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -83,8 +73,8 @@ GeneratePrivateMembers(io::Printer* printer) const {
|
||||
void EnumFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline $type$ $name$() const;\n"
|
||||
"inline void set_$name$($type$ value);\n");
|
||||
"inline $type$ $name$() const$deprecation$;\n"
|
||||
"inline void set_$name$($type$ value)$deprecation$;\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
@ -124,33 +114,37 @@ void EnumFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"int value;\n"
|
||||
"DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n"
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n"
|
||||
"if ($type$_IsValid(value)) {\n"
|
||||
" set_$name$(static_cast< $type$ >(value));\n"
|
||||
"} else {\n"
|
||||
" mutable_unknown_fields()->AddVarint($number$, value);\n"
|
||||
" set_$name$(static_cast< $type$ >(value));\n");
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
"} else {\n"
|
||||
" mutable_unknown_fields()->AddVarint($number$, value);\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormat::WriteEnum("
|
||||
"$number$, this->$name$(), output);\n");
|
||||
"::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
|
||||
" $number$, this->$name$(), output);\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"target = ::google::protobuf::internal::WireFormat::WriteEnumToArray("
|
||||
"$number$, this->$name$(), target);\n");
|
||||
"target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
|
||||
" $number$, this->$name$(), target);\n");
|
||||
}
|
||||
|
||||
void EnumFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormat::EnumSize(this->$name$());\n");
|
||||
" ::google::protobuf::internal::WireFormatLite::EnumSize(this->$name$());\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
@ -167,8 +161,7 @@ void RepeatedEnumFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::RepeatedField<int> $name$_;\n");
|
||||
if (descriptor_->options().packed() &&
|
||||
descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
|
||||
if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
"mutable int _$name$_cached_byte_size_;\n");
|
||||
}
|
||||
@ -177,11 +170,11 @@ GeneratePrivateMembers(io::Printer* printer) const {
|
||||
void RepeatedEnumFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::RepeatedField<int>& $name$() const;\n"
|
||||
"inline ::google::protobuf::RepeatedField<int>* mutable_$name$();\n"
|
||||
"inline $type$ $name$(int index) const;\n"
|
||||
"inline void set_$name$(int index, $type$ value);\n"
|
||||
"inline void add_$name$($type$ value);\n");
|
||||
"inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
|
||||
"inline ::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n"
|
||||
"inline $type$ $name$(int index) const$deprecation$;\n"
|
||||
"inline void set_$name$(int index, $type$ value)$deprecation$;\n"
|
||||
"inline void add_$name$($type$ value)$deprecation$;\n");
|
||||
}
|
||||
|
||||
void RepeatedEnumFieldGenerator::
|
||||
@ -238,7 +231,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
"input->PushLimit(length);\n"
|
||||
"while (input->BytesUntilLimit() > 0) {\n"
|
||||
" int value;\n"
|
||||
" DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n"
|
||||
" DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n"
|
||||
" if ($type$_IsValid(value)) {\n"
|
||||
" add_$name$(static_cast< $type$ >(value));\n"
|
||||
" }\n"
|
||||
@ -247,11 +240,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"int value;\n"
|
||||
"DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n"
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n"
|
||||
"if ($type$_IsValid(value)) {\n"
|
||||
" add_$name$(static_cast< $type$ >(value));\n"
|
||||
"} else {\n"
|
||||
" mutable_unknown_fields()->AddVarint($number$, value);\n"
|
||||
" add_$name$(static_cast< $type$ >(value));\n");
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
"} else {\n"
|
||||
" mutable_unknown_fields()->AddVarint($number$, value);\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
@ -262,10 +259,10 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
// Write the tag and the size.
|
||||
printer->Print(variables_,
|
||||
"if (this->$name$_size() > 0) {\n"
|
||||
" ::google::protobuf::internal::WireFormat::WriteTag("
|
||||
"$number$, "
|
||||
"::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
|
||||
"output);\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::WriteTag(\n"
|
||||
" $number$,\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
|
||||
" output);\n"
|
||||
" output->WriteVarint32(_$name$_cached_byte_size_);\n"
|
||||
"}\n");
|
||||
}
|
||||
@ -273,12 +270,12 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
if (descriptor_->options().packed()) {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormat::WriteEnumNoTag("
|
||||
"this->$name$(i), output);\n");
|
||||
" ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n"
|
||||
" this->$name$(i), output);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormat::WriteEnum("
|
||||
"$number$, this->$name$(i), output);\n");
|
||||
" ::google::protobuf::internal::WireFormatLite::WriteEnum(\n"
|
||||
" $number$, this->$name$(i), output);\n");
|
||||
}
|
||||
printer->Print("}\n");
|
||||
}
|
||||
@ -289,24 +286,24 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
// Write the tag and the size.
|
||||
printer->Print(variables_,
|
||||
"if (this->$name$_size() > 0) {\n"
|
||||
" target = ::google::protobuf::internal::WireFormat::WriteTagToArray("
|
||||
"$number$, "
|
||||
"::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
|
||||
"target);\n"
|
||||
" target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
|
||||
" $number$,\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
|
||||
" target);\n"
|
||||
" target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
|
||||
"_$name$_cached_byte_size_, target);\n"
|
||||
" _$name$_cached_byte_size_, target);\n"
|
||||
"}\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
if (descriptor_->options().packed()) {
|
||||
printer->Print(variables_,
|
||||
" target = ::google::protobuf::internal::WireFormat::WriteEnumNoTagToArray("
|
||||
"this->$name$(i), target);\n");
|
||||
" target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n"
|
||||
" this->$name$(i), target);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" target = ::google::protobuf::internal::WireFormat::WriteEnumToArray("
|
||||
"$number$, this->$name$(i), target);\n");
|
||||
" target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n"
|
||||
" $number$, this->$name$(i), target);\n");
|
||||
}
|
||||
printer->Print("}\n");
|
||||
}
|
||||
@ -319,15 +316,15 @@ GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Indent();
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
" data_size += ::google::protobuf::internal::WireFormat::EnumSize(\n"
|
||||
" data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n"
|
||||
" this->$name$(i));\n"
|
||||
"}\n");
|
||||
|
||||
if (descriptor_->options().packed()) {
|
||||
printer->Print(variables_,
|
||||
"if (data_size > 0) {\n"
|
||||
" total_size += $tag_size$ + "
|
||||
"::google::protobuf::internal::WireFormat::Int32Size(data_size);\n"
|
||||
" total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
|
||||
"}\n"
|
||||
"_$name$_cached_byte_size_ = data_size;\n"
|
||||
"total_size += data_size;\n");
|
||||
|
@ -133,6 +133,7 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) {
|
||||
vars["global_name"] = global_name;
|
||||
printer->Print(vars,
|
||||
"const ::std::string $global_name$_default($default$);\n");
|
||||
|
||||
// Update the default to refer to the string global.
|
||||
vars["default"] = global_name + "_default";
|
||||
}
|
||||
|
@ -33,18 +33,37 @@
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_string_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
using internal::WireFormat;
|
||||
|
||||
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables) {
|
||||
(*variables)["name"] = FieldName(descriptor);
|
||||
(*variables)["index"] = SimpleItoa(descriptor->index());
|
||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||
(*variables)["classname"] = ClassName(FieldScope(descriptor), false);
|
||||
(*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
|
||||
|
||||
(*variables)["tag_size"] = SimpleItoa(
|
||||
WireFormat::TagSize(descriptor->number(), descriptor->type()));
|
||||
(*variables)["deprecation"] = descriptor->options().deprecated()
|
||||
? " DEPRECATED_PROTOBUF_FIELD" : "";
|
||||
}
|
||||
|
||||
FieldGenerator::~FieldGenerator() {}
|
||||
|
||||
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
|
||||
|
@ -35,6 +35,9 @@
|
||||
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
|
||||
#define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
@ -49,6 +52,13 @@ namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
// Helper function: set variables in the map that are the same for all
|
||||
// field code generators.
|
||||
// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
|
||||
// 'deprecation'].
|
||||
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables);
|
||||
|
||||
class FieldGenerator {
|
||||
public:
|
||||
FieldGenerator() {}
|
||||
|
@ -125,13 +125,18 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
||||
|
||||
// OK, it's now safe to #include other files.
|
||||
printer->Print(
|
||||
"#include <google/protobuf/generated_message_reflection.h>\n"
|
||||
"#include <google/protobuf/generated_message_util.h>\n"
|
||||
"#include <google/protobuf/repeated_field.h>\n"
|
||||
"#include <google/protobuf/extension_set.h>\n");
|
||||
|
||||
if (file_->service_count() > 0) {
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
printer->Print(
|
||||
"#include <google/protobuf/service.h>\n");
|
||||
"#include <google/protobuf/generated_message_reflection.h>\n");
|
||||
|
||||
if (file_->service_count() > 0) {
|
||||
printer->Print(
|
||||
"#include <google/protobuf/service.h>\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < file_->dependency_count(); i++) {
|
||||
@ -193,19 +198,21 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
||||
printer->Print(kThickSeparator);
|
||||
printer->Print("\n");
|
||||
|
||||
// Generate service definitions.
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
if (i > 0) {
|
||||
printer->Print("\n");
|
||||
printer->Print(kThinSeparator);
|
||||
printer->Print("\n");
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
// Generate service definitions.
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
if (i > 0) {
|
||||
printer->Print("\n");
|
||||
printer->Print(kThinSeparator);
|
||||
printer->Print("\n");
|
||||
}
|
||||
service_generators_[i]->GenerateDeclarations(printer);
|
||||
}
|
||||
service_generators_[i]->GenerateDeclarations(printer);
|
||||
}
|
||||
|
||||
printer->Print("\n");
|
||||
printer->Print(kThickSeparator);
|
||||
printer->Print("\n");
|
||||
printer->Print("\n");
|
||||
printer->Print(kThickSeparator);
|
||||
printer->Print("\n");
|
||||
}
|
||||
|
||||
// Declare extension identifiers.
|
||||
for (int i = 0; i < file_->extension_count(); i++) {
|
||||
@ -228,6 +235,30 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
||||
// Close up namespace.
|
||||
GenerateNamespaceClosers(printer);
|
||||
|
||||
// Emit GetEnumDescriptor specializations into google::protobuf namespace:
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
// The SWIG conditional is to avoid a null-pointer dereference
|
||||
// (bug 1984964) in swig-1.3.21 resulting from the following syntax:
|
||||
// namespace X { void Y<Z::W>(); }
|
||||
// which appears in GetEnumDescriptor() specializations.
|
||||
printer->Print(
|
||||
"\n"
|
||||
"#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++) {
|
||||
enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
|
||||
}
|
||||
printer->Print(
|
||||
"\n"
|
||||
"} // namespace google\n} // namespace protobuf\n"
|
||||
"#endif // SWIG\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
|
||||
"filename_identifier", filename_identifier);
|
||||
@ -237,40 +268,52 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
|
||||
printer->Print(
|
||||
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
||||
"\n"
|
||||
// The generated code calls accessors that might be deprecated. We don't
|
||||
// want the compiler to warn in generated code.
|
||||
"#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
|
||||
"#include \"$basename$.pb.h\"\n"
|
||||
|
||||
"#include <google/protobuf/stubs/once.h>\n"
|
||||
"#include <google/protobuf/descriptor.h>\n"
|
||||
"#include <google/protobuf/io/coded_stream.h>\n"
|
||||
"#include <google/protobuf/reflection_ops.h>\n"
|
||||
"#include <google/protobuf/wire_format_inl.h>\n",
|
||||
"#include <google/protobuf/wire_format_lite_inl.h>\n",
|
||||
"basename", StripProto(file_->name()));
|
||||
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
printer->Print(
|
||||
"#include <google/protobuf/descriptor.h>\n"
|
||||
"#include <google/protobuf/reflection_ops.h>\n"
|
||||
"#include <google/protobuf/wire_format.h>\n");
|
||||
}
|
||||
|
||||
GenerateNamespaceOpeners(printer);
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"namespace {\n"
|
||||
"\n");
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateDescriptorDeclarations(printer);
|
||||
}
|
||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
printer->Print(
|
||||
"const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
|
||||
"name", ClassName(file_->enum_type(i), false));
|
||||
}
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
"\n"
|
||||
"namespace {\n"
|
||||
"\n");
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateDescriptorDeclarations(printer);
|
||||
}
|
||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||
printer->Print(
|
||||
"const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
|
||||
"name", ClassName(file_->enum_type(i), false));
|
||||
}
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
printer->Print(
|
||||
"const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
|
||||
"name", file_->service(i)->name());
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n",
|
||||
"name", file_->service(i)->name());
|
||||
"\n"
|
||||
"} // namespace\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"} // namespace\n"
|
||||
"\n");
|
||||
|
||||
// Define our externally-visible BuildDescriptors() function.
|
||||
// Define our externally-visible BuildDescriptors() function. (For the lite
|
||||
// library, all this does is initialize default instances.)
|
||||
GenerateBuildDescriptors(printer);
|
||||
|
||||
// Generate enums.
|
||||
@ -286,12 +329,14 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
|
||||
message_generators_[i]->GenerateClassMethods(printer);
|
||||
}
|
||||
|
||||
// Generate services.
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
if (i == 0) printer->Print("\n");
|
||||
printer->Print(kThickSeparator);
|
||||
printer->Print("\n");
|
||||
service_generators_[i]->GenerateImplementation(printer);
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
// Generate services.
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
if (i == 0) printer->Print("\n");
|
||||
printer->Print(kThickSeparator);
|
||||
printer->Print("\n");
|
||||
service_generators_[i]->GenerateImplementation(printer);
|
||||
}
|
||||
}
|
||||
|
||||
// Define extensions.
|
||||
@ -317,79 +362,83 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
|
||||
// anyone calls descriptor() or GetReflection() on one of the types defined
|
||||
// in the file.
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"void $assigndescriptorsname$() {\n",
|
||||
"assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
|
||||
printer->Indent();
|
||||
// In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
|
||||
// and we only use AddDescriptors() to allocate default instances.
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
printer->Print(
|
||||
"\n"
|
||||
"void $assigndescriptorsname$() {\n",
|
||||
"assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
|
||||
printer->Indent();
|
||||
|
||||
// Make sure the file has found its way into the pool. If a descriptor
|
||||
// is requested *during* static init then AddDescriptors() may not have
|
||||
// been called yet, so we call it manually. Note that it's fine if
|
||||
// AddDescriptors() is called multiple times.
|
||||
printer->Print(
|
||||
"$adddescriptorsname$();\n",
|
||||
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
|
||||
// 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());
|
||||
// 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);
|
||||
// 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);
|
||||
}
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
service_generators_[i]->GenerateDescriptorInitializer(printer, i);
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n"
|
||||
"\n");
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
// protobuf_AssignDescriptorsOnce(): The first time it is called, calls
|
||||
// AssignDescriptors(). All later times, waits for the first call to
|
||||
// complete and then returns.
|
||||
printer->Print(
|
||||
"namespace {\n"
|
||||
"\n"
|
||||
"GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
|
||||
"inline void protobuf_AssignDescriptorsOnce() {\n"
|
||||
" ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
|
||||
" &$assigndescriptorsname$);\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
|
||||
|
||||
// protobuf_RegisterTypes(): Calls
|
||||
// MessageFactory::InternalRegisterGeneratedType() for each message type.
|
||||
printer->Print(
|
||||
"void protobuf_RegisterTypes(const ::std::string&) {\n"
|
||||
" protobuf_AssignDescriptorsOnce();\n");
|
||||
printer->Indent();
|
||||
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateTypeRegistrations(printer);
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n"
|
||||
"\n"
|
||||
"} // namespace\n");
|
||||
}
|
||||
for (int i = 0; i < file_->enum_type_count(); i++) {
|
||||
enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
|
||||
}
|
||||
for (int i = 0; i < file_->service_count(); i++) {
|
||||
service_generators_[i]->GenerateDescriptorInitializer(printer, i);
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n"
|
||||
"\n");
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
// protobuf_AssignDescriptorsOnce(): The first time it is called, calls
|
||||
// AssignDescriptors(). All later times, waits for the first call to
|
||||
// complete and then returns.
|
||||
printer->Print(
|
||||
"namespace {\n"
|
||||
"\n"
|
||||
"GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
|
||||
"inline void protobuf_AssignDescriptorsOnce() {\n"
|
||||
" ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
|
||||
" &$assigndescriptorsname$);\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
|
||||
|
||||
// protobuf_RegisterTypes(): Calls
|
||||
// MessageFactory::InternalRegisterGeneratedType() for each message type.
|
||||
printer->Print(
|
||||
"void protobuf_RegisterTypes() {\n"
|
||||
" protobuf_AssignDescriptorsOnce();\n");
|
||||
printer->Indent();
|
||||
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
message_generators_[i]->GenerateTypeRegistrations(printer);
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n"
|
||||
"\n"
|
||||
"} // namespace\n");
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
@ -442,32 +491,34 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
|
||||
"name", GlobalAddDescriptorsName(dependency->name()));
|
||||
}
|
||||
|
||||
// Embed the descriptor. We simply serialize the entire FileDescriptorProto
|
||||
// and embed it as a string literal, which is parsed and built into real
|
||||
// descriptors at initialization time.
|
||||
FileDescriptorProto file_proto;
|
||||
file_->CopyTo(&file_proto);
|
||||
string file_data;
|
||||
file_proto.SerializeToString(&file_data);
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
// Embed the descriptor. We simply serialize the entire FileDescriptorProto
|
||||
// and embed it as a string literal, which is parsed and built into real
|
||||
// descriptors at initialization time.
|
||||
FileDescriptorProto file_proto;
|
||||
file_->CopyTo(&file_proto);
|
||||
string file_data;
|
||||
file_proto.SerializeToString(&file_data);
|
||||
|
||||
printer->Print(
|
||||
"::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
|
||||
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", CEscape(file_data.substr(i, kBytesPerLine)));
|
||||
// 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", CEscape(file_data.substr(i, kBytesPerLine)));
|
||||
}
|
||||
printer->Print(
|
||||
", $size$);\n",
|
||||
"size", SimpleItoa(file_data.size()));
|
||||
|
||||
// Call MessageFactory::InternalRegisterGeneratedFile().
|
||||
printer->Print(
|
||||
"::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
|
||||
" \"$filename$\", &protobuf_RegisterTypes);\n",
|
||||
"filename", file_->name());
|
||||
}
|
||||
printer->Print(
|
||||
", $size$);\n",
|
||||
"size", SimpleItoa(file_data.size()));
|
||||
|
||||
// Call MessageFactory::InternalRegisterGeneratedFile().
|
||||
printer->Print(
|
||||
"::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n"
|
||||
" \"$filename$\", &protobuf_RegisterTypes);\n",
|
||||
"filename", file_->name());
|
||||
|
||||
// Allocate and initialize default instances. This can't be done lazily
|
||||
// since default instances are returned by simple accessors and are used with
|
||||
|
@ -42,39 +42,12 @@
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
namespace {
|
||||
|
||||
// Parses a set of comma-delimited name/value pairs, e.g.:
|
||||
// "foo=bar,baz,qux=corge"
|
||||
// parses to the pairs:
|
||||
// ("foo", "bar"), ("baz", ""), ("qux", "corge")
|
||||
void ParseOptions(const string& text, vector<pair<string, string> >* output) {
|
||||
vector<string> parts;
|
||||
SplitStringUsing(text, ",", &parts);
|
||||
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
string::size_type equals_pos = parts[i].find_first_of('=');
|
||||
pair<string, string> value;
|
||||
if (equals_pos == string::npos) {
|
||||
value.first = parts[i];
|
||||
value.second = "";
|
||||
} else {
|
||||
value.first = parts[i].substr(0, equals_pos);
|
||||
value.second = parts[i].substr(equals_pos + 1);
|
||||
}
|
||||
output->push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
CppGenerator::CppGenerator() {}
|
||||
CppGenerator::~CppGenerator() {}
|
||||
|
||||
@ -83,7 +56,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
|
||||
OutputDirectory* output_directory,
|
||||
string* error) const {
|
||||
vector<pair<string, string> > options;
|
||||
ParseOptions(parameter, &options);
|
||||
ParseGeneratorParameter(parameter, &options);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// parse generator options
|
||||
|
@ -152,7 +152,18 @@ string FieldName(const FieldDescriptor* field) {
|
||||
|
||||
string FieldConstantName(const FieldDescriptor *field) {
|
||||
string field_name = UnderscoresToCamelCase(field->name(), true);
|
||||
return "k" + field_name + "FieldNumber";
|
||||
string result = "k" + field_name + "FieldNumber";
|
||||
|
||||
if (!field->is_extension() &&
|
||||
field->containing_type()->FindFieldByCamelcaseName(
|
||||
field->camelcase_name()) != field) {
|
||||
// This field's camelcase name is not unique. As a hack, add the field
|
||||
// number to the constant name. This makes the constant rather useless,
|
||||
// but what can we do?
|
||||
result += "_" + SimpleItoa(field->number());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
string StripProto(const string& filename) {
|
||||
|
@ -37,6 +37,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
@ -105,6 +106,34 @@ string GlobalAssignDescriptorsName(const string& filename);
|
||||
// Return the name of the ShutdownFile() function for a given file.
|
||||
string GlobalShutdownFileName(const string& filename);
|
||||
|
||||
// Do message classes in this file keep track of unknown fields?
|
||||
inline const bool HasUnknownFields(const FileDescriptor *file) {
|
||||
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
// Does this file have generated parsing, serialization, and other
|
||||
// standard methods for which reflection-based fallback implementations exist?
|
||||
inline const bool HasGeneratedMethods(const FileDescriptor *file) {
|
||||
return file->options().optimize_for() != FileOptions::CODE_SIZE;
|
||||
}
|
||||
|
||||
// Do message classes in this file have descriptor and refelction methods?
|
||||
inline const bool HasDescriptorMethods(const FileDescriptor *file) {
|
||||
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
// Should string fields in this file verify that their contents are UTF-8?
|
||||
inline const bool HasUtf8Verification(const FileDescriptor* file) {
|
||||
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
// Should we generate a separate, super-optimized code path for serializing to
|
||||
// flat arrays? We don't do this in Lite mode because we'd rather reduce code
|
||||
// size.
|
||||
inline const bool HasFastArraySerialization(const FileDescriptor* file) {
|
||||
return file->options().optimize_for() == FileOptions::SPEED;
|
||||
}
|
||||
|
||||
} // namespace cpp
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
@ -34,14 +34,17 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <google/protobuf/stubs/hash.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <google/protobuf/compiler/cpp/cpp_message.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_enum.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_extension.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_inl.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
|
||||
namespace google {
|
||||
@ -50,6 +53,7 @@ namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
using internal::WireFormat;
|
||||
using internal::WireFormatLite;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -195,6 +199,16 @@ GenerateEnumDefinitions(io::Printer* printer) {
|
||||
}
|
||||
}
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
|
||||
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
||||
nested_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
|
||||
}
|
||||
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
|
||||
enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
|
||||
}
|
||||
}
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateFieldAccessorDeclarations(io::Printer* printer) {
|
||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||
@ -203,17 +217,16 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
|
||||
PrintFieldComment(printer, field);
|
||||
|
||||
map<string, string> vars;
|
||||
vars["name"] = FieldName(field);
|
||||
SetCommonFieldVariables(field, &vars);
|
||||
vars["constant_name"] = FieldConstantName(field);
|
||||
vars["number"] = SimpleItoa(field->number());
|
||||
|
||||
if (field->is_repeated()) {
|
||||
printer->Print(vars, "inline int $name$_size() const;\n");
|
||||
printer->Print(vars, "inline int $name$_size() const$deprecation$;\n");
|
||||
} else {
|
||||
printer->Print(vars, "inline bool has_$name$() const;\n");
|
||||
printer->Print(vars, "inline bool has_$name$() const$deprecation$;\n");
|
||||
}
|
||||
|
||||
printer->Print(vars, "inline void clear_$name$();\n");
|
||||
printer->Print(vars, "inline void clear_$name$()$deprecation$;\n");
|
||||
printer->Print(vars, "static const int $constant_name$ = $number$;\n");
|
||||
|
||||
// Generate type-specific accessor declarations.
|
||||
@ -241,9 +254,7 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
|
||||
PrintFieldComment(printer, field);
|
||||
|
||||
map<string, string> vars;
|
||||
vars["name"] = FieldName(field);
|
||||
vars["index"] = SimpleItoa(field->index());
|
||||
vars["classname"] = classname_;
|
||||
SetCommonFieldVariables(field, &vars);
|
||||
|
||||
// Generate has_$name$() or $name$_size().
|
||||
if (field->is_repeated()) {
|
||||
@ -297,9 +308,11 @@ GenerateClassDefinition(io::Printer* printer) {
|
||||
} else {
|
||||
vars["dllexport"] = dllexport_decl_ + " ";
|
||||
}
|
||||
vars["superclass"] = HasDescriptorMethods(descriptor_->file()) ?
|
||||
"Message" : "MessageLite";
|
||||
|
||||
printer->Print(vars,
|
||||
"class $dllexport$$classname$ : public ::google::protobuf::Message {\n"
|
||||
"class $dllexport$$classname$ : public ::google::protobuf::$superclass$ {\n"
|
||||
" public:\n");
|
||||
printer->Indent();
|
||||
|
||||
@ -313,16 +326,28 @@ GenerateClassDefinition(io::Printer* printer) {
|
||||
" CopyFrom(from);\n"
|
||||
" return *this;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
|
||||
" return _unknown_fields_;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n"
|
||||
" return &_unknown_fields_;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"static const ::google::protobuf::Descriptor* descriptor();\n"
|
||||
"\n");
|
||||
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
printer->Print(
|
||||
"inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
|
||||
" return _unknown_fields_;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n"
|
||||
" return &_unknown_fields_;\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
// Only generate this member if it's not disabled.
|
||||
if (HasDescriptorMethods(descriptor_->file()) &&
|
||||
!descriptor_->options().no_standard_descriptor_accessor()) {
|
||||
printer->Print(vars,
|
||||
"static const ::google::protobuf::Descriptor* descriptor();\n");
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
"static const $classname$& default_instance();\n"
|
||||
"void Swap($classname$* other);\n"
|
||||
"\n"
|
||||
@ -330,28 +355,29 @@ GenerateClassDefinition(io::Printer* printer) {
|
||||
"\n"
|
||||
"$classname$* New() const;\n");
|
||||
|
||||
if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
|
||||
if (HasGeneratedMethods(descriptor_->file())) {
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
printer->Print(vars,
|
||||
"void CopyFrom(const ::google::protobuf::Message& from);\n"
|
||||
"void MergeFrom(const ::google::protobuf::Message& from);\n");
|
||||
} else {
|
||||
printer->Print(vars,
|
||||
"void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);\n");
|
||||
}
|
||||
|
||||
printer->Print(vars,
|
||||
"void CopyFrom(const ::google::protobuf::Message& from);\n"
|
||||
"void MergeFrom(const ::google::protobuf::Message& from);\n"
|
||||
"void CopyFrom(const $classname$& from);\n"
|
||||
"void MergeFrom(const $classname$& from);\n"
|
||||
"void Clear();\n"
|
||||
"bool IsInitialized() const;\n");
|
||||
|
||||
if (!descriptor_->options().message_set_wire_format()) {
|
||||
// For message_set_wire_format, we don't generate parsing or
|
||||
// serialization code even if optimize_for = SPEED, since MessageSet
|
||||
// encoding is somewhat more complicated than normal extension encoding
|
||||
// and we'd like to avoid having to implement it in multiple places.
|
||||
// WireFormat's implementation is probably good enough.
|
||||
printer->Print(vars,
|
||||
"\n"
|
||||
"int ByteSize() const;\n"
|
||||
"bool MergePartialFromCodedStream(\n"
|
||||
" ::google::protobuf::io::CodedInputStream* input);\n"
|
||||
"void SerializeWithCachedSizes(\n"
|
||||
" ::google::protobuf::io::CodedOutputStream* output) const;\n"
|
||||
"bool IsInitialized() const;\n"
|
||||
"\n"
|
||||
"int ByteSize() const;\n"
|
||||
"bool MergePartialFromCodedStream(\n"
|
||||
" ::google::protobuf::io::CodedInputStream* input);\n"
|
||||
"void SerializeWithCachedSizes(\n"
|
||||
" ::google::protobuf::io::CodedOutputStream* output) const;\n");
|
||||
if (HasFastArraySerialization(descriptor_->file())) {
|
||||
printer->Print(
|
||||
"::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n");
|
||||
}
|
||||
}
|
||||
@ -363,10 +389,19 @@ GenerateClassDefinition(io::Printer* printer) {
|
||||
"void SharedDtor();\n"
|
||||
"void SetCachedSize(int size) const { _cached_size_ = size; }\n"
|
||||
"public:\n"
|
||||
"\n"
|
||||
"const ::google::protobuf::Descriptor* GetDescriptor() const;\n"
|
||||
"const ::google::protobuf::Reflection* GetReflection() const;\n"
|
||||
"\n"
|
||||
"\n");
|
||||
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
printer->Print(
|
||||
"::google::protobuf::Metadata GetMetadata() const;\n"
|
||||
"\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"::std::string GetTypeName() const;\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"// nested types ----------------------------------------------------\n"
|
||||
"\n");
|
||||
|
||||
@ -411,9 +446,13 @@ GenerateClassDefinition(io::Printer* printer) {
|
||||
"::google::protobuf::internal::ExtensionSet _extensions_;\n");
|
||||
}
|
||||
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
printer->Print(
|
||||
"::google::protobuf::UnknownFieldSet _unknown_fields_;\n");
|
||||
}
|
||||
|
||||
// TODO(kenton): Make _cached_size_ an atomic<int> when C++ supports it.
|
||||
printer->Print(
|
||||
"::google::protobuf::UnknownFieldSet _unknown_fields_;\n"
|
||||
"mutable int _cached_size_;\n"
|
||||
"\n");
|
||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||
@ -431,7 +470,8 @@ GenerateClassDefinition(io::Printer* printer) {
|
||||
GlobalAddDescriptorsName(descriptor_->file()->name()));
|
||||
printer->Print(
|
||||
"friend void $assigndescriptorsname$();\n"
|
||||
"friend void $shutdownfilename$();\n",
|
||||
"friend void $shutdownfilename$();\n"
|
||||
"\n",
|
||||
"assigndescriptorsname",
|
||||
GlobalAssignDescriptorsName(descriptor_->file()->name()),
|
||||
"shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name()));
|
||||
@ -605,10 +645,15 @@ GenerateDefaultInstanceInitializer(io::Printer* printer) {
|
||||
void MessageGenerator::
|
||||
GenerateShutdownCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
"delete $classname$::default_instance_;\n"
|
||||
"delete $classname$_reflection_;\n",
|
||||
"delete $classname$::default_instance_;\n",
|
||||
"classname", classname_);
|
||||
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
printer->Print(
|
||||
"delete $classname$_reflection_;\n",
|
||||
"classname", classname_);
|
||||
}
|
||||
|
||||
// Handle nested types.
|
||||
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
||||
nested_generators_[i]->GenerateShutdownCode(printer);
|
||||
@ -655,29 +700,24 @@ GenerateClassMethods(io::Printer* printer) {
|
||||
GenerateStructors(printer);
|
||||
printer->Print("\n");
|
||||
|
||||
if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
|
||||
if (HasGeneratedMethods(descriptor_->file())) {
|
||||
GenerateClear(printer);
|
||||
printer->Print("\n");
|
||||
|
||||
if (!descriptor_->options().message_set_wire_format()) {
|
||||
// For message_set_wire_format, we don't generate parsing or
|
||||
// serialization code even if optimize_for = SPEED, since MessageSet
|
||||
// encoding is somewhat more complicated than normal extension encoding
|
||||
// and we'd like to avoid having to implement it in multiple places.
|
||||
// WireFormat's implementation is probably good enough.
|
||||
GenerateMergeFromCodedStream(printer);
|
||||
printer->Print("\n");
|
||||
GenerateMergeFromCodedStream(printer);
|
||||
printer->Print("\n");
|
||||
|
||||
GenerateSerializeWithCachedSizes(printer);
|
||||
printer->Print("\n");
|
||||
GenerateSerializeWithCachedSizes(printer);
|
||||
printer->Print("\n");
|
||||
|
||||
if (HasFastArraySerialization(descriptor_->file())) {
|
||||
GenerateSerializeWithCachedSizesToArray(printer);
|
||||
printer->Print("\n");
|
||||
|
||||
GenerateByteSize(printer);
|
||||
printer->Print("\n");
|
||||
}
|
||||
|
||||
GenerateByteSize(printer);
|
||||
printer->Print("\n");
|
||||
|
||||
GenerateMergeFrom(printer);
|
||||
printer->Print("\n");
|
||||
|
||||
@ -691,16 +731,26 @@ GenerateClassMethods(io::Printer* printer) {
|
||||
GenerateSwap(printer);
|
||||
printer->Print("\n");
|
||||
|
||||
printer->Print(
|
||||
"const ::google::protobuf::Descriptor* $classname$::GetDescriptor() const {\n"
|
||||
" return descriptor();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"const ::google::protobuf::Reflection* $classname$::GetReflection() const {\n"
|
||||
" protobuf_AssignDescriptorsOnce();\n"
|
||||
" return $classname$_reflection_;\n"
|
||||
"}\n",
|
||||
"classname", classname_);
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
printer->Print(
|
||||
"::google::protobuf::Metadata $classname$::GetMetadata() const {\n"
|
||||
" protobuf_AssignDescriptorsOnce();\n"
|
||||
" ::google::protobuf::Metadata metadata;\n"
|
||||
" metadata.descriptor = $classname$_descriptor_;\n"
|
||||
" metadata.reflection = $classname$_reflection_;\n"
|
||||
" return metadata;\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", classname_);
|
||||
} else {
|
||||
printer->Print(
|
||||
"::std::string $classname$::GetTypeName() const {\n"
|
||||
" return \"$type_name$\";\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", classname_,
|
||||
"type_name", descriptor_->full_name());
|
||||
}
|
||||
}
|
||||
|
||||
void MessageGenerator::
|
||||
@ -723,18 +773,6 @@ GenerateOffsets(io::Printer* printer) {
|
||||
printer->Print("};\n");
|
||||
}
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateInitializerList(io::Printer* printer) {
|
||||
printer->Indent();
|
||||
printer->Indent();
|
||||
|
||||
printer->Print(
|
||||
"::google::protobuf::Message()");
|
||||
|
||||
printer->Outdent();
|
||||
printer->Outdent();
|
||||
}
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateSharedConstructorCode(io::Printer* printer) {
|
||||
printer->Print(
|
||||
@ -797,17 +835,14 @@ void MessageGenerator::
|
||||
GenerateStructors(io::Printer* printer) {
|
||||
// Generate the default constructor.
|
||||
printer->Print(
|
||||
"$classname$::$classname$()\n"
|
||||
" : ",
|
||||
"classname", classname_);
|
||||
GenerateInitializerList(printer);
|
||||
printer->Print(" {\n"
|
||||
"$classname$::$classname$() {\n"
|
||||
" SharedCtor();\n"
|
||||
"}\n");
|
||||
"}\n",
|
||||
"classname", classname_);
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"void $classname$::InitAsDefaultInstance() {",
|
||||
"void $classname$::InitAsDefaultInstance() {\n",
|
||||
"classname", classname_);
|
||||
|
||||
// The default instance needs all of its embedded message pointers
|
||||
@ -833,15 +868,12 @@ GenerateStructors(io::Printer* printer) {
|
||||
|
||||
// Generate the copy constructor.
|
||||
printer->Print(
|
||||
"$classname$::$classname$(const $classname$& from)\n"
|
||||
" : ",
|
||||
"classname", classname_);
|
||||
GenerateInitializerList(printer);
|
||||
printer->Print(" {\n"
|
||||
"$classname$::$classname$(const $classname$& from) {\n"
|
||||
" SharedCtor();\n"
|
||||
" MergeFrom(from);\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
"\n",
|
||||
"classname", classname_);
|
||||
|
||||
// Generate the shared constructor code.
|
||||
GenerateSharedConstructorCode(printer);
|
||||
@ -857,12 +889,21 @@ GenerateStructors(io::Printer* printer) {
|
||||
// Generate the shared destructor code.
|
||||
GenerateSharedDestructorCode(printer);
|
||||
|
||||
// Only generate this member if it's not disabled.
|
||||
if (HasDescriptorMethods(descriptor_->file()) &&
|
||||
!descriptor_->options().no_standard_descriptor_accessor()) {
|
||||
printer->Print(
|
||||
"const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
|
||||
" protobuf_AssignDescriptorsOnce();\n"
|
||||
" return $classname$_descriptor_;\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", classname_,
|
||||
"adddescriptorsname",
|
||||
GlobalAddDescriptorsName(descriptor_->file()->name()));
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
|
||||
" protobuf_AssignDescriptorsOnce();\n"
|
||||
" return $classname$_descriptor_;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"const $classname$& $classname$::default_instance() {\n"
|
||||
" if (default_instance_ == NULL) $adddescriptorsname$();"
|
||||
" return *default_instance_;\n"
|
||||
@ -951,8 +992,12 @@ GenerateClear(io::Printer* printer) {
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"::memset(_has_bits_, 0, sizeof(_has_bits_));\n"
|
||||
"mutable_unknown_fields()->Clear();\n");
|
||||
"::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
|
||||
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
printer->Print(
|
||||
"mutable_unknown_fields()->Clear();\n");
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
@ -967,7 +1012,7 @@ GenerateSwap(io::Printer* printer) {
|
||||
printer->Print("if (other != this) {\n");
|
||||
printer->Indent();
|
||||
|
||||
if ( descriptor_->file()->options().optimize_for() == FileOptions::SPEED ) {
|
||||
if (HasGeneratedMethods(descriptor_->file())) {
|
||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||
const FieldDescriptor* field = descriptor_->field(i);
|
||||
field_generators_.get(field).GenerateSwappingCode(printer);
|
||||
@ -978,7 +1023,9 @@ GenerateSwap(io::Printer* printer) {
|
||||
"i", SimpleItoa(i));
|
||||
}
|
||||
|
||||
printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
|
||||
}
|
||||
printer->Print("std::swap(_cached_size_, other->_cached_size_);\n");
|
||||
if (descriptor_->extension_range_count() > 0) {
|
||||
printer->Print("_extensions_.Swap(&other->_extensions_);\n");
|
||||
@ -987,7 +1034,6 @@ GenerateSwap(io::Printer* printer) {
|
||||
printer->Print("GetReflection()->Swap(this, other);");
|
||||
}
|
||||
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
printer->Outdent();
|
||||
@ -996,31 +1042,42 @@ GenerateSwap(io::Printer* printer) {
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateMergeFrom(io::Printer* printer) {
|
||||
// Generate the generalized MergeFrom (aka that which takes in the Message
|
||||
// base class as a parameter).
|
||||
printer->Print(
|
||||
"void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
|
||||
" GOOGLE_CHECK_NE(&from, this);\n",
|
||||
"classname", classname_);
|
||||
printer->Indent();
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
// Generate the generalized MergeFrom (aka that which takes in the Message
|
||||
// base class as a parameter).
|
||||
printer->Print(
|
||||
"void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
|
||||
" GOOGLE_CHECK_NE(&from, this);\n",
|
||||
"classname", classname_);
|
||||
printer->Indent();
|
||||
|
||||
// Cast the message to the proper type. If we find that the message is
|
||||
// *not* of the proper type, we can still call Merge via the reflection
|
||||
// system, as the GOOGLE_CHECK above ensured that we have the same descriptor
|
||||
// for each message.
|
||||
printer->Print(
|
||||
"const $classname$* source =\n"
|
||||
" ::google::protobuf::internal::dynamic_cast_if_available<const $classname$*>(\n"
|
||||
" &from);\n"
|
||||
"if (source == NULL) {\n"
|
||||
" ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
|
||||
"} else {\n"
|
||||
" MergeFrom(*source);\n"
|
||||
"}\n",
|
||||
"classname", classname_);
|
||||
// Cast the message to the proper type. If we find that the message is
|
||||
// *not* of the proper type, we can still call Merge via the reflection
|
||||
// system, as the GOOGLE_CHECK above ensured that we have the same descriptor
|
||||
// for each message.
|
||||
printer->Print(
|
||||
"const $classname$* source =\n"
|
||||
" ::google::protobuf::internal::dynamic_cast_if_available<const $classname$*>(\n"
|
||||
" &from);\n"
|
||||
"if (source == NULL) {\n"
|
||||
" ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
|
||||
"} else {\n"
|
||||
" MergeFrom(*source);\n"
|
||||
"}\n",
|
||||
"classname", classname_);
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("}\n\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n\n");
|
||||
} else {
|
||||
// Generate CheckTypeAndMergeFrom().
|
||||
printer->Print(
|
||||
"void $classname$::CheckTypeAndMergeFrom(\n"
|
||||
" const ::google::protobuf::MessageLite& from) {\n"
|
||||
" MergeFrom(*::google::protobuf::down_cast<const $classname$*>(&from));\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", classname_);
|
||||
}
|
||||
|
||||
// Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
|
||||
printer->Print(
|
||||
@ -1082,8 +1139,10 @@ GenerateMergeFrom(io::Printer* printer) {
|
||||
printer->Print("_extensions_.MergeFrom(from._extensions_);\n");
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n");
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
printer->Print(
|
||||
"mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n");
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
@ -1091,20 +1150,22 @@ GenerateMergeFrom(io::Printer* printer) {
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateCopyFrom(io::Printer* printer) {
|
||||
// Generate the generalized CopyFrom (aka that which takes in the Message
|
||||
// base class as a parameter).
|
||||
printer->Print(
|
||||
"void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n",
|
||||
"classname", classname_);
|
||||
printer->Indent();
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
// Generate the generalized CopyFrom (aka that which takes in the Message
|
||||
// base class as a parameter).
|
||||
printer->Print(
|
||||
"void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n",
|
||||
"classname", classname_);
|
||||
printer->Indent();
|
||||
|
||||
printer->Print(
|
||||
"if (&from == this) return;\n"
|
||||
"Clear();\n"
|
||||
"MergeFrom(from);\n");
|
||||
printer->Print(
|
||||
"if (&from == this) return;\n"
|
||||
"Clear();\n"
|
||||
"MergeFrom(from);\n");
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("}\n\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n\n");
|
||||
}
|
||||
|
||||
// Generate the class-specific CopyFrom.
|
||||
printer->Print(
|
||||
@ -1123,6 +1184,18 @@ GenerateCopyFrom(io::Printer* printer) {
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) {
|
||||
if (descriptor_->options().message_set_wire_format()) {
|
||||
// Special-case MessageSet.
|
||||
printer->Print(
|
||||
"bool $classname$::MergePartialFromCodedStream(\n"
|
||||
" ::google::protobuf::io::CodedInputStream* input) {\n"
|
||||
" return _extensions_.ParseMessageSet(input, default_instance_,\n"
|
||||
" mutable_unknown_fields());\n"
|
||||
"}\n",
|
||||
"classname", classname_);
|
||||
return;
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"bool $classname$::MergePartialFromCodedStream(\n"
|
||||
" ::google::protobuf::io::CodedInputStream* input) {\n"
|
||||
@ -1144,7 +1217,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
|
||||
// creates a jump table that is 8x larger and sparser, and meanwhile the
|
||||
// if()s are highly predictable.
|
||||
printer->Print(
|
||||
"switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {\n");
|
||||
"switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {\n");
|
||||
|
||||
printer->Indent();
|
||||
|
||||
@ -1158,8 +1231,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
|
||||
|
||||
printer->Print(
|
||||
"case $number$: {\n"
|
||||
" if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=\n"
|
||||
" ::google::protobuf::internal::WireFormat::WIRETYPE_$wiretype$) {\n"
|
||||
" if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_$wiretype$) {\n"
|
||||
" goto handle_uninterpreted;\n"
|
||||
" }\n",
|
||||
"number", SimpleItoa(field->number()),
|
||||
@ -1214,8 +1287,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
|
||||
|
||||
// Is this an end-group tag? If so, this must be the end of the message.
|
||||
printer->Print(
|
||||
"if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==\n"
|
||||
" ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {\n"
|
||||
"if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n"
|
||||
" return true;\n"
|
||||
"}\n");
|
||||
|
||||
@ -1228,10 +1301,10 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
|
||||
descriptor_->extension_range(i);
|
||||
if (i > 0) printer->Print(" ||\n ");
|
||||
|
||||
uint32 start_tag = WireFormat::MakeTag(
|
||||
range->start, static_cast<WireFormat::WireType>(0));
|
||||
uint32 end_tag = WireFormat::MakeTag(
|
||||
range->end, static_cast<WireFormat::WireType>(0));
|
||||
uint32 start_tag = WireFormatLite::MakeTag(
|
||||
range->start, static_cast<WireFormatLite::WireType>(0));
|
||||
uint32 end_tag = WireFormatLite::MakeTag(
|
||||
range->end, static_cast<WireFormatLite::WireType>(0));
|
||||
|
||||
if (range->end > FieldDescriptor::kMaxNumber) {
|
||||
printer->Print(
|
||||
@ -1244,17 +1317,29 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
|
||||
"end", SimpleItoa(end_tag));
|
||||
}
|
||||
}
|
||||
printer->Print(") {\n"
|
||||
" DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
|
||||
" mutable_unknown_fields()));\n"
|
||||
printer->Print(") {\n");
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
printer->Print(
|
||||
" DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
|
||||
" mutable_unknown_fields()));\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
" DO_(_extensions_.ParseField(tag, input, default_instance_));\n");
|
||||
}
|
||||
printer->Print(
|
||||
" continue;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
// We really don't recognize this tag. Skip it.
|
||||
printer->Print(
|
||||
"DO_(::google::protobuf::internal::WireFormat::SkipField(\n"
|
||||
" input, tag, mutable_unknown_fields()));\n");
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
printer->Print(
|
||||
"DO_(::google::protobuf::internal::WireFormat::SkipField(\n"
|
||||
" input, tag, mutable_unknown_fields()));\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n");
|
||||
}
|
||||
|
||||
if (descriptor_->field_count() > 0) {
|
||||
printer->Print("break;\n");
|
||||
@ -1319,21 +1404,41 @@ void MessageGenerator::GenerateSerializeOneExtensionRange(
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) {
|
||||
if (descriptor_->options().message_set_wire_format()) {
|
||||
// Special-case MessageSet.
|
||||
printer->Print(
|
||||
"void $classname$::SerializeWithCachedSizes(\n"
|
||||
" ::google::protobuf::io::CodedOutputStream* output) const {\n"
|
||||
" _extensions_.SerializeMessageSetWithCachedSizes(output);\n",
|
||||
"classname", classname_);
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
printer->Print(
|
||||
" ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n"
|
||||
" unknown_fields(), output);\n");
|
||||
}
|
||||
printer->Print(
|
||||
"}\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"void $classname$::SerializeWithCachedSizes(\n"
|
||||
" ::google::protobuf::io::CodedOutputStream* output) const {\n",
|
||||
"classname", classname_);
|
||||
printer->Indent();
|
||||
|
||||
printer->Print(
|
||||
"::google::protobuf::uint8* raw_buffer = "
|
||||
"output->GetDirectBufferForNBytesAndAdvance(_cached_size_);\n"
|
||||
"if (raw_buffer != NULL) {\n"
|
||||
" $classname$::SerializeWithCachedSizesToArray(raw_buffer);\n"
|
||||
" return;\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", classname_);
|
||||
if (HasFastArraySerialization(descriptor_->file())) {
|
||||
printer->Print(
|
||||
"::google::protobuf::uint8* raw_buffer = "
|
||||
"output->GetDirectBufferForNBytesAndAdvance(_cached_size_);\n"
|
||||
"if (raw_buffer != NULL) {\n"
|
||||
" $classname$::SerializeWithCachedSizesToArray(raw_buffer);\n"
|
||||
" return;\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", classname_);
|
||||
}
|
||||
|
||||
GenerateSerializeWithCachedSizesBody(printer, false);
|
||||
|
||||
printer->Outdent();
|
||||
@ -1343,6 +1448,26 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) {
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) {
|
||||
if (descriptor_->options().message_set_wire_format()) {
|
||||
// Special-case MessageSet.
|
||||
printer->Print(
|
||||
"::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
|
||||
" ::google::protobuf::uint8* target) const {\n"
|
||||
" target =\n"
|
||||
" _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n",
|
||||
"classname", classname_);
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
printer->Print(
|
||||
" target = ::google::protobuf::internal::WireFormat::\n"
|
||||
" SerializeUnknownMessageSetItemsToArray(\n"
|
||||
" unknown_fields(), target);\n");
|
||||
}
|
||||
printer->Print(
|
||||
" return target;\n"
|
||||
"}\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
|
||||
" ::google::protobuf::uint8* target) const {\n",
|
||||
@ -1389,26 +1514,46 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
|
||||
}
|
||||
}
|
||||
|
||||
printer->Print("if (!unknown_fields().empty()) {\n");
|
||||
printer->Indent();
|
||||
if (to_array) {
|
||||
printer->Print(
|
||||
"target = "
|
||||
"::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
|
||||
" unknown_fields(), target);\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
|
||||
" unknown_fields(), output);\n");
|
||||
}
|
||||
printer->Outdent();
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
printer->Print("if (!unknown_fields().empty()) {\n");
|
||||
printer->Indent();
|
||||
if (to_array) {
|
||||
printer->Print(
|
||||
"target = "
|
||||
"::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
|
||||
" unknown_fields(), target);\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
|
||||
" unknown_fields(), output);\n");
|
||||
}
|
||||
printer->Outdent();
|
||||
|
||||
printer->Print(
|
||||
"}\n");
|
||||
printer->Print(
|
||||
"}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MessageGenerator::
|
||||
GenerateByteSize(io::Printer* printer) {
|
||||
if (descriptor_->options().message_set_wire_format()) {
|
||||
// Special-case MessageSet.
|
||||
printer->Print(
|
||||
"int $classname$::ByteSize() const {\n"
|
||||
" int total_size = _extensions_.MessageSetByteSize();\n",
|
||||
"classname", classname_);
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
printer->Print(
|
||||
" total_size += ::google::protobuf::internal::WireFormat::\n"
|
||||
" ComputeUnknownMessageSetItemsSize(unknown_fields());\n");
|
||||
}
|
||||
printer->Print(
|
||||
" _cached_size_ = total_size;\n"
|
||||
" return total_size;\n"
|
||||
"}\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"int $classname$::ByteSize() const {\n",
|
||||
"classname", classname_);
|
||||
@ -1478,14 +1623,16 @@ GenerateByteSize(io::Printer* printer) {
|
||||
"\n");
|
||||
}
|
||||
|
||||
printer->Print("if (!unknown_fields().empty()) {\n");
|
||||
printer->Indent();
|
||||
printer->Print(
|
||||
"total_size +=\n"
|
||||
" ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
|
||||
" unknown_fields());\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
if (HasUnknownFields(descriptor_->file())) {
|
||||
printer->Print("if (!unknown_fields().empty()) {\n");
|
||||
printer->Indent();
|
||||
printer->Print(
|
||||
"total_size +=\n"
|
||||
" ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
|
||||
" unknown_fields());\n");
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
// We update _cached_size_ even though this is a const method. In theory,
|
||||
// this is not thread-compatible, because concurrent writes have undefined
|
||||
|
@ -69,6 +69,10 @@ class MessageGenerator {
|
||||
// definitions because those classes use the enums definitions).
|
||||
void GenerateEnumDefinitions(io::Printer* printer);
|
||||
|
||||
// Generate specializations of GetEnumDescriptor<MyEnum>().
|
||||
// Precondition: in ::google::protobuf namespace.
|
||||
void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
|
||||
|
||||
// Generate definitions for this class and all its nested types.
|
||||
void GenerateClassDefinition(io::Printer* printer);
|
||||
|
||||
@ -125,11 +129,6 @@ class MessageGenerator {
|
||||
// Generate the shared destructor code.
|
||||
void GenerateSharedDestructorCode(io::Printer* printer);
|
||||
|
||||
// Generate the member initializer list for the constructors. The member
|
||||
// initializer list is shared between the default constructor and the copy
|
||||
// constructor.
|
||||
void GenerateInitializerList(io::Printer* printer);
|
||||
|
||||
// Generate standard Message methods.
|
||||
void GenerateClear(io::Printer* printer);
|
||||
void GenerateMergeFromCodedStream(io::Printer* printer);
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include <google/protobuf/compiler/cpp/cpp_message_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/wire_format_inl.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
@ -43,22 +42,12 @@ namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
using internal::WireFormat;
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
|
||||
// repeat code between this and the other field types.
|
||||
void SetMessageVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables) {
|
||||
(*variables)["name"] = FieldName(descriptor);
|
||||
SetCommonFieldVariables(descriptor, variables);
|
||||
(*variables)["type"] = ClassName(descriptor->message_type(), true);
|
||||
(*variables)["index"] = SimpleItoa(descriptor->index());
|
||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||
(*variables)["classname"] = ClassName(FieldScope(descriptor), false);
|
||||
(*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
|
||||
(*variables)["tag_size"] = SimpleItoa(
|
||||
WireFormat::TagSize(descriptor->number(), descriptor->type()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -81,8 +70,8 @@ GeneratePrivateMembers(io::Printer* printer) const {
|
||||
void MessageFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline const $type$& $name$() const;\n"
|
||||
"inline $type$* mutable_$name$();\n");
|
||||
"inline const $type$& $name$() const$deprecation$;\n"
|
||||
"inline $type$* mutable_$name$()$deprecation$;\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
@ -124,35 +113,35 @@ void MessageFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(\n"
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
|
||||
" input, mutable_$name$()));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormat::ReadGroupNoVirtual("
|
||||
"$number$, input, mutable_$name$()));\n");
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
|
||||
" $number$, input, mutable_$name$()));\n");
|
||||
}
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual("
|
||||
"$number$, this->$name$(), output);\n");
|
||||
"::google::protobuf::internal::WireFormatLite::Write$declared_type$NoVirtual(\n"
|
||||
" $number$, this->$name$(), output);\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"target = ::google::protobuf::internal::WireFormat::"
|
||||
"Write$declared_type$NoVirtualToArray("
|
||||
"$number$, this->$name$(), target);\n");
|
||||
"target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$NoVirtualToArray(\n"
|
||||
" $number$, this->$name$(), target);\n");
|
||||
}
|
||||
|
||||
void MessageFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormat::$declared_type$SizeNoVirtual(\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
|
||||
" this->$name$());\n");
|
||||
}
|
||||
|
||||
@ -175,11 +164,13 @@ GeneratePrivateMembers(io::Printer* printer) const {
|
||||
void RepeatedMessageFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::RepeatedPtrField< $type$ >& $name$() const;\n"
|
||||
"inline ::google::protobuf::RepeatedPtrField< $type$ >* mutable_$name$();\n"
|
||||
"inline const $type$& $name$(int index) const;\n"
|
||||
"inline $type$* mutable_$name$(int index);\n"
|
||||
"inline $type$* add_$name$();\n");
|
||||
"inline const ::google::protobuf::RepeatedPtrField< $type$ >& $name$() const"
|
||||
"$deprecation$;\n"
|
||||
"inline ::google::protobuf::RepeatedPtrField< $type$ >* mutable_$name$()"
|
||||
"$deprecation$;\n"
|
||||
"inline const $type$& $name$(int index) const$deprecation$;\n"
|
||||
"inline $type$* mutable_$name$(int index)$deprecation$;\n"
|
||||
"inline $type$* add_$name$()$deprecation$;\n");
|
||||
}
|
||||
|
||||
void RepeatedMessageFieldGenerator::
|
||||
@ -228,12 +219,12 @@ void RepeatedMessageFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(\n"
|
||||
" input, add_$name$()));\n");
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
|
||||
" input, add_$name$()));\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormat::ReadGroupNoVirtual("
|
||||
"$number$, input, add_$name$()));\n");
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
|
||||
" $number$, input, add_$name$()));\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,8 +232,8 @@ void RepeatedMessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
" ::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual("
|
||||
"$number$, this->$name$(i), output);\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoVirtual(\n"
|
||||
" $number$, this->$name$(i), output);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
@ -250,9 +241,9 @@ void RepeatedMessageFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
" target = ::google::protobuf::internal::WireFormat::"
|
||||
"Write$declared_type$NoVirtualToArray("
|
||||
"$number$, this->$name$(i), target);\n"
|
||||
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$NoVirtualToArray(\n"
|
||||
" $number$, this->$name$(i), target);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
@ -262,7 +253,7 @@ GenerateByteSize(io::Printer* printer) const {
|
||||
"total_size += $tag_size$ * this->$name$_size();\n"
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
" total_size +=\n"
|
||||
" ::google::protobuf::internal::WireFormat::$declared_type$SizeNoVirtual(\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
|
||||
" this->$name$(i));\n"
|
||||
"}\n");
|
||||
}
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/wire_format_inl.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
@ -43,7 +43,7 @@ namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
using internal::WireFormat;
|
||||
using internal::WireFormatLite;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -57,14 +57,14 @@ int FixedSize(FieldDescriptor::Type type) {
|
||||
case FieldDescriptor::TYPE_UINT64 : return -1;
|
||||
case FieldDescriptor::TYPE_SINT32 : return -1;
|
||||
case FieldDescriptor::TYPE_SINT64 : return -1;
|
||||
case FieldDescriptor::TYPE_FIXED32 : return WireFormat::kFixed32Size;
|
||||
case FieldDescriptor::TYPE_FIXED64 : return WireFormat::kFixed64Size;
|
||||
case FieldDescriptor::TYPE_SFIXED32: return WireFormat::kSFixed32Size;
|
||||
case FieldDescriptor::TYPE_SFIXED64: return WireFormat::kSFixed64Size;
|
||||
case FieldDescriptor::TYPE_FLOAT : return WireFormat::kFloatSize;
|
||||
case FieldDescriptor::TYPE_DOUBLE : return WireFormat::kDoubleSize;
|
||||
case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
|
||||
case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
|
||||
case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
|
||||
case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
|
||||
case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
|
||||
case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
|
||||
|
||||
case FieldDescriptor::TYPE_BOOL : return WireFormat::kBoolSize;
|
||||
case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize;
|
||||
case FieldDescriptor::TYPE_ENUM : return -1;
|
||||
|
||||
case FieldDescriptor::TYPE_STRING : return -1;
|
||||
@ -79,20 +79,11 @@ int FixedSize(FieldDescriptor::Type type) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
|
||||
// repeat code between this and the other field types.
|
||||
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables) {
|
||||
(*variables)["name"] = FieldName(descriptor);
|
||||
SetCommonFieldVariables(descriptor, variables);
|
||||
(*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
|
||||
(*variables)["default"] = DefaultValue(descriptor);
|
||||
(*variables)["index"] = SimpleItoa(descriptor->index());
|
||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||
(*variables)["classname"] = ClassName(FieldScope(descriptor), false);
|
||||
(*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
|
||||
(*variables)["tag_size"] = SimpleItoa(
|
||||
WireFormat::TagSize(descriptor->number(), descriptor->type()));
|
||||
|
||||
int fixed_size = FixedSize(descriptor->type());
|
||||
if (fixed_size != -1) {
|
||||
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
|
||||
@ -119,8 +110,8 @@ GeneratePrivateMembers(io::Printer* printer) const {
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline $type$ $name$() const;\n"
|
||||
"inline void set_$name$($type$ value);\n");
|
||||
"inline $type$ $name$() const$deprecation$;\n"
|
||||
"inline void set_$name$($type$ value)$deprecation$;\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
@ -158,7 +149,7 @@ GenerateConstructorCode(io::Printer* printer) const {
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(\n"
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
|
||||
" input, &$name$_));\n"
|
||||
"_set_bit($index$);\n");
|
||||
}
|
||||
@ -166,14 +157,14 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormat::Write$declared_type$("
|
||||
"::google::protobuf::internal::WireFormatLite::Write$declared_type$("
|
||||
"$number$, this->$name$(), output);\n");
|
||||
}
|
||||
|
||||
void PrimitiveFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"target = ::google::protobuf::internal::WireFormat::Write$declared_type$ToArray("
|
||||
"target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray("
|
||||
"$number$, this->$name$(), target);\n");
|
||||
}
|
||||
|
||||
@ -183,7 +174,7 @@ GenerateByteSize(io::Printer* printer) const {
|
||||
if (fixed_size == -1) {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormat::$declared_type$Size(\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
|
||||
" this->$name$());\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
@ -205,8 +196,7 @@ void RepeatedPrimitiveFieldGenerator::
|
||||
GeneratePrivateMembers(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::RepeatedField< $type$ > $name$_;\n");
|
||||
if (descriptor_->options().packed() &&
|
||||
descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
|
||||
if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) {
|
||||
printer->Print(variables_,
|
||||
"mutable int _$name$_cached_byte_size_;\n");
|
||||
}
|
||||
@ -215,11 +205,12 @@ GeneratePrivateMembers(io::Printer* printer) const {
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::RepeatedField< $type$ >& $name$() const;\n"
|
||||
"inline ::google::protobuf::RepeatedField< $type$ >* mutable_$name$();\n"
|
||||
"inline $type$ $name$(int index) const;\n"
|
||||
"inline void set_$name$(int index, $type$ value);\n"
|
||||
"inline void add_$name$($type$ value);\n");
|
||||
"inline const ::google::protobuf::RepeatedField< $type$ >& $name$() const\n"
|
||||
" $deprecation$;\n"
|
||||
"inline ::google::protobuf::RepeatedField< $type$ >* mutable_$name$()$deprecation$;\n"
|
||||
"inline $type$ $name$(int index) const$deprecation$;\n"
|
||||
"inline void set_$name$(int index, $type$ value)$deprecation$;\n"
|
||||
"inline void add_$name$($type$ value)$deprecation$;\n");
|
||||
}
|
||||
|
||||
void RepeatedPrimitiveFieldGenerator::
|
||||
@ -272,12 +263,12 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::uint32 length;\n"
|
||||
"DO_(input->ReadVarint32(&length));\n"
|
||||
"::google::protobuf::io::CodedInputStream::Limit limit = "
|
||||
"input->PushLimit(length);\n"
|
||||
"::google::protobuf::io::CodedInputStream::Limit limit =\n"
|
||||
" input->PushLimit(length);\n"
|
||||
"while (input->BytesUntilLimit() > 0) {\n"
|
||||
" $type$ value;\n"
|
||||
" DO_(::google::protobuf::internal::WireFormat::Read$declared_type$("
|
||||
"input, &value));\n"
|
||||
" DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
|
||||
" input, &value));\n"
|
||||
" add_$name$(value);\n"
|
||||
"}\n"
|
||||
"input->PopLimit(limit);\n");
|
||||
@ -286,8 +277,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"$type$ value;\n"
|
||||
"DO_(::google::protobuf::internal::WireFormat::Read$declared_type$("
|
||||
"input, &value));\n"
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
|
||||
" input, &value));\n"
|
||||
"add_$name$(value);\n");
|
||||
}
|
||||
}
|
||||
@ -298,9 +289,9 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
// Write the tag and the size.
|
||||
printer->Print(variables_,
|
||||
"if (this->$name$_size() > 0) {\n"
|
||||
" ::google::protobuf::internal::WireFormat::WriteTag("
|
||||
" ::google::protobuf::internal::WireFormatLite::WriteTag("
|
||||
"$number$, "
|
||||
"::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
|
||||
"::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
|
||||
"output);\n"
|
||||
" output->WriteVarint32(_$name$_cached_byte_size_);\n"
|
||||
"}\n");
|
||||
@ -309,12 +300,12 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
if (descriptor_->options().packed()) {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormat::Write$declared_type$NoTag("
|
||||
"this->$name$(i), output);\n");
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
|
||||
" this->$name$(i), output);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormat::Write$declared_type$("
|
||||
"$number$, this->$name$(i), output);\n");
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
|
||||
" $number$, this->$name$(i), output);\n");
|
||||
}
|
||||
printer->Print("}\n");
|
||||
}
|
||||
@ -325,26 +316,24 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
// Write the tag and the size.
|
||||
printer->Print(variables_,
|
||||
"if (this->$name$_size() > 0) {\n"
|
||||
" target = ::google::protobuf::internal::WireFormat::WriteTagToArray("
|
||||
"$number$, "
|
||||
"::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, "
|
||||
"target);\n"
|
||||
" target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
|
||||
"_$name$_cached_byte_size_, target);\n"
|
||||
" target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
|
||||
" $number$,\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
|
||||
" target);\n"
|
||||
" target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n"
|
||||
" _$name$_cached_byte_size_, target);\n"
|
||||
"}\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
if (descriptor_->options().packed()) {
|
||||
printer->Print(variables_,
|
||||
" target = ::google::protobuf::internal::WireFormat::"
|
||||
"Write$declared_type$NoTagToArray("
|
||||
"this->$name$(i), target);\n");
|
||||
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$NoTagToArray(this->$name$(i), target);\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" target = ::google::protobuf::internal::WireFormat::"
|
||||
"Write$declared_type$ToArray("
|
||||
"$number$, this->$name$(i), target);\n");
|
||||
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$ToArray($number$, this->$name$(i), target);\n");
|
||||
}
|
||||
printer->Print("}\n");
|
||||
}
|
||||
@ -359,8 +348,8 @@ GenerateByteSize(io::Printer* printer) const {
|
||||
if (fixed_size == -1) {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
" data_size += ::google::protobuf::internal::WireFormat::$declared_type$Size(\n"
|
||||
" this->$name$(i));\n"
|
||||
" data_size += ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" $declared_type$Size(this->$name$(i));\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
@ -370,8 +359,8 @@ GenerateByteSize(io::Printer* printer) const {
|
||||
if (descriptor_->options().packed()) {
|
||||
printer->Print(variables_,
|
||||
"if (data_size > 0) {\n"
|
||||
" total_size += $tag_size$ + "
|
||||
"::google::protobuf::internal::WireFormat::Int32Size(data_size);\n"
|
||||
" total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
|
||||
"}\n"
|
||||
"_$name$_cached_byte_size_ = data_size;\n"
|
||||
"total_size += data_size;\n");
|
||||
|
@ -249,7 +249,7 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
|
||||
sub_vars["input_type"] = ClassName(method->input_type(), true);
|
||||
sub_vars["output_type"] = ClassName(method->output_type(), true);
|
||||
|
||||
// Note: ::google::protobuf::down_cast does not work here because it only works on pointers,
|
||||
// Note: down_cast does not work here because it only works on pointers,
|
||||
// not references.
|
||||
printer->Print(sub_vars,
|
||||
" case $index$:\n"
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include <google/protobuf/compiler/cpp/cpp_string_field.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/wire_format_inl.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
@ -44,23 +43,13 @@ namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace cpp {
|
||||
|
||||
using internal::WireFormat;
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
|
||||
// repeat code between this and the other field types.
|
||||
void SetStringVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables) {
|
||||
(*variables)["name"] = FieldName(descriptor);
|
||||
SetCommonFieldVariables(descriptor, variables);
|
||||
(*variables)["default"] =
|
||||
"\"" + CEscape(descriptor->default_value_string()) + "\"";
|
||||
(*variables)["index"] = SimpleItoa(descriptor->index());
|
||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||
(*variables)["classname"] = ClassName(FieldScope(descriptor), false);
|
||||
(*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
|
||||
(*variables)["tag_size"] = SimpleItoa(
|
||||
WireFormat::TagSize(descriptor->number(), descriptor->type()));
|
||||
(*variables)["pointer_type"] =
|
||||
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
|
||||
}
|
||||
@ -111,11 +100,12 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
}
|
||||
|
||||
printer->Print(variables_,
|
||||
"inline const ::std::string& $name$() const;\n"
|
||||
"inline void set_$name$(const ::std::string& value);\n"
|
||||
"inline void set_$name$(const char* value);\n"
|
||||
"inline void set_$name$(const $pointer_type$* value, size_t size);\n"
|
||||
"inline ::std::string* mutable_$name$();\n");
|
||||
"inline const ::std::string& $name$() const$deprecation$;\n"
|
||||
"inline void set_$name$(const ::std::string& value)$deprecation$;\n"
|
||||
"inline void set_$name$(const char* value)$deprecation$;\n"
|
||||
"inline void set_$name$(const $pointer_type$* value, size_t size)"
|
||||
"$deprecation$;\n"
|
||||
"inline ::std::string* mutable_$name$()$deprecation$;\n");
|
||||
|
||||
if (descriptor_->options().has_ctype()) {
|
||||
printer->Outdent();
|
||||
@ -221,29 +211,52 @@ GenerateDestructorCode(io::Printer* printer) const {
|
||||
void StringFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormat::Read$declared_type$("
|
||||
"input, mutable_$name$()));\n");
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
|
||||
" input, this->mutable_$name$()));\n");
|
||||
if (HasUtf8Verification(descriptor_->file()) &&
|
||||
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||
" this->$name$().data(), this->$name$().length(),\n"
|
||||
" ::google::protobuf::internal::WireFormat::PARSE);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
if (HasUtf8Verification(descriptor_->file()) &&
|
||||
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||
" this->$name$().data(), this->$name$().length(),\n"
|
||||
" ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormat::Write$declared_type$("
|
||||
"$number$, this->$name$(), output);\n");
|
||||
"::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
|
||||
" $number$, this->$name$(), output);\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
if (HasUtf8Verification(descriptor_->file()) &&
|
||||
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||
" this->$name$().data(), this->$name$().length(),\n"
|
||||
" ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
"target = ::google::protobuf::internal::WireFormat::Write$declared_type$ToArray("
|
||||
"$number$, this->$name$(), target);\n");
|
||||
"target =\n"
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(\n"
|
||||
" $number$, this->$name$(), target);\n");
|
||||
}
|
||||
|
||||
void StringFieldGenerator::
|
||||
GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ +\n"
|
||||
" ::google::protobuf::internal::WireFormat::$declared_type$Size(this->$name$());\n");
|
||||
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
|
||||
" this->$name$());\n");
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
@ -274,18 +287,22 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
|
||||
}
|
||||
|
||||
printer->Print(variables_,
|
||||
"inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const;\n"
|
||||
"inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$();\n"
|
||||
"inline const ::std::string& $name$(int index) const;\n"
|
||||
"inline ::std::string* mutable_$name$(int index);\n"
|
||||
"inline void set_$name$(int index, const ::std::string& value);\n"
|
||||
"inline void set_$name$(int index, const char* value);\n"
|
||||
"inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
|
||||
"$deprecation$;\n"
|
||||
"inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
|
||||
"$deprecation$;\n"
|
||||
"inline const ::std::string& $name$(int index) const$deprecation$;\n"
|
||||
"inline ::std::string* mutable_$name$(int index)$deprecation$;\n"
|
||||
"inline void set_$name$(int index, const ::std::string& value)$deprecation$;\n"
|
||||
"inline void set_$name$(int index, const char* value)$deprecation$;\n"
|
||||
"inline "
|
||||
"void set_$name$(int index, const $pointer_type$* value, size_t size);\n"
|
||||
"inline ::std::string* add_$name$();\n"
|
||||
"inline void add_$name$(const ::std::string& value);\n"
|
||||
"inline void add_$name$(const char* value);\n"
|
||||
"inline void add_$name$(const $pointer_type$* value, size_t size);\n");
|
||||
"void set_$name$(int index, const $pointer_type$* value, size_t size)"
|
||||
"$deprecation$;\n"
|
||||
"inline ::std::string* add_$name$()$deprecation$;\n"
|
||||
"inline void add_$name$(const ::std::string& value)$deprecation$;\n"
|
||||
"inline void add_$name$(const char* value)$deprecation$;\n"
|
||||
"inline void add_$name$(const $pointer_type$* value, size_t size)"
|
||||
"$deprecation$;\n");
|
||||
|
||||
if (descriptor_->options().has_ctype()) {
|
||||
printer->Outdent();
|
||||
@ -361,26 +378,48 @@ GenerateConstructorCode(io::Printer* printer) const {
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateMergeFromCodedStream(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(\n"
|
||||
" input, add_$name$()));\n");
|
||||
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
|
||||
" input, this->add_$name$()));\n");
|
||||
if (HasUtf8Verification(descriptor_->file()) &&
|
||||
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||
" this->$name$(0).data(), this->$name$(0).length(),\n"
|
||||
" ::google::protobuf::internal::WireFormat::PARSE);\n");
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
" ::google::protobuf::internal::WireFormat::Write$declared_type$("
|
||||
"$number$, this->$name$(i), output);\n"
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
if (HasUtf8Verification(descriptor_->file()) &&
|
||||
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
printer->Print(variables_,
|
||||
"::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||
" this->$name$(i).data(), this->$name$(i).length(),\n"
|
||||
" ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
|
||||
" $number$, this->$name$(i), output);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
void RepeatedStringFieldGenerator::
|
||||
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
" target = ::google::protobuf::internal::WireFormat::"
|
||||
"Write$declared_type$ToArray("
|
||||
"$number$, this->$name$(i), target);\n"
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n");
|
||||
if (HasUtf8Verification(descriptor_->file()) &&
|
||||
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
|
||||
printer->Print(variables_,
|
||||
" ::google::protobuf::internal::WireFormat::VerifyUTF8String(\n"
|
||||
" this->$name$(i).data(), this->$name$(i).length(),\n"
|
||||
" ::google::protobuf::internal::WireFormat::SERIALIZE);\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" target = ::google::protobuf::internal::WireFormatLite::\n"
|
||||
" Write$declared_type$ToArray($number$, this->$name$(i), target);\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
@ -389,7 +428,7 @@ GenerateByteSize(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"total_size += $tag_size$ * this->$name$_size();\n"
|
||||
"for (int i = 0; i < this->$name$_size(); i++) {\n"
|
||||
" total_size += ::google::protobuf::internal::WireFormat::$declared_type$Size(\n"
|
||||
" total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
|
||||
" this->$name$(i));\n"
|
||||
"}\n");
|
||||
}
|
||||
|
@ -50,11 +50,9 @@
|
||||
#include <google/protobuf/unittest_optimize_for.pb.h>
|
||||
#include <google/protobuf/unittest_embed_optimize_for.pb.h>
|
||||
#include <google/protobuf/test_util.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
|
||||
#include <google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h>
|
||||
#include <google/protobuf/compiler/importer.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/io/tokenizer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
@ -75,18 +73,6 @@ namespace cpp {
|
||||
// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
|
||||
namespace cpp_unittest {
|
||||
|
||||
TEST(ExtremeDefaultValues, FloatingPoint) {
|
||||
const unittest::TestExtremeDefaultValues& extreme_default =
|
||||
unittest::TestExtremeDefaultValues::default_instance();
|
||||
|
||||
EXPECT_EQ(0.0f, extreme_default.zero_float());
|
||||
EXPECT_EQ(1.0f, extreme_default.one_float());
|
||||
EXPECT_EQ(1.5f, extreme_default.small_float());
|
||||
EXPECT_EQ(-1.0f, extreme_default.negative_one_float());
|
||||
EXPECT_EQ(-1.5f, extreme_default.negative_float());
|
||||
EXPECT_EQ(2.0e8f, extreme_default.large_float());
|
||||
EXPECT_EQ(-8e-28f, extreme_default.small_negative_float());
|
||||
}
|
||||
|
||||
class MockErrorCollector : public MultiFileErrorCollector {
|
||||
public:
|
||||
@ -157,6 +143,19 @@ TEST(GeneratedMessageTest, Defaults) {
|
||||
&message.optional_import_message());
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageTest, FloatingPointDefaults) {
|
||||
const unittest::TestExtremeDefaultValues& extreme_default =
|
||||
unittest::TestExtremeDefaultValues::default_instance();
|
||||
|
||||
EXPECT_EQ(0.0f, extreme_default.zero_float());
|
||||
EXPECT_EQ(1.0f, extreme_default.one_float());
|
||||
EXPECT_EQ(1.5f, extreme_default.small_float());
|
||||
EXPECT_EQ(-1.0f, extreme_default.negative_one_float());
|
||||
EXPECT_EQ(-1.5f, extreme_default.negative_float());
|
||||
EXPECT_EQ(2.0e8f, extreme_default.large_float());
|
||||
EXPECT_EQ(-8e-28f, extreme_default.small_negative_float());
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageTest, Accessors) {
|
||||
// Set every field to a unique value then go back and check all those
|
||||
// values.
|
||||
@ -710,6 +709,32 @@ TEST(GeneratedMessageTest, TestSpaceUsed) {
|
||||
|
||||
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
|
||||
|
||||
TEST(GeneratedMessageTest, FieldConstantValues) {
|
||||
unittest::TestRequired message;
|
||||
EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1);
|
||||
EXPECT_EQ(unittest::TestAllTypes::kOptionalInt32FieldNumber, 1);
|
||||
EXPECT_EQ(unittest::TestAllTypes::kOptionalgroupFieldNumber, 16);
|
||||
EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedMessageFieldNumber, 18);
|
||||
EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedEnumFieldNumber, 21);
|
||||
EXPECT_EQ(unittest::TestAllTypes::kRepeatedInt32FieldNumber, 31);
|
||||
EXPECT_EQ(unittest::TestAllTypes::kRepeatedgroupFieldNumber, 46);
|
||||
EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedMessageFieldNumber, 48);
|
||||
EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedEnumFieldNumber, 51);
|
||||
}
|
||||
|
||||
TEST(GeneratedMessageTest, ExtensionConstantValues) {
|
||||
EXPECT_EQ(unittest::TestRequired::kSingleFieldNumber, 1000);
|
||||
EXPECT_EQ(unittest::TestRequired::kMultiFieldNumber, 1001);
|
||||
EXPECT_EQ(unittest::kOptionalInt32ExtensionFieldNumber, 1);
|
||||
EXPECT_EQ(unittest::kOptionalgroupExtensionFieldNumber, 16);
|
||||
EXPECT_EQ(unittest::kOptionalNestedMessageExtensionFieldNumber, 18);
|
||||
EXPECT_EQ(unittest::kOptionalNestedEnumExtensionFieldNumber, 21);
|
||||
EXPECT_EQ(unittest::kRepeatedInt32ExtensionFieldNumber, 31);
|
||||
EXPECT_EQ(unittest::kRepeatedgroupExtensionFieldNumber, 46);
|
||||
EXPECT_EQ(unittest::kRepeatedNestedMessageExtensionFieldNumber, 48);
|
||||
EXPECT_EQ(unittest::kRepeatedNestedEnumExtensionFieldNumber, 51);
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) {
|
||||
@ -803,6 +828,17 @@ TEST(GeneratedEnumTest, Parse) {
|
||||
EXPECT_FALSE(unittest::TestEnumWithDupValue_Parse("FOO", &dup_value));
|
||||
}
|
||||
|
||||
TEST(GeneratedEnumTest, GetEnumDescriptor) {
|
||||
EXPECT_EQ(unittest::TestAllTypes::NestedEnum_descriptor(),
|
||||
GetEnumDescriptor<unittest::TestAllTypes::NestedEnum>());
|
||||
EXPECT_EQ(unittest::ForeignEnum_descriptor(),
|
||||
GetEnumDescriptor<unittest::ForeignEnum>());
|
||||
EXPECT_EQ(unittest::TestEnumWithDupValue_descriptor(),
|
||||
GetEnumDescriptor<unittest::TestEnumWithDupValue>());
|
||||
EXPECT_EQ(unittest::TestSparseEnum_descriptor(),
|
||||
GetEnumDescriptor<unittest::TestSparseEnum>());
|
||||
}
|
||||
|
||||
#endif // PROTOBUF_TEST_NO_DESCRIPTORS
|
||||
|
||||
// ===================================================================
|
||||
|
@ -67,14 +67,17 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor)
|
||||
EnumGenerator::~EnumGenerator() {}
|
||||
|
||||
void EnumGenerator::Generate(io::Printer* printer) {
|
||||
bool is_own_file =
|
||||
descriptor_->containing_type() == NULL &&
|
||||
descriptor_->file()->options().java_multiple_files();
|
||||
printer->Print(
|
||||
"public $static$ enum $classname$\n"
|
||||
" implements com.google.protobuf.ProtocolMessageEnum {\n",
|
||||
"static", is_own_file ? "" : "static",
|
||||
"classname", descriptor_->name());
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
printer->Print(
|
||||
"public enum $classname$\n"
|
||||
" implements com.google.protobuf.ProtocolMessageEnum {\n",
|
||||
"classname", descriptor_->name());
|
||||
} else {
|
||||
printer->Print(
|
||||
"public enum $classname$\n"
|
||||
" implements com.google.protobuf.Internal.EnumLite {\n",
|
||||
"classname", descriptor_->name());
|
||||
}
|
||||
printer->Indent();
|
||||
|
||||
for (int i = 0; i < canonical_values_.size(); i++) {
|
||||
@ -126,63 +129,78 @@ void EnumGenerator::Generate(io::Printer* printer) {
|
||||
" default: return null;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
"\n"
|
||||
"public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n"
|
||||
" internalGetValueMap() {\n"
|
||||
" return internalValueMap;\n"
|
||||
"}\n"
|
||||
"private static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n"
|
||||
" internalValueMap =\n"
|
||||
" new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
|
||||
" public $classname$ findValueByNumber(int number) {\n"
|
||||
" return $classname$.valueOf(number)\n;"
|
||||
" }\n"
|
||||
" };\n"
|
||||
"\n",
|
||||
"classname", descriptor_->name());
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// Reflection
|
||||
|
||||
printer->Print(
|
||||
"public final com.google.protobuf.Descriptors.EnumValueDescriptor\n"
|
||||
" getValueDescriptor() {\n"
|
||||
" return getDescriptor().getValues().get(index);\n"
|
||||
"}\n"
|
||||
"public final com.google.protobuf.Descriptors.EnumDescriptor\n"
|
||||
" getDescriptorForType() {\n"
|
||||
" return getDescriptor();\n"
|
||||
"}\n"
|
||||
"public static final com.google.protobuf.Descriptors.EnumDescriptor\n"
|
||||
" getDescriptor() {\n");
|
||||
|
||||
// TODO(kenton): Cache statically? Note that we can't access descriptors
|
||||
// at module init time because it wouldn't work with descriptor.proto, but
|
||||
// we can cache the value the first time getDescriptor() is called.
|
||||
if (descriptor_->containing_type() == NULL) {
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
printer->Print(
|
||||
" return $file$.getDescriptor().getEnumTypes().get($index$);\n",
|
||||
"file", ClassName(descriptor_->file()),
|
||||
"index", SimpleItoa(descriptor_->index()));
|
||||
} else {
|
||||
"public final com.google.protobuf.Descriptors.EnumValueDescriptor\n"
|
||||
" getValueDescriptor() {\n"
|
||||
" return getDescriptor().getValues().get(index);\n"
|
||||
"}\n"
|
||||
"public final com.google.protobuf.Descriptors.EnumDescriptor\n"
|
||||
" getDescriptorForType() {\n"
|
||||
" return getDescriptor();\n"
|
||||
"}\n"
|
||||
"public static final com.google.protobuf.Descriptors.EnumDescriptor\n"
|
||||
" getDescriptor() {\n");
|
||||
|
||||
// TODO(kenton): Cache statically? Note that we can't access descriptors
|
||||
// at module init time because it wouldn't work with descriptor.proto, but
|
||||
// we can cache the value the first time getDescriptor() is called.
|
||||
if (descriptor_->containing_type() == NULL) {
|
||||
printer->Print(
|
||||
" return $file$.getDescriptor().getEnumTypes().get($index$);\n",
|
||||
"file", ClassName(descriptor_->file()),
|
||||
"index", SimpleItoa(descriptor_->index()));
|
||||
} else {
|
||||
printer->Print(
|
||||
" return $parent$.getDescriptor().getEnumTypes().get($index$);\n",
|
||||
"parent", ClassName(descriptor_->containing_type()),
|
||||
"index", SimpleItoa(descriptor_->index()));
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
" return $parent$.getDescriptor().getEnumTypes().get($index$);\n",
|
||||
"parent", ClassName(descriptor_->containing_type()),
|
||||
"index", SimpleItoa(descriptor_->index()));
|
||||
"}\n"
|
||||
"\n"
|
||||
"private static final $classname$[] VALUES = {\n"
|
||||
" ",
|
||||
"classname", descriptor_->name());
|
||||
|
||||
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||
printer->Print("$name$, ",
|
||||
"name", descriptor_->value(i)->name());
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"};\n"
|
||||
"public static $classname$ valueOf(\n"
|
||||
" com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n"
|
||||
" if (desc.getType() != getDescriptor()) {\n"
|
||||
" throw new java.lang.IllegalArgumentException(\n"
|
||||
" \"EnumValueDescriptor is not for this type.\");\n"
|
||||
" }\n"
|
||||
" return VALUES[desc.getIndex()];\n"
|
||||
"}\n",
|
||||
"classname", descriptor_->name());
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"}\n"
|
||||
"\n"
|
||||
"private static final $classname$[] VALUES = {\n"
|
||||
" ",
|
||||
"classname", descriptor_->name());
|
||||
|
||||
for (int i = 0; i < descriptor_->value_count(); i++) {
|
||||
printer->Print("$name$, ",
|
||||
"name", descriptor_->value(i)->name());
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"\n"
|
||||
"};\n"
|
||||
"public static $classname$ valueOf(\n"
|
||||
" com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n"
|
||||
" if (desc.getType() != getDescriptor()) {\n"
|
||||
" throw new java.lang.IllegalArgumentException(\n"
|
||||
" \"EnumValueDescriptor is not for this type.\");\n"
|
||||
" }\n"
|
||||
" return VALUES[desc.getIndex()];\n"
|
||||
"}\n",
|
||||
"classname", descriptor_->name());
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
printer->Print(
|
||||
@ -194,14 +212,16 @@ void EnumGenerator::Generate(io::Printer* printer) {
|
||||
"}\n",
|
||||
"classname", descriptor_->name());
|
||||
|
||||
// Force the static initialization code for the file to run, since it may
|
||||
// initialize static variables declared in this class.
|
||||
printer->Print(
|
||||
"\n"
|
||||
"static {\n"
|
||||
" $file$.getDescriptor();\n"
|
||||
"}\n",
|
||||
"file", ClassName(descriptor_->file()));
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
// Force the static initialization code for the file to run, since it may
|
||||
// initialize static variables declared in this class.
|
||||
printer->Print(
|
||||
"\n"
|
||||
"static {\n"
|
||||
" $file$.getDescriptor();\n"
|
||||
"}\n",
|
||||
"file", ClassName(descriptor_->file()));
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("}\n\n");
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/java/java_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/wire_format_inl.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
|
||||
namespace google {
|
||||
@ -53,18 +53,13 @@ namespace {
|
||||
// repeat code between this and the other field types.
|
||||
void SetEnumVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables) {
|
||||
const EnumValueDescriptor* default_value;
|
||||
default_value = descriptor->default_value_enum();
|
||||
|
||||
string type = ClassName(descriptor->enum_type());
|
||||
|
||||
(*variables)["name"] =
|
||||
UnderscoresToCamelCase(descriptor);
|
||||
(*variables)["capitalized_name"] =
|
||||
UnderscoresToCapitalizedCamelCase(descriptor);
|
||||
(*variables)["number"] = SimpleItoa(descriptor->number());
|
||||
(*variables)["type"] = type;
|
||||
(*variables)["default"] = type + "." + default_value->name();
|
||||
(*variables)["type"] = ClassName(descriptor->enum_type());
|
||||
(*variables)["default"] = DefaultValue(descriptor);
|
||||
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
|
||||
(*variables)["tag_size"] = SimpleItoa(
|
||||
internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
|
||||
@ -132,10 +127,17 @@ void EnumFieldGenerator::
|
||||
GenerateParsingCode(io::Printer* printer) const {
|
||||
printer->Print(variables_,
|
||||
"int rawValue = input.readEnum();\n"
|
||||
"$type$ value = $type$.valueOf(rawValue);\n"
|
||||
"if (value == null) {\n"
|
||||
" unknownFields.mergeVarintField($number$, rawValue);\n"
|
||||
"} else {\n"
|
||||
"$type$ value = $type$.valueOf(rawValue);\n");
|
||||
if (HasUnknownFields(descriptor_->containing_type())) {
|
||||
printer->Print(variables_,
|
||||
"if (value == null) {\n"
|
||||
" unknownFields.mergeVarintField($number$, rawValue);\n"
|
||||
"} else {\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"if (value != null) {\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" set$capitalized_name$(value);\n"
|
||||
"}\n");
|
||||
}
|
||||
@ -185,7 +187,7 @@ GenerateMembers(io::Printer* printer) const {
|
||||
"}\n");
|
||||
|
||||
if (descriptor_->options().packed() &&
|
||||
descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
|
||||
HasGeneratedMethods(descriptor_->containing_type())) {
|
||||
printer->Print(variables_,
|
||||
"private int $name$MemoizedSerializedSize;\n");
|
||||
}
|
||||
@ -272,10 +274,17 @@ GenerateParsingCode(io::Printer* printer) const {
|
||||
// Read and store the enum
|
||||
printer->Print(variables_,
|
||||
"int rawValue = input.readEnum();\n"
|
||||
"$type$ value = $type$.valueOf(rawValue);\n"
|
||||
"if (value == null) {\n"
|
||||
" unknownFields.mergeVarintField($number$, rawValue);\n"
|
||||
"} else {\n"
|
||||
"$type$ value = $type$.valueOf(rawValue);\n");
|
||||
if (HasUnknownFields(descriptor_->containing_type())) {
|
||||
printer->Print(variables_,
|
||||
"if (value == null) {\n"
|
||||
" unknownFields.mergeVarintField($number$, rawValue);\n"
|
||||
"} else {\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
"if (value != null) {\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" add$capitalized_name$(value);\n"
|
||||
"}\n");
|
||||
|
||||
|
@ -42,6 +42,39 @@ namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace java {
|
||||
|
||||
namespace {
|
||||
|
||||
const char* TypeName(FieldDescriptor::Type field_type) {
|
||||
switch (field_type) {
|
||||
case FieldDescriptor::TYPE_INT32 : return "INT32";
|
||||
case FieldDescriptor::TYPE_UINT32 : return "UINT32";
|
||||
case FieldDescriptor::TYPE_SINT32 : return "SINT32";
|
||||
case FieldDescriptor::TYPE_FIXED32 : return "FIXED32";
|
||||
case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32";
|
||||
case FieldDescriptor::TYPE_INT64 : return "INT64";
|
||||
case FieldDescriptor::TYPE_UINT64 : return "UINT64";
|
||||
case FieldDescriptor::TYPE_SINT64 : return "SINT64";
|
||||
case FieldDescriptor::TYPE_FIXED64 : return "FIXED64";
|
||||
case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64";
|
||||
case FieldDescriptor::TYPE_FLOAT : return "FLOAT";
|
||||
case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE";
|
||||
case FieldDescriptor::TYPE_BOOL : return "BOOL";
|
||||
case FieldDescriptor::TYPE_STRING : return "STRING";
|
||||
case FieldDescriptor::TYPE_BYTES : return "BYTES";
|
||||
case FieldDescriptor::TYPE_ENUM : return "ENUM";
|
||||
case FieldDescriptor::TYPE_GROUP : return "GROUP";
|
||||
case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE";
|
||||
|
||||
// No default because we want the compiler to complain if any new
|
||||
// types are added.
|
||||
}
|
||||
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor)
|
||||
: descriptor_(descriptor) {
|
||||
if (descriptor_->extension_scope() != NULL) {
|
||||
@ -59,6 +92,7 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
|
||||
vars["containing_type"] = ClassName(descriptor_->containing_type());
|
||||
vars["number"] = SimpleItoa(descriptor_->number());
|
||||
vars["constant_name"] = FieldConstantName(descriptor_);
|
||||
vars["lite"] = HasDescriptorMethods(descriptor_->file()) ? "" : "Lite";
|
||||
|
||||
JavaType java_type = GetJavaType(descriptor_);
|
||||
string singular_type;
|
||||
@ -79,13 +113,13 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
|
||||
if (descriptor_->is_repeated()) {
|
||||
printer->Print(vars,
|
||||
"public static\n"
|
||||
" com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
|
||||
" com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n"
|
||||
" $containing_type$,\n"
|
||||
" java.util.List<$type$>> $name$;\n");
|
||||
} else {
|
||||
printer->Print(vars,
|
||||
"public static\n"
|
||||
" com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
|
||||
" com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n"
|
||||
" $containing_type$,\n"
|
||||
" $type$> $name$;\n");
|
||||
}
|
||||
@ -96,34 +130,71 @@ void ExtensionGenerator::GenerateInitializationCode(io::Printer* printer) {
|
||||
vars["name"] = UnderscoresToCamelCase(descriptor_);
|
||||
vars["scope"] = scope_;
|
||||
vars["index"] = SimpleItoa(descriptor_->index());
|
||||
vars["extendee"] = ClassName(descriptor_->containing_type());
|
||||
vars["default"] = descriptor_->is_repeated() ? "" : DefaultValue(descriptor_);
|
||||
vars["number"] = SimpleItoa(descriptor_->number());
|
||||
vars["type_constant"] = TypeName(descriptor_->type());
|
||||
vars["packed"] = descriptor_->options().packed() ? "true" : "false";
|
||||
vars["enum_map"] = "null";
|
||||
vars["prototype"] = "null";
|
||||
|
||||
JavaType java_type = GetJavaType(descriptor_);
|
||||
string singular_type;
|
||||
switch (java_type) {
|
||||
case JAVATYPE_MESSAGE:
|
||||
vars["type"] = ClassName(descriptor_->message_type());
|
||||
vars["prototype"] = ClassName(descriptor_->message_type()) +
|
||||
".getDefaultInstance()";
|
||||
break;
|
||||
case JAVATYPE_ENUM:
|
||||
vars["type"] = ClassName(descriptor_->enum_type());
|
||||
vars["enum_map"] = ClassName(descriptor_->enum_type()) +
|
||||
".internalGetValueMap()";
|
||||
break;
|
||||
default:
|
||||
vars["type"] = BoxedPrimitiveTypeName(java_type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (descriptor_->is_repeated()) {
|
||||
printer->Print(vars,
|
||||
"$scope$.$name$ =\n"
|
||||
" com.google.protobuf.GeneratedMessage\n"
|
||||
" .newRepeatedGeneratedExtension(\n"
|
||||
" $scope$.getDescriptor().getExtensions().get($index$),\n"
|
||||
" $type$.class);\n");
|
||||
if (HasDescriptorMethods(descriptor_->file())) {
|
||||
if (descriptor_->is_repeated()) {
|
||||
printer->Print(vars,
|
||||
"$scope$.$name$ =\n"
|
||||
" com.google.protobuf.GeneratedMessage\n"
|
||||
" .newRepeatedGeneratedExtension(\n"
|
||||
" $scope$.getDescriptor().getExtensions().get($index$),\n"
|
||||
" $type$.class);\n");
|
||||
} else {
|
||||
printer->Print(vars,
|
||||
"$scope$.$name$ =\n"
|
||||
" com.google.protobuf.GeneratedMessage.newGeneratedExtension(\n"
|
||||
" $scope$.getDescriptor().getExtensions().get($index$),\n"
|
||||
" $type$.class);\n");
|
||||
}
|
||||
} else {
|
||||
printer->Print(vars,
|
||||
"$scope$.$name$ =\n"
|
||||
" com.google.protobuf.GeneratedMessage.newGeneratedExtension(\n"
|
||||
" $scope$.getDescriptor().getExtensions().get($index$),\n"
|
||||
" $type$.class);\n");
|
||||
if (descriptor_->is_repeated()) {
|
||||
printer->Print(vars,
|
||||
"$scope$.$name$ =\n"
|
||||
" com.google.protobuf.GeneratedMessageLite\n"
|
||||
" .newRepeatedGeneratedExtension(\n"
|
||||
" $extendee$.getDefaultInstance(),\n"
|
||||
" $prototype$,\n"
|
||||
" $enum_map$,\n"
|
||||
" $number$,\n"
|
||||
" com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
|
||||
" $packed$);\n");
|
||||
} else {
|
||||
printer->Print(vars,
|
||||
"$scope$.$name$ =\n"
|
||||
" com.google.protobuf.GeneratedMessageLite\n"
|
||||
" .newGeneratedExtension(\n"
|
||||
" $extendee$.getDefaultInstance(),\n"
|
||||
" $default$,\n"
|
||||
" $prototype$,\n"
|
||||
" $enum_map$,\n"
|
||||
" $number$,\n"
|
||||
" com.google.protobuf.WireFormat.FieldType.$type_constant$);\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,9 @@ void FileGenerator::Generate(io::Printer* printer) {
|
||||
|
||||
printer->Print(
|
||||
"public static void registerAllExtensions(\n"
|
||||
" com.google.protobuf.ExtensionRegistry registry) {\n");
|
||||
" com.google.protobuf.ExtensionRegistry$lite$ registry) {\n",
|
||||
"lite", HasDescriptorMethods(file_) ? "" : "Lite");
|
||||
|
||||
printer->Indent();
|
||||
|
||||
for (int i = 0; i < file_->extension_count(); i++) {
|
||||
@ -195,8 +197,42 @@ void FileGenerator::Generate(io::Printer* printer) {
|
||||
|
||||
printer->Print("\n");
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
if (HasDescriptorMethods(file_)) {
|
||||
GenerateEmbeddedDescriptor(printer);
|
||||
} else {
|
||||
printer->Print(
|
||||
"static {\n");
|
||||
printer->Indent();
|
||||
|
||||
for (int i = 0; i < file_->message_type_count(); i++) {
|
||||
// TODO(kenton): Reuse MessageGenerator objects?
|
||||
MessageGenerator(file_->message_type(i))
|
||||
.GenerateStaticVariableInitializers(printer);
|
||||
}
|
||||
|
||||
for (int i = 0; i < file_->extension_count(); i++) {
|
||||
// TODO(kenton): Reuse ExtensionGenerator objects?
|
||||
ExtensionGenerator(file_->extension(i))
|
||||
.GenerateInitializationCode(printer);
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n");
|
||||
}
|
||||
|
||||
// Dummy function we can use to force the static initialization block to
|
||||
// run. Needed by inner classes. Cannot be private due to
|
||||
// java_multiple_files option.
|
||||
printer->Print(
|
||||
"\n"
|
||||
"public static void internalForceInit() {}\n");
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
|
||||
// Embed the descriptor. We simply serialize the entire FileDescriptorProto
|
||||
// and embed it as a string literal, which is parsed and built into real
|
||||
// descriptors at initialization time. We unfortunately have to put it in
|
||||
@ -310,9 +346,6 @@ void FileGenerator::Generate(io::Printer* printer) {
|
||||
printer->Outdent();
|
||||
printer->Print(
|
||||
"}\n");
|
||||
|
||||
printer->Outdent();
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
template<typename GeneratorClass, typename DescriptorClass>
|
||||
|
@ -81,6 +81,8 @@ class FileGenerator {
|
||||
string java_package_;
|
||||
string classname_;
|
||||
|
||||
void GenerateEmbeddedDescriptor(io::Printer* printer);
|
||||
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
|
||||
};
|
||||
|
||||
|
@ -45,32 +45,6 @@ namespace protobuf {
|
||||
namespace compiler {
|
||||
namespace java {
|
||||
|
||||
namespace {
|
||||
|
||||
// Parses a set of comma-delimited name/value pairs, e.g.:
|
||||
// "foo=bar,baz,qux=corge"
|
||||
// parses to the pairs:
|
||||
// ("foo", "bar"), ("baz", ""), ("qux", "corge")
|
||||
void ParseOptions(const string& text, vector<pair<string, string> >* output) {
|
||||
vector<string> parts;
|
||||
SplitStringUsing(text, ",", &parts);
|
||||
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
string::size_type equals_pos = parts[i].find_first_of('=');
|
||||
pair<string, string> value;
|
||||
if (equals_pos == string::npos) {
|
||||
value.first = parts[i];
|
||||
value.second = "";
|
||||
} else {
|
||||
value.first = parts[i].substr(0, equals_pos);
|
||||
value.second = parts[i].substr(equals_pos + 1);
|
||||
}
|
||||
output->push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
JavaGenerator::JavaGenerator() {}
|
||||
JavaGenerator::~JavaGenerator() {}
|
||||
|
||||
@ -79,7 +53,7 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
|
||||
OutputDirectory* output_directory,
|
||||
string* error) const {
|
||||
vector<pair<string, string> > options;
|
||||
ParseOptions(parameter, &options);
|
||||
ParseGeneratorParameter(parameter, &options);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// parse generator options
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <google/protobuf/compiler/java/java_helpers.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/stubs/substitute.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
@ -243,6 +244,72 @@ const char* BoxedPrimitiveTypeName(JavaType type) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool AllAscii(const string& text) {
|
||||
for (int i = 0; i < text.size(); i++) {
|
||||
if ((text[i] & 0x80) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
string DefaultValue(const FieldDescriptor* field) {
|
||||
// Switch on cpp_type since we need to know which default_value_* method
|
||||
// of FieldDescriptor to call.
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
return SimpleItoa(field->default_value_int32());
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
// Need to print as a signed int since Java has no unsigned.
|
||||
return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
return SimpleItoa(field->default_value_int64()) + "L";
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
|
||||
"L";
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
return SimpleDtoa(field->default_value_double()) + "D";
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
return SimpleFtoa(field->default_value_float()) + "F";
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
return field->default_value_bool() ? "true" : "false";
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
if (field->type() == FieldDescriptor::TYPE_BYTES) {
|
||||
if (field->has_default_value()) {
|
||||
// See comments in Internal.java for gory details.
|
||||
return strings::Substitute(
|
||||
"com.google.protobuf.Internal.bytesDefaultValue(\"$0\")",
|
||||
CEscape(field->default_value_string()));
|
||||
} else {
|
||||
return "com.google.protobuf.ByteString.EMPTY";
|
||||
}
|
||||
} else {
|
||||
if (AllAscii(field->default_value_string())) {
|
||||
// All chars are ASCII. In this case CEscape() works fine.
|
||||
return "\"" + CEscape(field->default_value_string()) + "\"";
|
||||
} else {
|
||||
// See comments in Internal.java for gory details.
|
||||
return strings::Substitute(
|
||||
"com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
|
||||
CEscape(field->default_value_string()));
|
||||
}
|
||||
}
|
||||
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
return ClassName(field->enum_type()) + "." +
|
||||
field->default_value_enum()->name();
|
||||
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return ClassName(field->message_type()) + ".getDefaultInstance()";
|
||||
|
||||
// No default because we want the compiler to complain if any new
|
||||
// types are added.
|
||||
}
|
||||
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace java
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
@ -36,6 +36,7 @@
|
||||
#define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
|
||||
|
||||
#include <string>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
namespace google {
|
||||
@ -115,6 +116,35 @@ inline JavaType GetJavaType(const FieldDescriptor* field) {
|
||||
// types.
|
||||
const char* BoxedPrimitiveTypeName(JavaType type);
|
||||
|
||||
string DefaultValue(const FieldDescriptor* field);
|
||||
|
||||
// Does this message class keep track of unknown fields?
|
||||
inline bool HasUnknownFields(const Descriptor* descriptor) {
|
||||
return descriptor->file()->options().optimize_for() !=
|
||||
FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
// Does this message class have generated parsing, serialization, and other
|
||||
// standard methods for which reflection-based fallback implementations exist?
|
||||
inline bool HasGeneratedMethods(const Descriptor* descriptor) {
|
||||
return descriptor->file()->options().optimize_for() !=
|
||||
FileOptions::CODE_SIZE;
|
||||
}
|
||||
|
||||
// Does this message class have descriptor and reflection methods?
|
||||
inline bool HasDescriptorMethods(const Descriptor* descriptor) {
|
||||
return descriptor->file()->options().optimize_for() !=
|
||||
FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
inline bool HasDescriptorMethods(const EnumDescriptor* descriptor) {
|
||||
return descriptor->file()->options().optimize_for() !=
|
||||
FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
inline bool HasDescriptorMethods(const FileDescriptor* descriptor) {
|
||||
return descriptor->options().optimize_for() !=
|
||||
FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
} // namespace java
|
||||
} // namespace compiler
|
||||
} // namespace protobuf
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/coded_stream.h>
|
||||
#include <google/protobuf/wire_format_inl.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
|
||||
namespace google {
|
||||
@ -50,6 +50,7 @@ namespace compiler {
|
||||
namespace java {
|
||||
|
||||
using internal::WireFormat;
|
||||
using internal::WireFormatLite;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -153,38 +154,41 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor)
|
||||
MessageGenerator::~MessageGenerator() {}
|
||||
|
||||
void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
|
||||
// Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
|
||||
// used in the construction of descriptors, we have a tricky bootstrapping
|
||||
// problem. To help control static initialization order, we make sure all
|
||||
// descriptors and other static data that depends on them are members of
|
||||
// the outermost class in the file. This way, they will be initialized in
|
||||
// a deterministic order.
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
// Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
|
||||
// used in the construction of descriptors, we have a tricky bootstrapping
|
||||
// problem. To help control static initialization order, we make sure all
|
||||
// descriptors and other static data that depends on them are members of
|
||||
// the outermost class in the file. This way, they will be initialized in
|
||||
// a deterministic order.
|
||||
|
||||
map<string, string> vars;
|
||||
vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
|
||||
vars["index"] = SimpleItoa(descriptor_->index());
|
||||
vars["classname"] = ClassName(descriptor_);
|
||||
if (descriptor_->containing_type() != NULL) {
|
||||
vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
|
||||
map<string, string> vars;
|
||||
vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
|
||||
vars["index"] = SimpleItoa(descriptor_->index());
|
||||
vars["classname"] = ClassName(descriptor_);
|
||||
if (descriptor_->containing_type() != NULL) {
|
||||
vars["parent"] = UniqueFileScopeIdentifier(
|
||||
descriptor_->containing_type());
|
||||
}
|
||||
if (descriptor_->file()->options().java_multiple_files()) {
|
||||
// We can only make these package-private since the classes that use them
|
||||
// are in separate files.
|
||||
vars["private"] = "";
|
||||
} else {
|
||||
vars["private"] = "private ";
|
||||
}
|
||||
|
||||
// The descriptor for this type.
|
||||
printer->Print(vars,
|
||||
"$private$static com.google.protobuf.Descriptors.Descriptor\n"
|
||||
" internal_$identifier$_descriptor;\n");
|
||||
|
||||
// And the FieldAccessorTable.
|
||||
printer->Print(vars,
|
||||
"$private$static\n"
|
||||
" com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
|
||||
" internal_$identifier$_fieldAccessorTable;\n");
|
||||
}
|
||||
if (descriptor_->file()->options().java_multiple_files()) {
|
||||
// We can only make these package-private since the classes that use them
|
||||
// are in separate files.
|
||||
vars["private"] = "";
|
||||
} else {
|
||||
vars["private"] = "private ";
|
||||
}
|
||||
|
||||
// The descriptor for this type.
|
||||
printer->Print(vars,
|
||||
"$private$static com.google.protobuf.Descriptors.Descriptor\n"
|
||||
" internal_$identifier$_descriptor;\n");
|
||||
|
||||
// And the FieldAccessorTable.
|
||||
printer->Print(vars,
|
||||
"$private$static\n"
|
||||
" com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
|
||||
" internal_$identifier$_fieldAccessorTable;\n");
|
||||
|
||||
// Generate static members for all nested types.
|
||||
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
||||
@ -196,41 +200,44 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
|
||||
|
||||
void MessageGenerator::GenerateStaticVariableInitializers(
|
||||
io::Printer* printer) {
|
||||
map<string, string> vars;
|
||||
vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
|
||||
vars["index"] = SimpleItoa(descriptor_->index());
|
||||
vars["classname"] = ClassName(descriptor_);
|
||||
if (descriptor_->containing_type() != NULL) {
|
||||
vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
|
||||
}
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
map<string, string> vars;
|
||||
vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
|
||||
vars["index"] = SimpleItoa(descriptor_->index());
|
||||
vars["classname"] = ClassName(descriptor_);
|
||||
if (descriptor_->containing_type() != NULL) {
|
||||
vars["parent"] = UniqueFileScopeIdentifier(
|
||||
descriptor_->containing_type());
|
||||
}
|
||||
|
||||
// The descriptor for this type.
|
||||
if (descriptor_->containing_type() == NULL) {
|
||||
printer->Print(vars,
|
||||
"internal_$identifier$_descriptor =\n"
|
||||
" getDescriptor().getMessageTypes().get($index$);\n");
|
||||
} else {
|
||||
printer->Print(vars,
|
||||
"internal_$identifier$_descriptor =\n"
|
||||
" internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
|
||||
}
|
||||
// The descriptor for this type.
|
||||
if (descriptor_->containing_type() == NULL) {
|
||||
printer->Print(vars,
|
||||
"internal_$identifier$_descriptor =\n"
|
||||
" getDescriptor().getMessageTypes().get($index$);\n");
|
||||
} else {
|
||||
printer->Print(vars,
|
||||
"internal_$identifier$_descriptor =\n"
|
||||
" internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
|
||||
}
|
||||
|
||||
// And the FieldAccessorTable.
|
||||
printer->Print(vars,
|
||||
"internal_$identifier$_fieldAccessorTable = new\n"
|
||||
" com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n"
|
||||
" internal_$identifier$_descriptor,\n"
|
||||
" new java.lang.String[] { ");
|
||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||
printer->Print(
|
||||
"\"$field_name$\", ",
|
||||
"field_name",
|
||||
UnderscoresToCapitalizedCamelCase(descriptor_->field(i)));
|
||||
// And the FieldAccessorTable.
|
||||
printer->Print(vars,
|
||||
"internal_$identifier$_fieldAccessorTable = new\n"
|
||||
" com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n"
|
||||
" internal_$identifier$_descriptor,\n"
|
||||
" new java.lang.String[] { ");
|
||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||
printer->Print(
|
||||
"\"$field_name$\", ",
|
||||
"field_name",
|
||||
UnderscoresToCapitalizedCamelCase(descriptor_->field(i)));
|
||||
}
|
||||
printer->Print("},\n"
|
||||
" $classname$.class,\n"
|
||||
" $classname$.Builder.class);\n",
|
||||
"classname", ClassName(descriptor_));
|
||||
}
|
||||
printer->Print("},\n"
|
||||
" $classname$.class,\n"
|
||||
" $classname$.Builder.class);\n",
|
||||
"classname", ClassName(descriptor_));
|
||||
|
||||
// Generate static member initializers for all nested types.
|
||||
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
|
||||
@ -252,18 +259,35 @@ void MessageGenerator::Generate(io::Printer* printer) {
|
||||
descriptor_->file()->options().java_multiple_files();
|
||||
|
||||
if (descriptor_->extension_range_count() > 0) {
|
||||
printer->Print(
|
||||
"public $static$ final class $classname$ extends\n"
|
||||
" com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
|
||||
" $classname$> {\n",
|
||||
"static", is_own_file ? "" : "static",
|
||||
"classname", descriptor_->name());
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
printer->Print(
|
||||
"public $static$ final class $classname$ extends\n"
|
||||
" com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
|
||||
" $classname$> {\n",
|
||||
"static", is_own_file ? "" : "static",
|
||||
"classname", descriptor_->name());
|
||||
} else {
|
||||
printer->Print(
|
||||
"public $static$ final class $classname$ extends\n"
|
||||
" com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
|
||||
" $classname$> {\n",
|
||||
"static", is_own_file ? "" : "static",
|
||||
"classname", descriptor_->name());
|
||||
}
|
||||
} else {
|
||||
printer->Print(
|
||||
"public $static$ final class $classname$ extends\n"
|
||||
" com.google.protobuf.GeneratedMessage {\n",
|
||||
"static", is_own_file ? "" : "static",
|
||||
"classname", descriptor_->name());
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
printer->Print(
|
||||
"public $static$ final class $classname$ extends\n"
|
||||
" com.google.protobuf.GeneratedMessage {\n",
|
||||
"static", is_own_file ? "" : "static",
|
||||
"classname", descriptor_->name());
|
||||
} else {
|
||||
printer->Print(
|
||||
"public $static$ final class $classname$ extends\n"
|
||||
" com.google.protobuf.GeneratedMessageLite {\n",
|
||||
"static", is_own_file ? "" : "static",
|
||||
"classname", descriptor_->name());
|
||||
}
|
||||
}
|
||||
printer->Indent();
|
||||
printer->Print(
|
||||
@ -280,20 +304,23 @@ void MessageGenerator::Generate(io::Printer* printer) {
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", descriptor_->name());
|
||||
printer->Print(
|
||||
"public static final com.google.protobuf.Descriptors.Descriptor\n"
|
||||
" getDescriptor() {\n"
|
||||
" return $fileclass$.internal_$identifier$_descriptor;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"@Override\n"
|
||||
"protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
|
||||
" internalGetFieldAccessorTable() {\n"
|
||||
" return $fileclass$.internal_$identifier$_fieldAccessorTable;\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"fileclass", ClassName(descriptor_->file()),
|
||||
"identifier", UniqueFileScopeIdentifier(descriptor_));
|
||||
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
printer->Print(
|
||||
"public static final com.google.protobuf.Descriptors.Descriptor\n"
|
||||
" getDescriptor() {\n"
|
||||
" return $fileclass$.internal_$identifier$_descriptor;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"@Override\n"
|
||||
"protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
|
||||
" internalGetFieldAccessorTable() {\n"
|
||||
" return $fileclass$.internal_$identifier$_fieldAccessorTable;\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"fileclass", ClassName(descriptor_->file()),
|
||||
"identifier", UniqueFileScopeIdentifier(descriptor_));
|
||||
}
|
||||
|
||||
// Nested types and extensions
|
||||
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
|
||||
@ -318,7 +345,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
|
||||
printer->Print("\n");
|
||||
}
|
||||
|
||||
if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
|
||||
if (HasGeneratedMethods(descriptor_)) {
|
||||
GenerateIsInitialized(printer);
|
||||
GenerateMessageSerializationMethods(printer);
|
||||
}
|
||||
@ -326,12 +353,23 @@ void MessageGenerator::Generate(io::Printer* printer) {
|
||||
GenerateParseFromMethods(printer);
|
||||
GenerateBuilder(printer);
|
||||
|
||||
// Force the static initialization code for the file to run, since it may
|
||||
// initialize static variables declared in this class.
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
// Force the static initialization code for the file to run, since it may
|
||||
// initialize static variables declared in this class.
|
||||
printer->Print(
|
||||
"\n"
|
||||
"static {\n"
|
||||
" $file$.getDescriptor();\n"
|
||||
"}\n",
|
||||
"file", ClassName(descriptor_->file()));
|
||||
}
|
||||
|
||||
// Force initialization of outer class. Otherwise, nested extensions may
|
||||
// not be initialized.
|
||||
printer->Print(
|
||||
"\n"
|
||||
"static {\n"
|
||||
" $file$.getDescriptor();\n"
|
||||
" $file$.internalForceInit();\n"
|
||||
"}\n",
|
||||
"file", ClassName(descriptor_->file()));
|
||||
|
||||
@ -360,9 +398,18 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
|
||||
printer->Indent();
|
||||
|
||||
if (descriptor_->extension_range_count() > 0) {
|
||||
printer->Print(
|
||||
"com.google.protobuf.GeneratedMessage.ExtendableMessage\n"
|
||||
" .ExtensionWriter extensionWriter = newExtensionWriter();\n");
|
||||
if (descriptor_->options().message_set_wire_format()) {
|
||||
printer->Print(
|
||||
"com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage\n"
|
||||
" .ExtensionWriter extensionWriter =\n"
|
||||
" newMessageSetExtensionWriter();\n",
|
||||
"lite", HasDescriptorMethods(descriptor_) ? "" : "Lite");
|
||||
} else {
|
||||
printer->Print(
|
||||
"com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage\n"
|
||||
" .ExtensionWriter extensionWriter = newExtensionWriter();\n",
|
||||
"lite", HasDescriptorMethods(descriptor_) ? "" : "Lite");
|
||||
}
|
||||
}
|
||||
|
||||
// Merge the fields and the extension ranges, both sorted by field number.
|
||||
@ -380,12 +427,14 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
|
||||
}
|
||||
}
|
||||
|
||||
if (descriptor_->options().message_set_wire_format()) {
|
||||
printer->Print(
|
||||
"getUnknownFields().writeAsMessageSetTo(output);\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"getUnknownFields().writeTo(output);\n");
|
||||
if (HasUnknownFields(descriptor_)) {
|
||||
if (descriptor_->options().message_set_wire_format()) {
|
||||
printer->Print(
|
||||
"getUnknownFields().writeAsMessageSetTo(output);\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"getUnknownFields().writeTo(output);\n");
|
||||
}
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
@ -406,16 +455,23 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
|
||||
}
|
||||
|
||||
if (descriptor_->extension_range_count() > 0) {
|
||||
printer->Print(
|
||||
"size += extensionsSerializedSize();\n");
|
||||
if (descriptor_->options().message_set_wire_format()) {
|
||||
printer->Print(
|
||||
"size += extensionsSerializedSizeAsMessageSet();\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"size += extensionsSerializedSize();\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (descriptor_->options().message_set_wire_format()) {
|
||||
printer->Print(
|
||||
"size += getUnknownFields().getSerializedSizeAsMessageSet();\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"size += getUnknownFields().getSerializedSize();\n");
|
||||
if (HasUnknownFields(descriptor_)) {
|
||||
if (descriptor_->options().message_set_wire_format()) {
|
||||
printer->Print(
|
||||
"size += getUnknownFields().getSerializedSizeAsMessageSet();\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"size += getUnknownFields().getSerializedSize();\n");
|
||||
}
|
||||
}
|
||||
|
||||
printer->Outdent();
|
||||
@ -439,7 +495,7 @@ GenerateParseFromMethods(io::Printer* printer) {
|
||||
"}\n"
|
||||
"public static $classname$ parseFrom(\n"
|
||||
" com.google.protobuf.ByteString data,\n"
|
||||
" com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
|
||||
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
|
||||
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
|
||||
" return newBuilder().mergeFrom(data, extensionRegistry)\n"
|
||||
" .buildParsed();\n"
|
||||
@ -450,7 +506,7 @@ GenerateParseFromMethods(io::Printer* printer) {
|
||||
"}\n"
|
||||
"public static $classname$ parseFrom(\n"
|
||||
" byte[] data,\n"
|
||||
" com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
|
||||
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
|
||||
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
|
||||
" return newBuilder().mergeFrom(data, extensionRegistry)\n"
|
||||
" .buildParsed();\n"
|
||||
@ -461,7 +517,7 @@ GenerateParseFromMethods(io::Printer* printer) {
|
||||
"}\n"
|
||||
"public static $classname$ parseFrom(\n"
|
||||
" java.io.InputStream input,\n"
|
||||
" com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
|
||||
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
|
||||
" throws java.io.IOException {\n"
|
||||
" return newBuilder().mergeFrom(input, extensionRegistry)\n"
|
||||
" .buildParsed();\n"
|
||||
@ -472,7 +528,7 @@ GenerateParseFromMethods(io::Printer* printer) {
|
||||
"}\n"
|
||||
"public static $classname$ parseDelimitedFrom(\n"
|
||||
" java.io.InputStream input,\n"
|
||||
" com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
|
||||
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
|
||||
" throws java.io.IOException {\n"
|
||||
" return newBuilder().mergeDelimitedFrom(input, extensionRegistry)\n"
|
||||
" .buildParsed();\n"
|
||||
@ -484,7 +540,7 @@ GenerateParseFromMethods(io::Printer* printer) {
|
||||
"}\n"
|
||||
"public static $classname$ parseFrom(\n"
|
||||
" com.google.protobuf.CodedInputStream input,\n"
|
||||
" com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
|
||||
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
|
||||
" throws java.io.IOException {\n"
|
||||
" return newBuilder().mergeFrom(input, extensionRegistry)\n"
|
||||
" .buildParsed();\n"
|
||||
@ -509,32 +565,57 @@ void MessageGenerator::GenerateSerializeOneExtensionRange(
|
||||
|
||||
void MessageGenerator::GenerateBuilder(io::Printer* printer) {
|
||||
printer->Print(
|
||||
"public static Builder newBuilder() { return new Builder(); }\n"
|
||||
"public Builder newBuilderForType() { return new Builder(); }\n"
|
||||
"public static Builder newBuilder() { return Builder.create(); }\n"
|
||||
"public Builder newBuilderForType() { return newBuilder(); }\n"
|
||||
"public static Builder newBuilder($classname$ prototype) {\n"
|
||||
" return new Builder().mergeFrom(prototype);\n"
|
||||
" return newBuilder().mergeFrom(prototype);\n"
|
||||
"}\n"
|
||||
"public Builder toBuilder() { return newBuilder(this); }\n"
|
||||
"\n",
|
||||
"classname", ClassName(descriptor_));
|
||||
|
||||
if (descriptor_->extension_range_count() > 0) {
|
||||
printer->Print(
|
||||
"public static final class Builder extends\n"
|
||||
" com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
|
||||
" $classname$, Builder> {\n",
|
||||
"classname", ClassName(descriptor_));
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
printer->Print(
|
||||
"public static final class Builder extends\n"
|
||||
" com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
|
||||
" $classname$, Builder> {\n",
|
||||
"classname", ClassName(descriptor_));
|
||||
} else {
|
||||
printer->Print(
|
||||
"public static final class Builder extends\n"
|
||||
" com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n"
|
||||
" $classname$, Builder> {\n",
|
||||
"classname", ClassName(descriptor_));
|
||||
}
|
||||
} else {
|
||||
printer->Print(
|
||||
"public static final class Builder extends\n"
|
||||
" com.google.protobuf.GeneratedMessage.Builder<Builder> {\n",
|
||||
"classname", ClassName(descriptor_));
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
printer->Print(
|
||||
"public static final class Builder extends\n"
|
||||
" com.google.protobuf.GeneratedMessage.Builder<Builder> {\n",
|
||||
"classname", ClassName(descriptor_));
|
||||
} else {
|
||||
printer->Print(
|
||||
"public static final class Builder extends\n"
|
||||
" com.google.protobuf.GeneratedMessageLite.Builder<\n"
|
||||
" $classname$, Builder> {\n",
|
||||
"classname", ClassName(descriptor_));
|
||||
}
|
||||
}
|
||||
printer->Indent();
|
||||
|
||||
// By using a threadlocal queue, we do not have to worry about locking when
|
||||
// accessing the queue. Current JDKs implement this very efficiently, using
|
||||
// no locks themselves to acquire the value when needed.
|
||||
printer->Print(
|
||||
"private static final "
|
||||
" com.google.protobuf.Internal.ThreadLocalQuickQueue<Builder> builders =\n"
|
||||
" new com.google.protobuf.Internal.ThreadLocalQuickQueue<Builder>();\n"
|
||||
"\n");
|
||||
|
||||
GenerateCommonBuilderMethods(printer);
|
||||
|
||||
if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
|
||||
if (HasGeneratedMethods(descriptor_)) {
|
||||
GenerateBuilderParsingMethods(printer);
|
||||
}
|
||||
|
||||
@ -553,10 +634,19 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) {
|
||||
|
||||
void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
|
||||
printer->Print(
|
||||
"private $classname$ result;\n"
|
||||
"\n"
|
||||
"// Construct using $classname$.newBuilder()\n"
|
||||
"private Builder() {}\n"
|
||||
"\n"
|
||||
"$classname$ result = new $classname$();\n"
|
||||
"private static Builder create() {\n"
|
||||
" Builder builder = builders.get().poll();\n"
|
||||
" if (builder == null) {\n"
|
||||
" builder = new Builder();\n"
|
||||
" }\n"
|
||||
" builder.result = new $classname$();\n"
|
||||
" return builder;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"@Override\n"
|
||||
"protected $classname$ internalGetResult() {\n"
|
||||
@ -565,25 +655,38 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
|
||||
"\n"
|
||||
"@Override\n"
|
||||
"public Builder clear() {\n"
|
||||
" if (result == null) {\n"
|
||||
" throw new IllegalStateException(\n"
|
||||
" \"Cannot call clear() after build().\");\n"
|
||||
" }\n"
|
||||
" result = new $classname$();\n"
|
||||
" return this;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"@Override\n"
|
||||
"public Builder clone() {\n"
|
||||
" return new Builder().mergeFrom(result);\n"
|
||||
" return create().mergeFrom(result);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"@Override\n"
|
||||
"public com.google.protobuf.Descriptors.Descriptor\n"
|
||||
" getDescriptorForType() {\n"
|
||||
" return $classname$.getDescriptor();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"\n",
|
||||
"classname", ClassName(descriptor_));
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
printer->Print(
|
||||
"@Override\n"
|
||||
"public com.google.protobuf.Descriptors.Descriptor\n"
|
||||
" getDescriptorForType() {\n"
|
||||
" return $classname$.getDescriptor();\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", ClassName(descriptor_));
|
||||
}
|
||||
printer->Print(
|
||||
"public $classname$ getDefaultInstanceForType() {\n"
|
||||
" return $classname$.getDefaultInstance();\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"\n"
|
||||
"public boolean isInitialized() {\n"
|
||||
" return result.isInitialized();\n"
|
||||
"}\n",
|
||||
"classname", ClassName(descriptor_));
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
@ -592,8 +695,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
|
||||
"public $classname$ build() {\n"
|
||||
// If result == null, we'll throw an appropriate exception later.
|
||||
" if (result != null && !isInitialized()) {\n"
|
||||
" throw new com.google.protobuf.UninitializedMessageException(\n"
|
||||
" result);\n"
|
||||
" throw newUninitializedMessageException(result);\n"
|
||||
" }\n"
|
||||
" return buildPartial();\n"
|
||||
"}\n"
|
||||
@ -601,7 +703,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
|
||||
"private $classname$ buildParsed()\n"
|
||||
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
|
||||
" if (!isInitialized()) {\n"
|
||||
" throw new com.google.protobuf.UninitializedMessageException(\n"
|
||||
" throw newUninitializedMessageException(\n"
|
||||
" result).asInvalidProtocolBufferException();\n"
|
||||
" }\n"
|
||||
" return buildPartial();\n"
|
||||
@ -610,7 +712,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
|
||||
"public $classname$ buildPartial() {\n"
|
||||
" if (result == null) {\n"
|
||||
" throw new IllegalStateException(\n"
|
||||
" \"build() has already been called on this Builder.\");"
|
||||
" \"build() has already been called on this Builder.\");\n"
|
||||
" }\n",
|
||||
"classname", ClassName(descriptor_));
|
||||
printer->Indent();
|
||||
@ -623,6 +725,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
|
||||
printer->Print(
|
||||
" $classname$ returnMe = result;\n"
|
||||
" result = null;\n"
|
||||
" builders.get().offer(this);\n"
|
||||
" return returnMe;\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
@ -630,18 +733,25 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
|
||||
if (HasGeneratedMethods(descriptor_)) {
|
||||
// MergeFrom(Message other) requires the ability to distinguish the other
|
||||
// messages type by its descriptor.
|
||||
if (HasDescriptorMethods(descriptor_)) {
|
||||
printer->Print(
|
||||
"@Override\n"
|
||||
"public Builder mergeFrom(com.google.protobuf.Message other) {\n"
|
||||
" if (other instanceof $classname$) {\n"
|
||||
" return mergeFrom(($classname$)other);\n"
|
||||
" } else {\n"
|
||||
" super.mergeFrom(other);\n"
|
||||
" return this;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n",
|
||||
"classname", ClassName(descriptor_));
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"@Override\n"
|
||||
"public Builder mergeFrom(com.google.protobuf.Message other) {\n"
|
||||
" if (other instanceof $classname$) {\n"
|
||||
" return mergeFrom(($classname$)other);\n"
|
||||
" } else {\n"
|
||||
" super.mergeFrom(other);\n"
|
||||
" return this;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"public Builder mergeFrom($classname$ other) {\n"
|
||||
// Optimization: If other is the default instance, we know none of its
|
||||
// fields are set so we can skip the merge.
|
||||
@ -661,8 +771,12 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
|
||||
" this.mergeExtensionFields(other);\n");
|
||||
}
|
||||
|
||||
if (HasUnknownFields(descriptor_)) {
|
||||
printer->Print(
|
||||
" this.mergeUnknownFields(other.getUnknownFields());\n");
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
" this.mergeUnknownFields(other.getUnknownFields());\n"
|
||||
" return this;\n"
|
||||
"}\n"
|
||||
"\n");
|
||||
@ -676,25 +790,21 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
|
||||
SortFieldsByNumber(descriptor_));
|
||||
|
||||
printer->Print(
|
||||
"@Override\n"
|
||||
"public Builder mergeFrom(\n"
|
||||
" com.google.protobuf.CodedInputStream input)\n"
|
||||
" throws java.io.IOException {\n"
|
||||
" return mergeFrom(input,\n"
|
||||
" com.google.protobuf.ExtensionRegistry.getEmptyRegistry());\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"@Override\n"
|
||||
"public Builder mergeFrom(\n"
|
||||
" com.google.protobuf.CodedInputStream input,\n"
|
||||
" com.google.protobuf.ExtensionRegistry extensionRegistry)\n"
|
||||
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
|
||||
" throws java.io.IOException {\n");
|
||||
printer->Indent();
|
||||
|
||||
if (HasUnknownFields(descriptor_)) {
|
||||
printer->Print(
|
||||
"com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
|
||||
" com.google.protobuf.UnknownFieldSet.newBuilder(\n"
|
||||
" this.getUnknownFields());\n");
|
||||
}
|
||||
|
||||
printer->Print(
|
||||
"com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
|
||||
" com.google.protobuf.UnknownFieldSet.newBuilder(\n"
|
||||
" this.getUnknownFields());\n"
|
||||
"while (true) {\n");
|
||||
printer->Indent();
|
||||
|
||||
@ -703,22 +813,34 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
|
||||
"switch (tag) {\n");
|
||||
printer->Indent();
|
||||
|
||||
printer->Print(
|
||||
"case 0:\n" // zero signals EOF / limit reached
|
||||
" this.setUnknownFields(unknownFields.build());\n"
|
||||
" return this;\n"
|
||||
"default: {\n"
|
||||
" if (!parseUnknownField(input, unknownFields,\n"
|
||||
" extensionRegistry, tag)) {\n"
|
||||
" this.setUnknownFields(unknownFields.build());\n"
|
||||
" return this;\n" // it's an endgroup tag
|
||||
" }\n"
|
||||
" break;\n"
|
||||
"}\n");
|
||||
if (HasUnknownFields(descriptor_)) {
|
||||
printer->Print(
|
||||
"case 0:\n" // zero signals EOF / limit reached
|
||||
" this.setUnknownFields(unknownFields.build());\n"
|
||||
" return this;\n"
|
||||
"default: {\n"
|
||||
" if (!parseUnknownField(input, unknownFields,\n"
|
||||
" extensionRegistry, tag)) {\n"
|
||||
" this.setUnknownFields(unknownFields.build());\n"
|
||||
" return this;\n" // it's an endgroup tag
|
||||
" }\n"
|
||||
" break;\n"
|
||||
"}\n");
|
||||
} else {
|
||||
printer->Print(
|
||||
"case 0:\n" // zero signals EOF / limit reached
|
||||
" return this;\n"
|
||||
"default: {\n"
|
||||
" if (!parseUnknownField(input, extensionRegistry, tag)) {\n"
|
||||
" return this;\n" // it's an endgroup tag
|
||||
" }\n"
|
||||
" break;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||
const FieldDescriptor* field = sorted_fields[i];
|
||||
uint32 tag = WireFormat::MakeTag(field->number(),
|
||||
uint32 tag = WireFormatLite::MakeTag(field->number(),
|
||||
WireFormat::WireTypeForField(field));
|
||||
|
||||
printer->Print(
|
||||
|
@ -39,9 +39,8 @@
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/compiler/java/java_helpers.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/wire_format_inl.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
#include <google/protobuf/stubs/strutil.h>
|
||||
#include <google/protobuf/stubs/substitute.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
@ -49,6 +48,7 @@ namespace compiler {
|
||||
namespace java {
|
||||
|
||||
using internal::WireFormat;
|
||||
using internal::WireFormatLite;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -121,16 +121,6 @@ const char* GetCapitalizedType(const FieldDescriptor* field) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool AllPrintableAscii(const string& text) {
|
||||
// Cannot use isprint() because it's locale-specific. :(
|
||||
for (int i = 0; i < text.size(); i++) {
|
||||
if ((text[i] < 0x20) || text[i] >= 0x7F) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// For encodings with fixed sizes, returns that size in bytes. Otherwise
|
||||
// returns -1.
|
||||
int FixedSize(FieldDescriptor::Type type) {
|
||||
@ -141,14 +131,14 @@ int FixedSize(FieldDescriptor::Type type) {
|
||||
case FieldDescriptor::TYPE_UINT64 : return -1;
|
||||
case FieldDescriptor::TYPE_SINT32 : return -1;
|
||||
case FieldDescriptor::TYPE_SINT64 : return -1;
|
||||
case FieldDescriptor::TYPE_FIXED32 : return WireFormat::kFixed32Size;
|
||||
case FieldDescriptor::TYPE_FIXED64 : return WireFormat::kFixed64Size;
|
||||
case FieldDescriptor::TYPE_SFIXED32: return WireFormat::kSFixed32Size;
|
||||
case FieldDescriptor::TYPE_SFIXED64: return WireFormat::kSFixed64Size;
|
||||
case FieldDescriptor::TYPE_FLOAT : return WireFormat::kFloatSize;
|
||||
case FieldDescriptor::TYPE_DOUBLE : return WireFormat::kDoubleSize;
|
||||
case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
|
||||
case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
|
||||
case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
|
||||
case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
|
||||
case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
|
||||
case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
|
||||
|
||||
case FieldDescriptor::TYPE_BOOL : return WireFormat::kBoolSize;
|
||||
case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize;
|
||||
case FieldDescriptor::TYPE_ENUM : return -1;
|
||||
|
||||
case FieldDescriptor::TYPE_STRING : return -1;
|
||||
@ -163,64 +153,6 @@ int FixedSize(FieldDescriptor::Type type) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
string DefaultValue(const FieldDescriptor* field) {
|
||||
// Switch on cpp_type since we need to know which default_value_* method
|
||||
// of FieldDescriptor to call.
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_INT32:
|
||||
return SimpleItoa(field->default_value_int32());
|
||||
case FieldDescriptor::CPPTYPE_UINT32:
|
||||
// Need to print as a signed int since Java has no unsigned.
|
||||
return SimpleItoa(static_cast<int32>(field->default_value_uint32()));
|
||||
case FieldDescriptor::CPPTYPE_INT64:
|
||||
return SimpleItoa(field->default_value_int64()) + "L";
|
||||
case FieldDescriptor::CPPTYPE_UINT64:
|
||||
return SimpleItoa(static_cast<int64>(field->default_value_uint64())) +
|
||||
"L";
|
||||
case FieldDescriptor::CPPTYPE_DOUBLE:
|
||||
return SimpleDtoa(field->default_value_double()) + "D";
|
||||
case FieldDescriptor::CPPTYPE_FLOAT:
|
||||
return SimpleFtoa(field->default_value_float()) + "F";
|
||||
case FieldDescriptor::CPPTYPE_BOOL:
|
||||
return field->default_value_bool() ? "true" : "false";
|
||||
case FieldDescriptor::CPPTYPE_STRING: {
|
||||
bool isBytes = field->type() == FieldDescriptor::TYPE_BYTES;
|
||||
|
||||
if (!isBytes && AllPrintableAscii(field->default_value_string())) {
|
||||
// All chars are ASCII and printable. In this case CEscape() works
|
||||
// fine (it will only escape quotes and backslashes).
|
||||
// Note: If this "optimization" is removed, DescriptorProtos will
|
||||
// no longer be able to initialize itself due to bootstrapping
|
||||
// problems.
|
||||
return "\"" + CEscape(field->default_value_string()) + "\"";
|
||||
}
|
||||
|
||||
if (isBytes && !field->has_default_value()) {
|
||||
return "com.google.protobuf.ByteString.EMPTY";
|
||||
}
|
||||
|
||||
// Escaping strings correctly for Java and generating efficient
|
||||
// initializers for ByteStrings are both tricky. We can sidestep the
|
||||
// whole problem by just grabbing the default value from the descriptor.
|
||||
return strings::Substitute(
|
||||
"(($0) $1.getDescriptor().getFields().get($2).getDefaultValue())",
|
||||
isBytes ? "com.google.protobuf.ByteString" : "java.lang.String",
|
||||
ClassName(field->containing_type()), field->index());
|
||||
}
|
||||
|
||||
case FieldDescriptor::CPPTYPE_ENUM:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return "";
|
||||
|
||||
// No default because we want the compiler to complain if any new
|
||||
// types are added.
|
||||
}
|
||||
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return "";
|
||||
}
|
||||
|
||||
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
|
||||
map<string, string>* variables) {
|
||||
(*variables)["name"] =
|
||||
@ -285,8 +217,17 @@ GenerateBuilderMembers(io::Printer* printer) const {
|
||||
" return this;\n"
|
||||
"}\n"
|
||||
"public Builder clear$capitalized_name$() {\n"
|
||||
" result.has$capitalized_name$ = false;\n"
|
||||
" result.$name$_ = $default$;\n"
|
||||
" result.has$capitalized_name$ = false;\n");
|
||||
if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
|
||||
// The default value is not a simple literal so we want to avoid executing
|
||||
// it multiple times. Instead, get the default out of the default instance.
|
||||
printer->Print(variables_,
|
||||
" result.$name$_ = getDefaultInstance().get$capitalized_name$();\n");
|
||||
} else {
|
||||
printer->Print(variables_,
|
||||
" result.$name$_ = $default$;\n");
|
||||
}
|
||||
printer->Print(variables_,
|
||||
" return this;\n"
|
||||
"}\n");
|
||||
}
|
||||
@ -355,7 +296,7 @@ GenerateMembers(io::Printer* printer) const {
|
||||
"}\n");
|
||||
|
||||
if (descriptor_->options().packed() &&
|
||||
descriptor_->file()->options().optimize_for() == FileOptions::SPEED) {
|
||||
HasGeneratedMethods(descriptor_->containing_type())) {
|
||||
printer->Print(variables_,
|
||||
"private int $name$MemoizedSerializedSize;\n");
|
||||
}
|
||||
|
@ -661,7 +661,7 @@ bool Parser::ParseOptionAssignment(Message* options) {
|
||||
GOOGLE_CHECK(uninterpreted_option_field != NULL)
|
||||
<< "No field named \"uninterpreted_option\" in the Options proto.";
|
||||
|
||||
UninterpretedOption* uninterpreted_option = ::google::protobuf::down_cast<UninterpretedOption*>(
|
||||
UninterpretedOption* uninterpreted_option = down_cast<UninterpretedOption*>(
|
||||
options->GetReflection()->AddMessage(options,
|
||||
uninterpreted_option_field));
|
||||
|
||||
|
@ -798,7 +798,7 @@ namespace {
|
||||
|
||||
EncodedDescriptorDatabase* generated_database_ = NULL;
|
||||
DescriptorPool* generated_pool_ = NULL;
|
||||
GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_);
|
||||
GoogleOnceType generated_pool_init_;
|
||||
|
||||
void DeleteGeneratedPool() {
|
||||
delete generated_database_;
|
||||
@ -814,7 +814,7 @@ void InitGeneratedPool() {
|
||||
}
|
||||
|
||||
inline void InitGeneratedPoolOnce() {
|
||||
GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool);
|
||||
::google::protobuf::GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
@ -1859,7 +1859,11 @@ class DescriptorBuilder {
|
||||
// dependency of this file, it will fail, but will set
|
||||
// possible_undeclared_dependency_ to point at that file. This is only used
|
||||
// by AddNotDefinedError() to report a more useful error message.
|
||||
// possible_undeclared_dependency_name_ is the name of the symbol that was
|
||||
// actually found in possible_undeclared_dependency_, which may be a parent
|
||||
// of the symbol actually looked for.
|
||||
const FileDescriptor* possible_undeclared_dependency_;
|
||||
string possible_undeclared_dependency_name_;
|
||||
|
||||
void AddError(const string& element_name,
|
||||
const Message& descriptor,
|
||||
@ -2062,7 +2066,7 @@ class DescriptorBuilder {
|
||||
Message* options);
|
||||
|
||||
// A recursive helper function that drills into the intermediate fields
|
||||
// in unknown_fields to check if field #field_number is set on the
|
||||
// in unknown_fields to check if field innermost_field is set on the
|
||||
// innermost message. Returns false and sets an error if so.
|
||||
bool ExamineIfOptionIsSet(
|
||||
vector<const FieldDescriptor*>::const_iterator intermediate_fields_iter,
|
||||
@ -2233,8 +2237,9 @@ void DescriptorBuilder::AddNotDefinedError(
|
||||
"\"" + undefined_symbol + "\" is not defined.");
|
||||
} else {
|
||||
AddError(element_name, descriptor, location,
|
||||
"\"" + undefined_symbol + "\" seems to be defined in \""
|
||||
+ possible_undeclared_dependency_->name() + "\", which is not "
|
||||
"\"" + possible_undeclared_dependency_name_ +
|
||||
"\" seems to be defined in \"" +
|
||||
possible_undeclared_dependency_->name() + "\", which is not "
|
||||
"imported by \"" + filename_ + "\". To use it here, please "
|
||||
"add the necessary import.");
|
||||
}
|
||||
@ -2295,11 +2300,16 @@ Symbol DescriptorBuilder::FindSymbol(const string& name) {
|
||||
// symbol unless none of the dependencies define it.
|
||||
if (IsInPackage(file_, name)) return result;
|
||||
for (int i = 0; i < file_->dependency_count(); i++) {
|
||||
if (IsInPackage(file_->dependency(i), name)) return result;
|
||||
// Note: A dependency may be NULL if it was not found or had errors.
|
||||
if (file_->dependency(i) != NULL &&
|
||||
IsInPackage(file_->dependency(i), name)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
possible_undeclared_dependency_ = file;
|
||||
possible_undeclared_dependency_name_ = name;
|
||||
return kNullSymbol;
|
||||
}
|
||||
|
||||
@ -3592,12 +3602,38 @@ void DescriptorBuilder::CrossLinkMethod(
|
||||
proto.array_name(i)); \
|
||||
}
|
||||
|
||||
// Determine if the file uses optimize_for = LITE_RUNTIME, being careful to
|
||||
// avoid problems that exist at init time.
|
||||
static bool IsLite(const FileDescriptor* file) {
|
||||
// TODO(kenton): I don't even remember how many of these conditions are
|
||||
// actually possible. I'm just being super-safe.
|
||||
return file != NULL &&
|
||||
&file->options() != NULL &&
|
||||
&file->options() != &FileOptions::default_instance() &&
|
||||
file->options().optimize_for() == FileOptions::LITE_RUNTIME;
|
||||
}
|
||||
|
||||
void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file,
|
||||
const FileDescriptorProto& proto) {
|
||||
VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message);
|
||||
VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum);
|
||||
VALIDATE_OPTIONS_FROM_ARRAY(file, service, Service);
|
||||
VALIDATE_OPTIONS_FROM_ARRAY(file, extension, Field);
|
||||
|
||||
// Lite files can only be imported by other Lite files.
|
||||
if (!IsLite(file)) {
|
||||
for (int i = 0; i < file->dependency_count(); i++) {
|
||||
if (IsLite(file->dependency(i))) {
|
||||
AddError(
|
||||
file->name(), proto,
|
||||
DescriptorPool::ErrorCollector::OTHER,
|
||||
"Files that do not use optimize_for = LITE_RUNTIME cannot import "
|
||||
"files which do use this option. This file is not lite, but it "
|
||||
"imports \"" + file->dependency(i)->name() + "\" which is.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DescriptorBuilder::ValidateMessageOptions(Descriptor* message,
|
||||
@ -3647,6 +3683,17 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field,
|
||||
"MessageSets cannot have fields, only extensions.");
|
||||
}
|
||||
}
|
||||
|
||||
// Lite extensions can only be of Lite types.
|
||||
if (IsLite(field->file()) &&
|
||||
field->containing_type_ != NULL &&
|
||||
!IsLite(field->containing_type()->file())) {
|
||||
AddError(field->full_name(), proto,
|
||||
DescriptorPool::ErrorCollector::EXTENDEE,
|
||||
"Extensions to non-lite types can only be declared in non-lite "
|
||||
"files. Note that you cannot extend a non-lite type to contain "
|
||||
"a lite type, but the reverse is allowed.");
|
||||
}
|
||||
}
|
||||
|
||||
void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
|
||||
@ -3660,6 +3707,12 @@ void DescriptorBuilder::ValidateEnumValueOptions(
|
||||
}
|
||||
void DescriptorBuilder::ValidateServiceOptions(ServiceDescriptor* service,
|
||||
const ServiceDescriptorProto& proto) {
|
||||
if (IsLite(service->file())) {
|
||||
AddError(service->full_name(), proto,
|
||||
DescriptorPool::ErrorCollector::NAME,
|
||||
"Files with optimize_for = LITE_RUNTIME cannot define services.");
|
||||
}
|
||||
|
||||
VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method);
|
||||
}
|
||||
|
||||
@ -3761,7 +3814,7 @@ bool DescriptorBuilder::OptionInterpreter::InterpretOptions(
|
||||
const int num_uninterpreted_options = original_options->GetReflection()->
|
||||
FieldSize(*original_options, original_uninterpreted_options_field);
|
||||
for (int i = 0; i < num_uninterpreted_options; ++i) {
|
||||
uninterpreted_option_ = ::google::protobuf::down_cast<const UninterpretedOption*>(
|
||||
uninterpreted_option_ = down_cast<const UninterpretedOption*>(
|
||||
&original_options->GetReflection()->GetRepeatedMessage(
|
||||
*original_options, original_uninterpreted_options_field, i));
|
||||
if (!InterpretSingleOption(options)) {
|
||||
@ -4009,14 +4062,13 @@ bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet(
|
||||
const UnknownField* unknown_field = &unknown_fields.field(i);
|
||||
FieldDescriptor::Type type = (*intermediate_fields_iter)->type();
|
||||
// Recurse into the next submessage.
|
||||
++intermediate_fields_iter;
|
||||
switch (type) {
|
||||
case FieldDescriptor::TYPE_MESSAGE:
|
||||
if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) {
|
||||
UnknownFieldSet intermediate_unknown_fields;
|
||||
if (intermediate_unknown_fields.ParseFromString(
|
||||
unknown_field->length_delimited()) &&
|
||||
!ExamineIfOptionIsSet(intermediate_fields_iter,
|
||||
!ExamineIfOptionIsSet(intermediate_fields_iter + 1,
|
||||
intermediate_fields_end,
|
||||
innermost_field, debug_msg_name,
|
||||
intermediate_unknown_fields)) {
|
||||
@ -4027,7 +4079,7 @@ bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet(
|
||||
|
||||
case FieldDescriptor::TYPE_GROUP:
|
||||
if (unknown_field->type() == UnknownField::TYPE_GROUP) {
|
||||
if (!ExamineIfOptionIsSet(intermediate_fields_iter,
|
||||
if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1,
|
||||
intermediate_fields_end,
|
||||
innermost_field, debug_msg_name,
|
||||
unknown_field->group())) {
|
||||
@ -4139,7 +4191,7 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
|
||||
option_field->full_name() + "\".");
|
||||
}
|
||||
unknown_fields->AddFixed32(option_field->number(),
|
||||
google::protobuf::internal::WireFormat::EncodeFloat(value));
|
||||
google::protobuf::internal::WireFormatLite::EncodeFloat(value));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4156,7 +4208,7 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
|
||||
option_field->full_name() + "\".");
|
||||
}
|
||||
unknown_fields->AddFixed64(option_field->number(),
|
||||
google::protobuf::internal::WireFormat::EncodeDouble(value));
|
||||
google::protobuf::internal::WireFormatLite::EncodeDouble(value));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4267,7 +4319,7 @@ void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value,
|
||||
|
||||
case FieldDescriptor::TYPE_SINT32:
|
||||
unknown_fields->AddVarint(number,
|
||||
google::protobuf::internal::WireFormat::ZigZagEncode32(value));
|
||||
google::protobuf::internal::WireFormatLite::ZigZagEncode32(value));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -4289,7 +4341,7 @@ void DescriptorBuilder::OptionInterpreter::SetInt64(int number, int64 value,
|
||||
|
||||
case FieldDescriptor::TYPE_SINT64:
|
||||
unknown_fields->AddVarint(number,
|
||||
google::protobuf::internal::WireFormat::ZigZagEncode64(value));
|
||||
google::protobuf::internal::WireFormatLite::ZigZagEncode64(value));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -18,9 +18,10 @@
|
||||
#error regenerate this file with a newer version of protoc.
|
||||
#endif
|
||||
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
@ -69,11 +70,11 @@ enum FieldDescriptorProto_Type {
|
||||
FieldDescriptorProto_Type_TYPE_SINT32 = 17,
|
||||
FieldDescriptorProto_Type_TYPE_SINT64 = 18
|
||||
};
|
||||
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor();
|
||||
LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Type_IsValid(int value);
|
||||
const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MIN = FieldDescriptorProto_Type_TYPE_DOUBLE;
|
||||
const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MAX = FieldDescriptorProto_Type_TYPE_SINT64;
|
||||
|
||||
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor();
|
||||
inline const ::std::string& FieldDescriptorProto_Type_Name(FieldDescriptorProto_Type value) {
|
||||
return ::google::protobuf::internal::NameOfEnum(
|
||||
FieldDescriptorProto_Type_descriptor(), value);
|
||||
@ -88,11 +89,11 @@ enum FieldDescriptorProto_Label {
|
||||
FieldDescriptorProto_Label_LABEL_REQUIRED = 2,
|
||||
FieldDescriptorProto_Label_LABEL_REPEATED = 3
|
||||
};
|
||||
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor();
|
||||
LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Label_IsValid(int value);
|
||||
const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MIN = FieldDescriptorProto_Label_LABEL_OPTIONAL;
|
||||
const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MAX = FieldDescriptorProto_Label_LABEL_REPEATED;
|
||||
|
||||
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor();
|
||||
inline const ::std::string& FieldDescriptorProto_Label_Name(FieldDescriptorProto_Label value) {
|
||||
return ::google::protobuf::internal::NameOfEnum(
|
||||
FieldDescriptorProto_Label_descriptor(), value);
|
||||
@ -104,13 +105,14 @@ inline bool FieldDescriptorProto_Label_Parse(
|
||||
}
|
||||
enum FileOptions_OptimizeMode {
|
||||
FileOptions_OptimizeMode_SPEED = 1,
|
||||
FileOptions_OptimizeMode_CODE_SIZE = 2
|
||||
FileOptions_OptimizeMode_CODE_SIZE = 2,
|
||||
FileOptions_OptimizeMode_LITE_RUNTIME = 3
|
||||
};
|
||||
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor();
|
||||
LIBPROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value);
|
||||
const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = FileOptions_OptimizeMode_SPEED;
|
||||
const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = FileOptions_OptimizeMode_CODE_SIZE;
|
||||
const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = FileOptions_OptimizeMode_LITE_RUNTIME;
|
||||
|
||||
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor();
|
||||
inline const ::std::string& FileOptions_OptimizeMode_Name(FileOptions_OptimizeMode value) {
|
||||
return ::google::protobuf::internal::NameOfEnum(
|
||||
FileOptions_OptimizeMode_descriptor(), value);
|
||||
@ -124,11 +126,11 @@ enum FieldOptions_CType {
|
||||
FieldOptions_CType_CORD = 1,
|
||||
FieldOptions_CType_STRING_PIECE = 2
|
||||
};
|
||||
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor();
|
||||
LIBPROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value);
|
||||
const FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_CORD;
|
||||
const FieldOptions_CType FieldOptions_CType_CType_MAX = FieldOptions_CType_STRING_PIECE;
|
||||
|
||||
LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor();
|
||||
inline const ::std::string& FieldOptions_CType_Name(FieldOptions_CType value) {
|
||||
return ::google::protobuf::internal::NameOfEnum(
|
||||
FieldOptions_CType_descriptor(), value);
|
||||
@ -187,8 +189,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -212,6 +213,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -277,8 +279,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -384,6 +385,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -449,8 +451,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -479,6 +480,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -544,8 +546,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -635,6 +636,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -700,8 +702,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -724,13 +725,17 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
|
||||
static const Type TYPE_SFIXED64 = FieldDescriptorProto_Type_TYPE_SFIXED64;
|
||||
static const Type TYPE_SINT32 = FieldDescriptorProto_Type_TYPE_SINT32;
|
||||
static const Type TYPE_SINT64 = FieldDescriptorProto_Type_TYPE_SINT64;
|
||||
static inline bool Type_IsValid(int value) {
|
||||
return FieldDescriptorProto_Type_IsValid(value);
|
||||
}
|
||||
static const Type Type_MIN =
|
||||
FieldDescriptorProto_Type_Type_MIN;
|
||||
static const Type Type_MAX =
|
||||
FieldDescriptorProto_Type_Type_MAX;
|
||||
static inline const ::google::protobuf::EnumDescriptor*
|
||||
Type_descriptor() {
|
||||
return FieldDescriptorProto_Type_descriptor();
|
||||
}
|
||||
static inline bool Type_IsValid(int value) {
|
||||
return FieldDescriptorProto_Type_IsValid(value);
|
||||
}
|
||||
static inline const ::std::string& Type_Name(Type value) {
|
||||
return FieldDescriptorProto_Type_Name(value);
|
||||
}
|
||||
@ -738,22 +743,22 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
|
||||
Type* value) {
|
||||
return FieldDescriptorProto_Type_Parse(name, value);
|
||||
}
|
||||
static const Type Type_MIN =
|
||||
FieldDescriptorProto_Type_Type_MIN;
|
||||
static const Type Type_MAX =
|
||||
FieldDescriptorProto_Type_Type_MAX;
|
||||
|
||||
typedef FieldDescriptorProto_Label Label;
|
||||
static const Label LABEL_OPTIONAL = FieldDescriptorProto_Label_LABEL_OPTIONAL;
|
||||
static const Label LABEL_REQUIRED = FieldDescriptorProto_Label_LABEL_REQUIRED;
|
||||
static const Label LABEL_REPEATED = FieldDescriptorProto_Label_LABEL_REPEATED;
|
||||
static inline bool Label_IsValid(int value) {
|
||||
return FieldDescriptorProto_Label_IsValid(value);
|
||||
}
|
||||
static const Label Label_MIN =
|
||||
FieldDescriptorProto_Label_Label_MIN;
|
||||
static const Label Label_MAX =
|
||||
FieldDescriptorProto_Label_Label_MAX;
|
||||
static inline const ::google::protobuf::EnumDescriptor*
|
||||
Label_descriptor() {
|
||||
return FieldDescriptorProto_Label_descriptor();
|
||||
}
|
||||
static inline bool Label_IsValid(int value) {
|
||||
return FieldDescriptorProto_Label_IsValid(value);
|
||||
}
|
||||
static inline const ::std::string& Label_Name(Label value) {
|
||||
return FieldDescriptorProto_Label_Name(value);
|
||||
}
|
||||
@ -761,10 +766,6 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
|
||||
Label* value) {
|
||||
return FieldDescriptorProto_Label_Parse(name, value);
|
||||
}
|
||||
static const Label Label_MIN =
|
||||
FieldDescriptorProto_Label_Label_MIN;
|
||||
static const Label Label_MAX =
|
||||
FieldDescriptorProto_Label_Label_MAX;
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
@ -855,6 +856,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -920,8 +922,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -965,6 +966,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -1030,8 +1032,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -1072,6 +1073,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -1137,8 +1139,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -1182,6 +1183,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -1247,8 +1249,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -1305,6 +1306,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -1370,21 +1372,25 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
typedef FileOptions_OptimizeMode OptimizeMode;
|
||||
static const OptimizeMode SPEED = FileOptions_OptimizeMode_SPEED;
|
||||
static const OptimizeMode CODE_SIZE = FileOptions_OptimizeMode_CODE_SIZE;
|
||||
static const OptimizeMode LITE_RUNTIME = FileOptions_OptimizeMode_LITE_RUNTIME;
|
||||
static inline bool OptimizeMode_IsValid(int value) {
|
||||
return FileOptions_OptimizeMode_IsValid(value);
|
||||
}
|
||||
static const OptimizeMode OptimizeMode_MIN =
|
||||
FileOptions_OptimizeMode_OptimizeMode_MIN;
|
||||
static const OptimizeMode OptimizeMode_MAX =
|
||||
FileOptions_OptimizeMode_OptimizeMode_MAX;
|
||||
static inline const ::google::protobuf::EnumDescriptor*
|
||||
OptimizeMode_descriptor() {
|
||||
return FileOptions_OptimizeMode_descriptor();
|
||||
}
|
||||
static inline bool OptimizeMode_IsValid(int value) {
|
||||
return FileOptions_OptimizeMode_IsValid(value);
|
||||
}
|
||||
static inline const ::std::string& OptimizeMode_Name(OptimizeMode value) {
|
||||
return FileOptions_OptimizeMode_Name(value);
|
||||
}
|
||||
@ -1392,10 +1398,6 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
|
||||
OptimizeMode* value) {
|
||||
return FileOptions_OptimizeMode_Parse(name, value);
|
||||
}
|
||||
static const OptimizeMode OptimizeMode_MIN =
|
||||
FileOptions_OptimizeMode_OptimizeMode_MIN;
|
||||
static const OptimizeMode OptimizeMode_MAX =
|
||||
FileOptions_OptimizeMode_OptimizeMode_MAX;
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
@ -1459,6 +1461,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -1524,8 +1527,7 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -1538,6 +1540,13 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
|
||||
inline bool message_set_wire_format() const;
|
||||
inline void set_message_set_wire_format(bool value);
|
||||
|
||||
// optional bool no_standard_descriptor_accessor = 2 [default = false];
|
||||
inline bool has_no_standard_descriptor_accessor() const;
|
||||
inline void clear_no_standard_descriptor_accessor();
|
||||
static const int kNoStandardDescriptorAccessorFieldNumber = 2;
|
||||
inline bool no_standard_descriptor_accessor() const;
|
||||
inline void set_no_standard_descriptor_accessor(bool value);
|
||||
|
||||
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
|
||||
inline int uninterpreted_option_size() const;
|
||||
inline void clear_uninterpreted_option();
|
||||
@ -1555,11 +1564,13 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
|
||||
mutable int _cached_size_;
|
||||
|
||||
bool message_set_wire_format_;
|
||||
bool no_standard_descriptor_accessor_;
|
||||
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
inline bool _has_bit(int index) const {
|
||||
@ -1624,21 +1635,24 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
typedef FieldOptions_CType CType;
|
||||
static const CType CORD = FieldOptions_CType_CORD;
|
||||
static const CType STRING_PIECE = FieldOptions_CType_STRING_PIECE;
|
||||
static inline bool CType_IsValid(int value) {
|
||||
return FieldOptions_CType_IsValid(value);
|
||||
}
|
||||
static const CType CType_MIN =
|
||||
FieldOptions_CType_CType_MIN;
|
||||
static const CType CType_MAX =
|
||||
FieldOptions_CType_CType_MAX;
|
||||
static inline const ::google::protobuf::EnumDescriptor*
|
||||
CType_descriptor() {
|
||||
return FieldOptions_CType_descriptor();
|
||||
}
|
||||
static inline bool CType_IsValid(int value) {
|
||||
return FieldOptions_CType_IsValid(value);
|
||||
}
|
||||
static inline const ::std::string& CType_Name(CType value) {
|
||||
return FieldOptions_CType_Name(value);
|
||||
}
|
||||
@ -1646,10 +1660,6 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
|
||||
CType* value) {
|
||||
return FieldOptions_CType_Parse(name, value);
|
||||
}
|
||||
static const CType CType_MIN =
|
||||
FieldOptions_CType_CType_MIN;
|
||||
static const CType CType_MAX =
|
||||
FieldOptions_CType_CType_MAX;
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
|
||||
@ -1709,6 +1719,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(5 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -1774,8 +1785,7 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -1801,6 +1811,7 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -1866,8 +1877,7 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -1893,6 +1903,7 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -1958,8 +1969,7 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -1985,6 +1995,7 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -2050,8 +2061,7 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -2077,6 +2087,7 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -2142,8 +2153,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -2176,6 +2186,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -2241,8 +2252,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
|
||||
void SetCachedSize(int size) const { _cached_size_ = size; }
|
||||
public:
|
||||
|
||||
const ::google::protobuf::Descriptor* GetDescriptor() const;
|
||||
const ::google::protobuf::Reflection* GetReflection() const;
|
||||
::google::protobuf::Metadata GetMetadata() const;
|
||||
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
@ -2316,6 +2326,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
|
||||
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
|
||||
|
||||
::google::protobuf::uint32 _has_bits_[(6 + 31) / 32];
|
||||
|
||||
// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
|
||||
@ -3647,6 +3658,22 @@ inline void MessageOptions::set_message_set_wire_format(bool value) {
|
||||
message_set_wire_format_ = value;
|
||||
}
|
||||
|
||||
// optional bool no_standard_descriptor_accessor = 2 [default = false];
|
||||
inline bool MessageOptions::has_no_standard_descriptor_accessor() const {
|
||||
return _has_bit(1);
|
||||
}
|
||||
inline void MessageOptions::clear_no_standard_descriptor_accessor() {
|
||||
no_standard_descriptor_accessor_ = false;
|
||||
_clear_bit(1);
|
||||
}
|
||||
inline bool MessageOptions::no_standard_descriptor_accessor() const {
|
||||
return no_standard_descriptor_accessor_;
|
||||
}
|
||||
inline void MessageOptions::set_no_standard_descriptor_accessor(bool value) {
|
||||
_set_bit(1);
|
||||
no_standard_descriptor_accessor_ = value;
|
||||
}
|
||||
|
||||
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
|
||||
inline int MessageOptions::uninterpreted_option_size() const {
|
||||
return uninterpreted_option_.size();
|
||||
@ -4134,4 +4161,30 @@ inline ::std::string* UninterpretedOption::mutable_string_value() {
|
||||
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#ifndef SWIG
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
|
||||
template <>
|
||||
inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Type>() {
|
||||
return ::google::protobuf::FieldDescriptorProto_Type_descriptor();
|
||||
}
|
||||
template <>
|
||||
inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Label>() {
|
||||
return ::google::protobuf::FieldDescriptorProto_Label_descriptor();
|
||||
}
|
||||
template <>
|
||||
inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FileOptions_OptimizeMode>() {
|
||||
return ::google::protobuf::FileOptions_OptimizeMode_descriptor();
|
||||
}
|
||||
template <>
|
||||
inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_CType>() {
|
||||
return ::google::protobuf::FieldOptions_CType_descriptor();
|
||||
}
|
||||
|
||||
} // namespace google
|
||||
} // namespace protobuf
|
||||
#endif // SWIG
|
||||
|
||||
#endif // PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
|
||||
|
@ -247,8 +247,10 @@ message FileOptions {
|
||||
|
||||
// Generated classes can be optimized for speed or code size.
|
||||
enum OptimizeMode {
|
||||
SPEED = 1; // Generate complete code for parsing, serialization, etc.
|
||||
CODE_SIZE = 2; // Use ReflectionOps to implement these methods.
|
||||
SPEED = 1; // Generate complete code for parsing, serialization,
|
||||
// etc.
|
||||
CODE_SIZE = 2; // Use ReflectionOps to implement these methods.
|
||||
LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
|
||||
}
|
||||
optional OptimizeMode optimize_for = 9 [default=SPEED];
|
||||
|
||||
@ -282,6 +284,11 @@ message MessageOptions {
|
||||
// the protocol compiler.
|
||||
optional bool message_set_wire_format = 1 [default=false];
|
||||
|
||||
// Disables the generation of the standard "descriptor()" accessor, which can
|
||||
// conflict with a field of the same name. This is meant to make migration
|
||||
// from proto1 easier; new code should avoid fields named "descriptor".
|
||||
optional bool no_standard_descriptor_accessor = 2 [default=false];
|
||||
|
||||
// The parser stores options it doesn't recognize here. See above.
|
||||
repeated UninterpretedOption uninterpreted_option = 999;
|
||||
|
||||
|
@ -2135,6 +2135,83 @@ TEST(CustomOptions, OptionsFromOtherFile) {
|
||||
EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for());
|
||||
}
|
||||
|
||||
TEST(CustomOptions, MessageOptionThreeFieldsSet) {
|
||||
// This tests a bug which previously existed in custom options parsing. The
|
||||
// bug occurred when you defined a custom option with message type and then
|
||||
// set three fields of that option on a single definition (see the example
|
||||
// below). The bug is a bit hard to explain, so check the change history if
|
||||
// you want to know more.
|
||||
DescriptorPool pool;
|
||||
|
||||
FileDescriptorProto file_proto;
|
||||
FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
|
||||
ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
|
||||
|
||||
protobuf_unittest::TestMessageWithCustomOptions::descriptor()
|
||||
->file()->CopyTo(&file_proto);
|
||||
ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
|
||||
|
||||
// The following represents the definition:
|
||||
//
|
||||
// import "google/protobuf/unittest_custom_options.proto"
|
||||
// package protobuf_unittest;
|
||||
// message Foo {
|
||||
// option (complex_opt1).foo = 1234;
|
||||
// option (complex_opt1).foo2 = 1234;
|
||||
// option (complex_opt1).foo3 = 1234;
|
||||
// }
|
||||
ASSERT_TRUE(TextFormat::ParseFromString(
|
||||
"name: \"custom_options_import.proto\" "
|
||||
"package: \"protobuf_unittest\" "
|
||||
"dependency: \"google/protobuf/unittest_custom_options.proto\" "
|
||||
"message_type { "
|
||||
" name: \"Foo\" "
|
||||
" options { "
|
||||
" uninterpreted_option { "
|
||||
" name { "
|
||||
" name_part: \"complex_opt1\" "
|
||||
" is_extension: true "
|
||||
" } "
|
||||
" name { "
|
||||
" name_part: \"foo\" "
|
||||
" is_extension: false "
|
||||
" } "
|
||||
" positive_int_value: 1234 "
|
||||
" } "
|
||||
" uninterpreted_option { "
|
||||
" name { "
|
||||
" name_part: \"complex_opt1\" "
|
||||
" is_extension: true "
|
||||
" } "
|
||||
" name { "
|
||||
" name_part: \"foo2\" "
|
||||
" is_extension: false "
|
||||
" } "
|
||||
" positive_int_value: 1234 "
|
||||
" } "
|
||||
" uninterpreted_option { "
|
||||
" name { "
|
||||
" name_part: \"complex_opt1\" "
|
||||
" is_extension: true "
|
||||
" } "
|
||||
" name { "
|
||||
" name_part: \"foo3\" "
|
||||
" is_extension: false "
|
||||
" } "
|
||||
" positive_int_value: 1234 "
|
||||
" } "
|
||||
" } "
|
||||
"}",
|
||||
&file_proto));
|
||||
|
||||
const FileDescriptor* file = pool.BuildFile(file_proto);
|
||||
ASSERT_TRUE(file != NULL);
|
||||
ASSERT_EQ(1, file->message_type_count());
|
||||
|
||||
const MessageOptions& options = file->message_type(0)->options();
|
||||
EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo());
|
||||
}
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
@ -2335,6 +2412,30 @@ TEST_F(ValidationErrorTest, UnknownDependency) {
|
||||
"bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n");
|
||||
}
|
||||
|
||||
TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) {
|
||||
// Used to crash: If we depend on a non-existent file and then refer to a
|
||||
// package defined in a file that we didn't import, and that package is
|
||||
// nested within a parent package which this file is also in, and we don't
|
||||
// include that parent package in the name (i.e. we do a relative lookup)...
|
||||
// Yes, really.
|
||||
BuildFile(
|
||||
"name: 'foo.proto' "
|
||||
"package: 'outer.foo' ");
|
||||
BuildFileWithErrors(
|
||||
"name: 'bar.proto' "
|
||||
"dependency: 'baz.proto' "
|
||||
"package: 'outer.bar' "
|
||||
"message_type { "
|
||||
" name: 'Bar' "
|
||||
" field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }"
|
||||
"}",
|
||||
|
||||
"bar.proto: bar.proto: OTHER: Import \"baz.proto\" has not been loaded.\n"
|
||||
"bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined in "
|
||||
"\"foo.proto\", which is not imported by \"bar.proto\". To use it here, "
|
||||
"please add the necessary import.\n");
|
||||
}
|
||||
|
||||
TEST_F(ValidationErrorTest, DupeFile) {
|
||||
BuildFile(
|
||||
"name: \"foo.proto\" "
|
||||
@ -3345,6 +3446,50 @@ TEST_F(ValidationErrorTest, TryingToSetMessageValuedOption) {
|
||||
"message type.\n");
|
||||
}
|
||||
|
||||
TEST_F(ValidationErrorTest, NotLiteImportsLite) {
|
||||
BuildFile(
|
||||
"name: \"bar.proto\" "
|
||||
"options { optimize_for: LITE_RUNTIME } ");
|
||||
|
||||
BuildFileWithErrors(
|
||||
"name: \"foo.proto\" "
|
||||
"dependency: \"bar.proto\" ",
|
||||
|
||||
"foo.proto: foo.proto: OTHER: Files that do not use optimize_for = "
|
||||
"LITE_RUNTIME cannot import files which do use this option. This file "
|
||||
"is not lite, but it imports \"bar.proto\" which is.\n");
|
||||
}
|
||||
|
||||
TEST_F(ValidationErrorTest, LiteExtendsNotLite) {
|
||||
BuildFile(
|
||||
"name: \"bar.proto\" "
|
||||
"message_type: {"
|
||||
" name: \"Bar\""
|
||||
" extension_range { start: 1 end: 1000 }"
|
||||
"}");
|
||||
|
||||
BuildFileWithErrors(
|
||||
"name: \"foo.proto\" "
|
||||
"dependency: \"bar.proto\" "
|
||||
"options { optimize_for: LITE_RUNTIME } "
|
||||
"extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL "
|
||||
" type: TYPE_INT32 extendee: \"Bar\" }",
|
||||
|
||||
"foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be "
|
||||
"declared in non-lite files. Note that you cannot extend a non-lite "
|
||||
"type to contain a lite type, but the reverse is allowed.\n");
|
||||
}
|
||||
|
||||
TEST_F(ValidationErrorTest, NoLiteServices) {
|
||||
BuildFileWithErrors(
|
||||
"name: \"foo.proto\" "
|
||||
"options { optimize_for: LITE_RUNTIME } "
|
||||
"service { name: \"Foo\" }",
|
||||
|
||||
"foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
|
||||
"define services.\n");
|
||||
}
|
||||
|
||||
TEST_F(ValidationErrorTest, RollbackAfterError) {
|
||||
// Build a file which contains every kind of construct but references an
|
||||
// undefined type. All these constructs will be added to the symbol table
|
||||
|
@ -70,6 +70,7 @@
|
||||
#include <google/protobuf/dynamic_message.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/generated_message_reflection.h>
|
||||
#include <google/protobuf/reflection_ops.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
@ -82,7 +83,6 @@ namespace protobuf {
|
||||
using internal::WireFormat;
|
||||
using internal::ExtensionSet;
|
||||
using internal::GeneratedMessageReflection;
|
||||
using internal::GenericRepeatedField;
|
||||
|
||||
|
||||
// ===================================================================
|
||||
@ -186,8 +186,7 @@ class DynamicMessage : public Message {
|
||||
int GetCachedSize() const;
|
||||
void SetCachedSize(int size) const;
|
||||
|
||||
const Descriptor* GetDescriptor() const;
|
||||
const Reflection* GetReflection() const;
|
||||
Metadata GetMetadata() const;
|
||||
|
||||
private:
|
||||
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
|
||||
@ -279,20 +278,10 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info)
|
||||
break;
|
||||
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE: {
|
||||
// If this object is the prototype, its CPPTYPE_MESSAGE fields
|
||||
// must be initialized later, in CrossLinkPrototypes(), so we don't
|
||||
// initialize them here.
|
||||
if (!is_prototype()) {
|
||||
if (!field->is_repeated()) {
|
||||
new(field_ptr) Message*(NULL);
|
||||
} else {
|
||||
const RepeatedPtrField<Message>* prototype_field =
|
||||
reinterpret_cast<const RepeatedPtrField<Message>*>(
|
||||
type_info_->prototype->OffsetToPointer(
|
||||
type_info_->offsets[i]));
|
||||
new(field_ptr) RepeatedPtrField<Message>(
|
||||
prototype_field->prototype());
|
||||
}
|
||||
if (!field->is_repeated()) {
|
||||
new(field_ptr) Message*(NULL);
|
||||
} else {
|
||||
new(field_ptr) RepeatedPtrField<Message>();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -322,9 +311,33 @@ DynamicMessage::~DynamicMessage() {
|
||||
void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
|
||||
|
||||
if (field->is_repeated()) {
|
||||
GenericRepeatedField* field =
|
||||
reinterpret_cast<GenericRepeatedField*>(field_ptr);
|
||||
field->~GenericRepeatedField();
|
||||
switch (field->cpp_type()) {
|
||||
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
|
||||
case FieldDescriptor::CPPTYPE_##UPPERCASE : \
|
||||
reinterpret_cast<RepeatedField<LOWERCASE>*>(field_ptr) \
|
||||
->~RepeatedField<LOWERCASE>(); \
|
||||
break
|
||||
|
||||
HANDLE_TYPE( INT32, int32);
|
||||
HANDLE_TYPE( INT64, int64);
|
||||
HANDLE_TYPE(UINT32, uint32);
|
||||
HANDLE_TYPE(UINT64, uint64);
|
||||
HANDLE_TYPE(DOUBLE, double);
|
||||
HANDLE_TYPE( FLOAT, float);
|
||||
HANDLE_TYPE( BOOL, bool);
|
||||
HANDLE_TYPE( ENUM, int);
|
||||
#undef HANDLE_TYPE
|
||||
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
reinterpret_cast<RepeatedPtrField<string>*>(field_ptr)
|
||||
->~RepeatedPtrField<string>();
|
||||
break;
|
||||
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
|
||||
->~RepeatedPtrField<Message>();
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
|
||||
string* ptr = *reinterpret_cast<string**>(field_ptr);
|
||||
@ -353,24 +366,14 @@ void DynamicMessage::CrossLinkPrototypes() {
|
||||
const FieldDescriptor* field = descriptor->field(i);
|
||||
void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
|
||||
|
||||
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
||||
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
|
||||
!field->is_repeated()) {
|
||||
// For fields with message types, we need to cross-link with the
|
||||
// prototype for the field's type.
|
||||
const Message* field_prototype =
|
||||
// For singular fields, the field is just a pointer which should
|
||||
// point to the prototype.
|
||||
*reinterpret_cast<const Message**>(field_ptr) =
|
||||
factory->GetPrototype(field->message_type());
|
||||
|
||||
if (field->is_repeated()) {
|
||||
// For repeated fields, we actually construct the RepeatedPtrField
|
||||
// here, but only for fields with message types. All other repeated
|
||||
// fields are constructed in DynamicMessage's constructor.
|
||||
new(field_ptr) RepeatedPtrField<Message>(field_prototype);
|
||||
} else {
|
||||
// For singular fields, the field is just a pointer which should
|
||||
// point to the prototype. (OK to const_cast here because the
|
||||
// prototype itself will only be available const to the outside
|
||||
// world.)
|
||||
new(field_ptr) Message*(const_cast<Message*>(field_prototype));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -392,12 +395,11 @@ void DynamicMessage::SetCachedSize(int size) const {
|
||||
cached_byte_size_ = size;
|
||||
}
|
||||
|
||||
const Descriptor* DynamicMessage::GetDescriptor() const {
|
||||
return type_info_->type;
|
||||
}
|
||||
|
||||
const Reflection* DynamicMessage::GetReflection() const {
|
||||
return type_info_->reflection.get();
|
||||
Metadata DynamicMessage::GetMetadata() const {
|
||||
Metadata metadata;
|
||||
metadata.descriptor = type_info_->type;
|
||||
metadata.reflection = type_info_->reflection.get();
|
||||
return metadata;
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -45,20 +45,23 @@
|
||||
#include <string>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/message.h>
|
||||
|
||||
namespace google {
|
||||
|
||||
namespace protobuf {
|
||||
class Descriptor; // descriptor.h
|
||||
class FieldDescriptor; // descriptor.h
|
||||
class DescriptorPool; // descriptor.h
|
||||
class Message; // message.h
|
||||
class MessageLite; // message_lite.h
|
||||
class MessageFactory; // message.h
|
||||
class UnknownFieldSet; // unknown_field_set.h
|
||||
namespace io {
|
||||
class CodedInputStream; // coded_stream.h
|
||||
class CodedOutputStream; // coded_stream.h
|
||||
}
|
||||
namespace internal {
|
||||
class FieldSkipper; // wire_format_lite.h
|
||||
}
|
||||
template <typename Element> class RepeatedField; // repeated_field.h
|
||||
template <typename Element> class RepeatedPtrField; // repeated_field.h
|
||||
}
|
||||
@ -66,9 +69,9 @@ namespace protobuf {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Used to store values of type FieldDescriptor::Type without having to
|
||||
// #include descriptor.h. Also, ensures that we use only one byte to store
|
||||
// these values, which is important to keep the layout of
|
||||
// Used to store values of type WireFormatLite::FieldType without having to
|
||||
// #include wire_format_lite.h. Also, ensures that we use only one byte to
|
||||
// store these values, which is important to keep the layout of
|
||||
// ExtensionSet::Extension small.
|
||||
typedef uint8 FieldType;
|
||||
|
||||
@ -98,17 +101,17 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
|
||||
// to look up extensions for parsed field numbers. Note that dynamic parsing
|
||||
// does not use ParseField(); only protocol-compiler-generated parsing
|
||||
// methods do.
|
||||
static void RegisterExtension(const Message* containing_type,
|
||||
static void RegisterExtension(const MessageLite* containing_type,
|
||||
int number, FieldType type,
|
||||
bool is_repeated, bool is_packed);
|
||||
static void RegisterEnumExtension(const Message* containing_type,
|
||||
static void RegisterEnumExtension(const MessageLite* containing_type,
|
||||
int number, FieldType type,
|
||||
bool is_repeated, bool is_packed,
|
||||
EnumValidityFunc* is_valid);
|
||||
static void RegisterMessageExtension(const Message* containing_type,
|
||||
static void RegisterMessageExtension(const MessageLite* containing_type,
|
||||
int number, FieldType type,
|
||||
bool is_repeated, bool is_packed,
|
||||
const Message* prototype);
|
||||
const MessageLite* prototype);
|
||||
|
||||
// =================================================================
|
||||
|
||||
@ -167,9 +170,10 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
|
||||
bool GetBool (int number, bool default_value) const;
|
||||
int GetEnum (int number, int default_value) const;
|
||||
const string & GetString (int number, const string& default_value) const;
|
||||
const Message& GetMessage(int number, const Message& default_value) const;
|
||||
const Message& GetMessage(int number, const Descriptor* message_type,
|
||||
MessageFactory* factory) const;
|
||||
const MessageLite& GetMessage(int number,
|
||||
const MessageLite& default_value) const;
|
||||
const MessageLite& GetMessage(int number, const Descriptor* message_type,
|
||||
MessageFactory* factory) const;
|
||||
|
||||
void SetInt32 (int number, FieldType type, int32 value);
|
||||
void SetInt64 (int number, FieldType type, int64 value);
|
||||
@ -181,11 +185,11 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
|
||||
void SetEnum (int number, FieldType type, int value);
|
||||
void SetString(int number, FieldType type, const string& value);
|
||||
string * MutableString (int number, FieldType type);
|
||||
Message* MutableMessage(int number, FieldType type,
|
||||
const Message& prototype);
|
||||
Message* MutableMessage(int number, FieldType type,
|
||||
const Descriptor* message_type,
|
||||
MessageFactory* factory);
|
||||
MessageLite* MutableMessage(int number, FieldType type,
|
||||
const MessageLite& prototype);
|
||||
MessageLite* MutableMessage(int number, FieldType type,
|
||||
const Descriptor* message_type,
|
||||
MessageFactory* factory);
|
||||
|
||||
// repeated fields -------------------------------------------------
|
||||
|
||||
@ -198,7 +202,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
|
||||
bool GetRepeatedBool (int number, int index) const;
|
||||
int GetRepeatedEnum (int number, int index) const;
|
||||
const string & GetRepeatedString (int number, int index) const;
|
||||
const Message& GetRepeatedMessage(int number, int index) const;
|
||||
const MessageLite& GetRepeatedMessage(int number, int index) const;
|
||||
|
||||
void SetRepeatedInt32 (int number, int index, int32 value);
|
||||
void SetRepeatedInt64 (int number, int index, int64 value);
|
||||
@ -210,7 +214,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
|
||||
void SetRepeatedEnum (int number, int index, int value);
|
||||
void SetRepeatedString(int number, int index, const string& value);
|
||||
string * MutableRepeatedString (int number, int index);
|
||||
Message* MutableRepeatedMessage(int number, int index);
|
||||
MessageLite* MutableRepeatedMessage(int number, int index);
|
||||
|
||||
void AddInt32 (int number, FieldType type, bool packed, int32 value);
|
||||
void AddInt64 (int number, FieldType type, bool packed, int64 value);
|
||||
@ -222,11 +226,11 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
|
||||
void AddEnum (int number, FieldType type, bool packed, int value);
|
||||
void AddString(int number, FieldType type, const string& value);
|
||||
string * AddString (int number, FieldType type);
|
||||
Message* AddMessage(int number, FieldType type,
|
||||
const Message& prototype);
|
||||
Message* AddMessage(int number, FieldType type,
|
||||
const Descriptor* message_type,
|
||||
MessageFactory* factory);
|
||||
MessageLite* AddMessage(int number, FieldType type,
|
||||
const MessageLite& prototype);
|
||||
MessageLite* AddMessage(int number, FieldType type,
|
||||
const Descriptor* message_type,
|
||||
MessageFactory* factory);
|
||||
|
||||
void RemoveLast(int number);
|
||||
void SwapElements(int number, int index1, int index2);
|
||||
@ -252,9 +256,31 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
|
||||
// methods of ExtensionSet, this only works for generated message types --
|
||||
// it looks up extensions registered using RegisterExtension().
|
||||
bool ParseField(uint32 tag, io::CodedInputStream* input,
|
||||
const Message* containing_type,
|
||||
const MessageLite* containing_type,
|
||||
FieldSkipper* field_skipper);
|
||||
|
||||
// Specific versions for lite or full messages (constructs the appropriate
|
||||
// FieldSkipper automatically).
|
||||
bool ParseField(uint32 tag, io::CodedInputStream* input,
|
||||
const MessageLite* containing_type);
|
||||
bool ParseField(uint32 tag, io::CodedInputStream* input,
|
||||
const MessageLite* containing_type,
|
||||
UnknownFieldSet* unknown_fields);
|
||||
|
||||
// Parse an entire message in MessageSet format. Such messages have no
|
||||
// fields, only extensions.
|
||||
bool ParseMessageSet(io::CodedInputStream* input,
|
||||
const MessageLite* containing_type,
|
||||
FieldSkipper* field_skipper);
|
||||
|
||||
// Specific versions for lite or full messages (constructs the appropriate
|
||||
// FieldSkipper automatically).
|
||||
bool ParseMessageSet(io::CodedInputStream* input,
|
||||
const MessageLite* containing_type);
|
||||
bool ParseMessageSet(io::CodedInputStream* input,
|
||||
const MessageLite* containing_type,
|
||||
UnknownFieldSet* unknown_fields);
|
||||
|
||||
// Write all extension fields with field numbers in the range
|
||||
// [start_field_number, end_field_number)
|
||||
// to the output stream, using the cached sizes computed when ByteSize() was
|
||||
@ -272,37 +298,50 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
|
||||
int end_field_number,
|
||||
uint8* target) const;
|
||||
|
||||
// Like above but serializes in MessageSet format.
|
||||
void SerializeMessageSetWithCachedSizes(io::CodedOutputStream* output) const;
|
||||
uint8* SerializeMessageSetWithCachedSizesToArray(uint8* target) const;
|
||||
|
||||
// Returns the total serialized size of all the extensions.
|
||||
int ByteSize() const;
|
||||
|
||||
// Like ByteSize() but uses MessageSet format.
|
||||
int MessageSetByteSize() const;
|
||||
|
||||
// Returns (an estimate of) the total number of bytes used for storing the
|
||||
// extensions in memory, excluding sizeof(*this).
|
||||
// extensions in memory, excluding sizeof(*this). If the ExtensionSet is
|
||||
// for a lite message (and thus possibly contains lite messages), the results
|
||||
// are undefined (might work, might crash, might corrupt data, might not even
|
||||
// be linked in). It's up to the protocol compiler to avoid calling this on
|
||||
// such ExtensionSets (easy enough since lite messages don't implement
|
||||
// SpaceUsed()).
|
||||
int SpaceUsedExcludingSelf() const;
|
||||
|
||||
private:
|
||||
|
||||
struct Extension {
|
||||
union {
|
||||
int32 int32_value;
|
||||
int64 int64_value;
|
||||
uint32 uint32_value;
|
||||
uint64 uint64_value;
|
||||
float float_value;
|
||||
double double_value;
|
||||
bool bool_value;
|
||||
int enum_value;
|
||||
string* string_value;
|
||||
Message* message_value;
|
||||
int32 int32_value;
|
||||
int64 int64_value;
|
||||
uint32 uint32_value;
|
||||
uint64 uint64_value;
|
||||
float float_value;
|
||||
double double_value;
|
||||
bool bool_value;
|
||||
int enum_value;
|
||||
string* string_value;
|
||||
MessageLite* message_value;
|
||||
|
||||
RepeatedField <int32 >* repeated_int32_value;
|
||||
RepeatedField <int64 >* repeated_int64_value;
|
||||
RepeatedField <uint32 >* repeated_uint32_value;
|
||||
RepeatedField <uint64 >* repeated_uint64_value;
|
||||
RepeatedField <float >* repeated_float_value;
|
||||
RepeatedField <double >* repeated_double_value;
|
||||
RepeatedField <bool >* repeated_bool_value;
|
||||
RepeatedField <int >* repeated_enum_value;
|
||||
RepeatedPtrField<string >* repeated_string_value;
|
||||
RepeatedPtrField<Message>* repeated_message_value;
|
||||
RepeatedField <int32 >* repeated_int32_value;
|
||||
RepeatedField <int64 >* repeated_int64_value;
|
||||
RepeatedField <uint32 >* repeated_uint32_value;
|
||||
RepeatedField <uint64 >* repeated_uint64_value;
|
||||
RepeatedField <float >* repeated_float_value;
|
||||
RepeatedField <double >* repeated_double_value;
|
||||
RepeatedField <bool >* repeated_bool_value;
|
||||
RepeatedField <int >* repeated_enum_value;
|
||||
RepeatedPtrField<string >* repeated_string_value;
|
||||
RepeatedPtrField<MessageLite>* repeated_message_value;
|
||||
};
|
||||
|
||||
FieldType type;
|
||||
@ -328,7 +367,11 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
|
||||
void SerializeFieldWithCachedSizes(
|
||||
int number,
|
||||
io::CodedOutputStream* output) const;
|
||||
void SerializeMessageSetItemWithCachedSizes(
|
||||
int number,
|
||||
io::CodedOutputStream* output) const;
|
||||
int ByteSize(int number) const;
|
||||
int MessageSetItemByteSize(int number) const;
|
||||
void Clear();
|
||||
int GetSize() const;
|
||||
void Free();
|
||||
@ -339,6 +382,13 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
|
||||
// already exist. Returns true if the extension did not already exist.
|
||||
bool MaybeNewExtension(int number, Extension** result);
|
||||
|
||||
// Parse a single MessageSet item -- called just after the item group start
|
||||
// tag has been read.
|
||||
bool ParseMessageSetItem(io::CodedInputStream* input,
|
||||
const MessageLite* containing_type,
|
||||
FieldSkipper* field_skipper);
|
||||
|
||||
|
||||
// The Extension struct is small enough to be passed by value, so we use it
|
||||
// directly as the value type in the map rather than use pointers. We use
|
||||
// a map rather than hash_map here because we expect most ExtensionSets will
|
||||
|
218
src/google/protobuf/extension_set_heavy.cc
Normal file
218
src/google/protobuf/extension_set_heavy.cc
Normal file
@ -0,0 +1,218 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// Contains methods defined in extension_set.h which cannot be part of the
|
||||
// lite library because they use descriptors or reflection.
|
||||
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/wire_format.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
void ExtensionSet::AppendToList(const Descriptor* containing_type,
|
||||
const DescriptorPool* pool,
|
||||
vector<const FieldDescriptor*>* output) const {
|
||||
for (map<int, Extension>::const_iterator iter = extensions_.begin();
|
||||
iter != extensions_.end(); ++iter) {
|
||||
bool has = false;
|
||||
if (iter->second.is_repeated) {
|
||||
has = iter->second.GetSize() > 0;
|
||||
} else {
|
||||
has = !iter->second.is_cleared;
|
||||
}
|
||||
|
||||
if (has) {
|
||||
output->push_back(
|
||||
pool->FindExtensionByNumber(containing_type, iter->first));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline FieldDescriptor::CppType cpp_type(FieldType type) {
|
||||
return FieldDescriptor::TypeToCppType(
|
||||
static_cast<FieldDescriptor::Type>(type));
|
||||
}
|
||||
|
||||
#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \
|
||||
GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \
|
||||
: FieldDescriptor::LABEL_OPTIONAL, \
|
||||
FieldDescriptor::LABEL_##LABEL); \
|
||||
GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE)
|
||||
|
||||
const MessageLite& ExtensionSet::GetMessage(int number,
|
||||
const Descriptor* message_type,
|
||||
MessageFactory* factory) const {
|
||||
map<int, Extension>::const_iterator iter = extensions_.find(number);
|
||||
if (iter == extensions_.end() || iter->second.is_cleared) {
|
||||
// Not present. Return the default value.
|
||||
return *factory->GetPrototype(message_type);
|
||||
} else {
|
||||
GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
|
||||
return *iter->second.message_value;
|
||||
}
|
||||
}
|
||||
|
||||
MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
|
||||
const Descriptor* message_type,
|
||||
MessageFactory* factory) {
|
||||
Extension* extension;
|
||||
if (MaybeNewExtension(number, &extension)) {
|
||||
extension->type = type;
|
||||
GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
|
||||
extension->is_repeated = false;
|
||||
extension->is_packed = false;
|
||||
const MessageLite* prototype = factory->GetPrototype(message_type);
|
||||
GOOGLE_CHECK(prototype != NULL);
|
||||
extension->message_value = prototype->New();
|
||||
} else {
|
||||
GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
|
||||
}
|
||||
extension->is_cleared = false;
|
||||
return extension->message_value;
|
||||
}
|
||||
|
||||
MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
|
||||
const Descriptor* message_type,
|
||||
MessageFactory* factory) {
|
||||
Extension* extension;
|
||||
if (MaybeNewExtension(number, &extension)) {
|
||||
extension->type = type;
|
||||
GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
|
||||
extension->is_repeated = true;
|
||||
extension->repeated_message_value =
|
||||
new RepeatedPtrField<MessageLite>();
|
||||
} else {
|
||||
GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
|
||||
}
|
||||
|
||||
// RepeatedPtrField<Message> does not know how to Add() since it cannot
|
||||
// allocate an abstract object, so we have to be tricky.
|
||||
MessageLite* result = extension->repeated_message_value
|
||||
->AddFromCleared<internal::GenericTypeHandler<MessageLite> >();
|
||||
if (result == NULL) {
|
||||
const MessageLite* prototype;
|
||||
if (extension->repeated_message_value->size() == 0) {
|
||||
prototype = factory->GetPrototype(message_type);
|
||||
GOOGLE_CHECK(prototype != NULL);
|
||||
} else {
|
||||
prototype = &extension->repeated_message_value->Get(0);
|
||||
}
|
||||
result = prototype->New();
|
||||
extension->repeated_message_value->AddAllocated(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input,
|
||||
const MessageLite* containing_type,
|
||||
UnknownFieldSet* unknown_fields) {
|
||||
UnknownFieldSetFieldSkipper skipper(unknown_fields);
|
||||
return ParseField(tag, input, containing_type, &skipper);
|
||||
}
|
||||
|
||||
bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
|
||||
const MessageLite* containing_type,
|
||||
UnknownFieldSet* unknown_fields) {
|
||||
UnknownFieldSetFieldSkipper skipper(unknown_fields);
|
||||
return ParseMessageSet(input, containing_type, &skipper);
|
||||
}
|
||||
|
||||
int ExtensionSet::SpaceUsedExcludingSelf() const {
|
||||
int total_size =
|
||||
extensions_.size() * sizeof(map<int, Extension>::value_type);
|
||||
for (map<int, Extension>::const_iterator iter = extensions_.begin(),
|
||||
end = extensions_.end();
|
||||
iter != end;
|
||||
++iter) {
|
||||
total_size += iter->second.SpaceUsedExcludingSelf();
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
|
||||
int ExtensionSet::Extension::SpaceUsedExcludingSelf() const {
|
||||
int total_size = 0;
|
||||
if (is_repeated) {
|
||||
switch (cpp_type(type)) {
|
||||
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
|
||||
case WireFormatLite::CPPTYPE_##UPPERCASE: \
|
||||
total_size += sizeof(*repeated_##LOWERCASE##_value) + \
|
||||
repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\
|
||||
break
|
||||
|
||||
HANDLE_TYPE( INT32, int32);
|
||||
HANDLE_TYPE( INT64, int64);
|
||||
HANDLE_TYPE( UINT32, uint32);
|
||||
HANDLE_TYPE( UINT64, uint64);
|
||||
HANDLE_TYPE( FLOAT, float);
|
||||
HANDLE_TYPE( DOUBLE, double);
|
||||
HANDLE_TYPE( BOOL, bool);
|
||||
HANDLE_TYPE( ENUM, enum);
|
||||
HANDLE_TYPE( STRING, string);
|
||||
|
||||
case WireFormatLite::CPPTYPE_MESSAGE:
|
||||
// repeated_message_value is actually a RepeatedPtrField<MessageLite>,
|
||||
// but MessageLite has no SpaceUsed(), so we must directly call
|
||||
// RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type
|
||||
// handler.
|
||||
total_size += sizeof(*repeated_message_value) +
|
||||
repeated_message_value->
|
||||
RepeatedPtrFieldBase::SpaceUsedExcludingSelf<
|
||||
GenericTypeHandler<Message> >();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (cpp_type(type)) {
|
||||
case WireFormatLite::CPPTYPE_STRING:
|
||||
total_size += sizeof(*string_value) +
|
||||
StringSpaceUsedExcludingSelf(*string_value);
|
||||
break;
|
||||
case WireFormatLite::CPPTYPE_MESSAGE:
|
||||
total_size += down_cast<Message*>(message_value)->SpaceUsed();
|
||||
break;
|
||||
default:
|
||||
// No extra storage costs for primitive types.
|
||||
break;
|
||||
}
|
||||
}
|
||||
return total_size;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
@ -38,6 +38,7 @@
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/repeated_field.h>
|
||||
#include <google/protobuf/extension_set.h>
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
@ -220,8 +221,36 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
|
||||
const FieldDescriptor* field = descriptor_->field(i);
|
||||
|
||||
if (field->is_repeated()) {
|
||||
total_size += GetRaw<GenericRepeatedField>(message, field)
|
||||
.GenericSpaceUsedExcludingSelf();
|
||||
switch (field->cpp_type()) {
|
||||
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
|
||||
case FieldDescriptor::CPPTYPE_##UPPERCASE : \
|
||||
total_size += GetRaw<RepeatedField<LOWERCASE> >(message, field) \
|
||||
.SpaceUsedExcludingSelf(); \
|
||||
break
|
||||
|
||||
HANDLE_TYPE( INT32, int32);
|
||||
HANDLE_TYPE( INT64, int64);
|
||||
HANDLE_TYPE(UINT32, uint32);
|
||||
HANDLE_TYPE(UINT64, uint64);
|
||||
HANDLE_TYPE(DOUBLE, double);
|
||||
HANDLE_TYPE( FLOAT, float);
|
||||
HANDLE_TYPE( BOOL, bool);
|
||||
HANDLE_TYPE( ENUM, int);
|
||||
#undef HANDLE_TYPE
|
||||
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
total_size += GetRaw<RepeatedPtrField<string> >(message, field)
|
||||
.SpaceUsedExcludingSelf();
|
||||
break;
|
||||
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
// We don't know which subclass of RepeatedPtrFieldBase the type is,
|
||||
// so we use RepeatedPtrFieldBase directly.
|
||||
total_size +=
|
||||
GetRaw<RepeatedPtrFieldBase>(message, field)
|
||||
.SpaceUsedExcludingSelf<GenericTypeHandler<Message> >();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (field->cpp_type()) {
|
||||
case FieldDescriptor::CPPTYPE_INT32 :
|
||||
@ -274,25 +303,59 @@ void GeneratedMessageReflection::Swap(
|
||||
Message* message2) const {
|
||||
if (message1 == message2) return;
|
||||
|
||||
// TODO(kenton): Other Reflection methods should probably check this too.
|
||||
GOOGLE_CHECK_EQ(message1->GetReflection(), this)
|
||||
<< "Tried to swap using reflection object incompatible with message1.";
|
||||
|
||||
<< "First argument to Swap() (of type \""
|
||||
<< message1->GetDescriptor()->full_name()
|
||||
<< "\") is not compatible with this reflection object (which is for type \""
|
||||
<< descriptor_->full_name()
|
||||
<< "\"). Note that the exact same class is required; not just the same "
|
||||
"descriptor.";
|
||||
GOOGLE_CHECK_EQ(message2->GetReflection(), this)
|
||||
<< "Tried to swap using reflection object incompatible with message2.";
|
||||
<< "Second argument to Swap() (of type \""
|
||||
<< message1->GetDescriptor()->full_name()
|
||||
<< "\") is not compatible with this reflection object (which is for type \""
|
||||
<< descriptor_->full_name()
|
||||
<< "\"). Note that the exact same class is required; not just the same "
|
||||
"descriptor.";
|
||||
|
||||
uint32* has_bits1 = MutableHasBits(message1);
|
||||
uint32* has_bits2 = MutableHasBits(message2);
|
||||
int has_bits_size = (descriptor_->field_count() + 31) / 32;
|
||||
|
||||
for (int i = 0; i < has_bits_size; i++) {
|
||||
std::swap(has_bits1[i], has_bits2[i]);
|
||||
swap(has_bits1[i], has_bits2[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||
const FieldDescriptor* field = descriptor_->field(i);
|
||||
if (field->is_repeated()) {
|
||||
MutableRaw<GenericRepeatedField>(message1, field)->GenericSwap(
|
||||
MutableRaw<GenericRepeatedField>(message2, field));
|
||||
switch (field->cpp_type()) {
|
||||
#define SWAP_ARRAYS(CPPTYPE, TYPE) \
|
||||
case FieldDescriptor::CPPTYPE_##CPPTYPE: \
|
||||
MutableRaw<RepeatedField<TYPE> >(message1, field)->Swap( \
|
||||
MutableRaw<RepeatedField<TYPE> >(message2, field)); \
|
||||
break;
|
||||
|
||||
SWAP_ARRAYS(INT32 , int32 );
|
||||
SWAP_ARRAYS(INT64 , int64 );
|
||||
SWAP_ARRAYS(UINT32, uint32);
|
||||
SWAP_ARRAYS(UINT64, uint64);
|
||||
SWAP_ARRAYS(FLOAT , float );
|
||||
SWAP_ARRAYS(DOUBLE, double);
|
||||
SWAP_ARRAYS(BOOL , bool );
|
||||
SWAP_ARRAYS(ENUM , int );
|
||||
#undef SWAP_ARRAYS
|
||||
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
MutableRaw<RepeatedPtrFieldBase>(message1, field)->Swap(
|
||||
MutableRaw<RepeatedPtrFieldBase>(message2, field));
|
||||
break;
|
||||
|
||||
default:
|
||||
GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
|
||||
}
|
||||
} else {
|
||||
switch (field->cpp_type()) {
|
||||
#define SWAP_VALUES(CPPTYPE, TYPE) \
|
||||
@ -300,6 +363,7 @@ void GeneratedMessageReflection::Swap(
|
||||
swap(*MutableRaw<TYPE>(message1, field), \
|
||||
*MutableRaw<TYPE>(message2, field)); \
|
||||
break;
|
||||
|
||||
SWAP_VALUES(INT32 , int32 );
|
||||
SWAP_VALUES(INT64 , int64 );
|
||||
SWAP_VALUES(UINT32, uint32);
|
||||
@ -307,10 +371,15 @@ void GeneratedMessageReflection::Swap(
|
||||
SWAP_VALUES(FLOAT , float );
|
||||
SWAP_VALUES(DOUBLE, double);
|
||||
SWAP_VALUES(BOOL , bool );
|
||||
SWAP_VALUES(ENUM , int32 );
|
||||
SWAP_VALUES(STRING, string*);
|
||||
SWAP_VALUES(ENUM , int );
|
||||
SWAP_VALUES(MESSAGE, Message*);
|
||||
#undef SWAP_PRIMITIVE_VALUES
|
||||
#undef SWAP_VALUES
|
||||
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
swap(*MutableRaw<string*>(message1, field),
|
||||
*MutableRaw<string*>(message2, field));
|
||||
break;
|
||||
|
||||
default:
|
||||
GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
|
||||
}
|
||||
@ -346,7 +415,28 @@ int GeneratedMessageReflection::FieldSize(const Message& message,
|
||||
if (field->is_extension()) {
|
||||
return GetExtensionSet(message).ExtensionSize(field->number());
|
||||
} else {
|
||||
return GetRaw<GenericRepeatedField>(message, field).GenericSize();
|
||||
switch (field->cpp_type()) {
|
||||
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
|
||||
case FieldDescriptor::CPPTYPE_##UPPERCASE : \
|
||||
return GetRaw<RepeatedField<LOWERCASE> >(message, field).size()
|
||||
|
||||
HANDLE_TYPE( INT32, int32);
|
||||
HANDLE_TYPE( INT64, int64);
|
||||
HANDLE_TYPE(UINT32, uint32);
|
||||
HANDLE_TYPE(UINT64, uint64);
|
||||
HANDLE_TYPE(DOUBLE, double);
|
||||
HANDLE_TYPE( FLOAT, float);
|
||||
HANDLE_TYPE( BOOL, bool);
|
||||
HANDLE_TYPE( ENUM, int);
|
||||
#undef HANDLE_TYPE
|
||||
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
return GetRaw<RepeatedPtrFieldBase>(message, field).size();
|
||||
}
|
||||
|
||||
GOOGLE_LOG(FATAL) << "Can't get here.";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,7 +491,35 @@ void GeneratedMessageReflection::ClearField(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MutableRaw<GenericRepeatedField>(message, field)->GenericClear();
|
||||
switch (field->cpp_type()) {
|
||||
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
|
||||
case FieldDescriptor::CPPTYPE_##UPPERCASE : \
|
||||
MutableRaw<RepeatedField<LOWERCASE> >(message, field)->Clear(); \
|
||||
break
|
||||
|
||||
HANDLE_TYPE( INT32, int32);
|
||||
HANDLE_TYPE( INT64, int64);
|
||||
HANDLE_TYPE(UINT32, uint32);
|
||||
HANDLE_TYPE(UINT64, uint64);
|
||||
HANDLE_TYPE(DOUBLE, double);
|
||||
HANDLE_TYPE( FLOAT, float);
|
||||
HANDLE_TYPE( BOOL, bool);
|
||||
HANDLE_TYPE( ENUM, int);
|
||||
#undef HANDLE_TYPE
|
||||
|
||||
case FieldDescriptor::CPPTYPE_STRING: {
|
||||
MutableRaw<RepeatedPtrField<string> >(message, field)->Clear();
|
||||
break;
|
||||
}
|
||||
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE: {
|
||||
// We don't know which subclass of RepeatedPtrFieldBase the type is,
|
||||
// so we use RepeatedPtrFieldBase directly.
|
||||
MutableRaw<RepeatedPtrFieldBase>(message, field)
|
||||
->Clear<GenericTypeHandler<Message> >();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -414,7 +532,31 @@ void GeneratedMessageReflection::RemoveLast(
|
||||
if (field->is_extension()) {
|
||||
MutableExtensionSet(message)->RemoveLast(field->number());
|
||||
} else {
|
||||
MutableRaw<GenericRepeatedField>(message, field)->GenericRemoveLast();
|
||||
switch (field->cpp_type()) {
|
||||
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
|
||||
case FieldDescriptor::CPPTYPE_##UPPERCASE : \
|
||||
MutableRaw<RepeatedField<LOWERCASE> >(message, field)->RemoveLast(); \
|
||||
break
|
||||
|
||||
HANDLE_TYPE( INT32, int32);
|
||||
HANDLE_TYPE( INT64, int64);
|
||||
HANDLE_TYPE(UINT32, uint32);
|
||||
HANDLE_TYPE(UINT64, uint64);
|
||||
HANDLE_TYPE(DOUBLE, double);
|
||||
HANDLE_TYPE( FLOAT, float);
|
||||
HANDLE_TYPE( BOOL, bool);
|
||||
HANDLE_TYPE( ENUM, int);
|
||||
#undef HANDLE_TYPE
|
||||
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
MutableRaw<RepeatedPtrField<string> >(message, field)->RemoveLast();
|
||||
break;
|
||||
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
MutableRaw<RepeatedPtrFieldBase>(message, field)
|
||||
->RemoveLast<GenericTypeHandler<Message> >();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,11 +569,31 @@ void GeneratedMessageReflection::SwapElements(
|
||||
USAGE_CHECK_REPEATED(Swap);
|
||||
|
||||
if (field->is_extension()) {
|
||||
MutableExtensionSet(message)->SwapElements(
|
||||
field->number(), index1, index2);
|
||||
MutableExtensionSet(message)->SwapElements(field->number(), index1, index2);
|
||||
} else {
|
||||
MutableRaw<GenericRepeatedField>(message, field)->GenericSwapElements(
|
||||
index1, index2);
|
||||
switch (field->cpp_type()) {
|
||||
#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \
|
||||
case FieldDescriptor::CPPTYPE_##UPPERCASE : \
|
||||
MutableRaw<RepeatedField<LOWERCASE> >(message, field) \
|
||||
->SwapElements(index1, index2); \
|
||||
break
|
||||
|
||||
HANDLE_TYPE( INT32, int32);
|
||||
HANDLE_TYPE( INT64, int64);
|
||||
HANDLE_TYPE(UINT32, uint32);
|
||||
HANDLE_TYPE(UINT64, uint64);
|
||||
HANDLE_TYPE(DOUBLE, double);
|
||||
HANDLE_TYPE( FLOAT, float);
|
||||
HANDLE_TYPE( BOOL, bool);
|
||||
HANDLE_TYPE( ENUM, int);
|
||||
#undef HANDLE_TYPE
|
||||
|
||||
case FieldDescriptor::CPPTYPE_STRING:
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE:
|
||||
MutableRaw<RepeatedPtrFieldBase>(message, field)
|
||||
->SwapElements(index1, index2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -456,7 +618,7 @@ void GeneratedMessageReflection::ListFields(
|
||||
for (int i = 0; i < descriptor_->field_count(); i++) {
|
||||
const FieldDescriptor* field = descriptor_->field(i);
|
||||
if (field->is_repeated()) {
|
||||
if (GetRaw<GenericRepeatedField>(message, field).GenericSize() > 0) {
|
||||
if (FieldSize(message, field) > 0) {
|
||||
output->push_back(field);
|
||||
}
|
||||
} else {
|
||||
@ -597,7 +759,7 @@ string GeneratedMessageReflection::GetRepeatedString(
|
||||
if (field->is_extension()) {
|
||||
return GetExtensionSet(message).GetRepeatedString(field->number(), index);
|
||||
} else {
|
||||
return GetRepeatedField<string>(message, field, index);
|
||||
return GetRepeatedPtrField<string>(message, field, index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -608,7 +770,7 @@ const string& GeneratedMessageReflection::GetRepeatedStringReference(
|
||||
if (field->is_extension()) {
|
||||
return GetExtensionSet(message).GetRepeatedString(field->number(), index);
|
||||
} else {
|
||||
return GetRepeatedField<string>(message, field, index);
|
||||
return GetRepeatedPtrField<string>(message, field, index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -621,7 +783,7 @@ void GeneratedMessageReflection::SetRepeatedString(
|
||||
MutableExtensionSet(message)->SetRepeatedString(
|
||||
field->number(), index, value);
|
||||
} else {
|
||||
SetRepeatedField<string>(message, field, index, value);
|
||||
*MutableRepeatedField<string>(message, field, index) = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -634,7 +796,7 @@ void GeneratedMessageReflection::AddString(
|
||||
MutableExtensionSet(message)->AddString(field->number(),
|
||||
field->type(), value);
|
||||
} else {
|
||||
AddField<string>(message, field, value);
|
||||
*AddField<string>(message, field) = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -725,9 +887,10 @@ const Message& GeneratedMessageReflection::GetMessage(
|
||||
USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
|
||||
|
||||
if (field->is_extension()) {
|
||||
return GetExtensionSet(message).GetMessage(field->number(),
|
||||
field->message_type(),
|
||||
message_factory_);
|
||||
return static_cast<const Message&>(
|
||||
GetExtensionSet(message).GetMessage(field->number(),
|
||||
field->message_type(),
|
||||
message_factory_));
|
||||
} else {
|
||||
const Message* result = GetRaw<const Message*>(message, field);
|
||||
if (result == NULL) {
|
||||
@ -742,10 +905,11 @@ Message* GeneratedMessageReflection::MutableMessage(
|
||||
USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
|
||||
|
||||
if (field->is_extension()) {
|
||||
return MutableExtensionSet(message)->MutableMessage(field->number(),
|
||||
field->type(),
|
||||
field->message_type(),
|
||||
message_factory_);
|
||||
return static_cast<Message*>(
|
||||
MutableExtensionSet(message)->MutableMessage(field->number(),
|
||||
field->type(),
|
||||
field->message_type(),
|
||||
message_factory_));
|
||||
} else {
|
||||
Message** result = MutableField<Message*>(message, field);
|
||||
if (*result == NULL) {
|
||||
@ -761,9 +925,11 @@ const Message& GeneratedMessageReflection::GetRepeatedMessage(
|
||||
USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
|
||||
|
||||
if (field->is_extension()) {
|
||||
return GetExtensionSet(message).GetRepeatedMessage(field->number(), index);
|
||||
return static_cast<const Message&>(
|
||||
GetExtensionSet(message).GetRepeatedMessage(field->number(), index));
|
||||
} else {
|
||||
return GetRepeatedField<Message>(message, field, index);
|
||||
return GetRaw<RepeatedPtrFieldBase>(message, field)
|
||||
.Get<GenericTypeHandler<Message> >(index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -772,10 +938,12 @@ Message* GeneratedMessageReflection::MutableRepeatedMessage(
|
||||
USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE);
|
||||
|
||||
if (field->is_extension()) {
|
||||
return MutableExtensionSet(message)->MutableRepeatedMessage(
|
||||
field->number(), index);
|
||||
return static_cast<Message*>(
|
||||
MutableExtensionSet(message)->MutableRepeatedMessage(
|
||||
field->number(), index));
|
||||
} else {
|
||||
return MutableRepeatedField<Message>(message, field, index);
|
||||
return MutableRaw<RepeatedPtrFieldBase>(message, field)
|
||||
->Mutable<GenericTypeHandler<Message> >(index);
|
||||
}
|
||||
}
|
||||
|
||||
@ -784,12 +952,29 @@ Message* GeneratedMessageReflection::AddMessage(
|
||||
USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
|
||||
|
||||
if (field->is_extension()) {
|
||||
return MutableExtensionSet(message)->AddMessage(field->number(),
|
||||
field->type(),
|
||||
field->message_type(),
|
||||
message_factory_);
|
||||
return static_cast<Message*>(
|
||||
MutableExtensionSet(message)->AddMessage(field->number(),
|
||||
field->type(),
|
||||
field->message_type(),
|
||||
message_factory_));
|
||||
} else {
|
||||
return AddField<Message>(message, field);
|
||||
// We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
|
||||
// know how to allocate one.
|
||||
RepeatedPtrFieldBase* repeated =
|
||||
MutableRaw<RepeatedPtrFieldBase>(message, field);
|
||||
Message* result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
|
||||
if (result == NULL) {
|
||||
// We must allocate a new object.
|
||||
const Message* prototype;
|
||||
if (repeated->size() == 0) {
|
||||
prototype = message_factory_->GetPrototype(field->message_type());
|
||||
} else {
|
||||
prototype = &repeated->Get<GenericTypeHandler<Message> >(0);
|
||||
}
|
||||
result = prototype->New();
|
||||
repeated->AddAllocated<GenericTypeHandler<Message> >(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -925,46 +1110,46 @@ inline Type* GeneratedMessageReflection::MutableField(
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline const Type& GeneratedMessageReflection::GetRepeatedField(
|
||||
inline Type GeneratedMessageReflection::GetRepeatedField(
|
||||
const Message& message, const FieldDescriptor* field, int index) const {
|
||||
return *reinterpret_cast<const Type*>(
|
||||
GetRaw<GenericRepeatedField>(message, field).GenericGet(index));
|
||||
return GetRaw<RepeatedField<Type> >(message, field).Get(index);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline const Type& GeneratedMessageReflection::GetRepeatedPtrField(
|
||||
const Message& message, const FieldDescriptor* field, int index) const {
|
||||
return GetRaw<RepeatedPtrField<Type> >(message, field).Get(index);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline void GeneratedMessageReflection::SetRepeatedField(
|
||||
Message* message, const FieldDescriptor* field,
|
||||
int index, const Type& value) const {
|
||||
GenericRepeatedField* repeated =
|
||||
MutableRaw<GenericRepeatedField>(message, field);
|
||||
*reinterpret_cast<Type*>(repeated->GenericMutable(index)) = value;
|
||||
int index, Type value) const {
|
||||
MutableRaw<RepeatedField<Type> >(message, field)->Set(index, value);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type* GeneratedMessageReflection::MutableRepeatedField(
|
||||
Message* message, const FieldDescriptor* field, int index) const {
|
||||
GenericRepeatedField* repeated =
|
||||
MutableRaw<GenericRepeatedField>(message, field);
|
||||
return reinterpret_cast<Type*>(repeated->GenericMutable(index));
|
||||
RepeatedPtrField<Type>* repeated =
|
||||
MutableRaw<RepeatedPtrField<Type> >(message, field);
|
||||
return repeated->Mutable(index);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline void GeneratedMessageReflection::AddField(
|
||||
Message* message, const FieldDescriptor* field, const Type& value) const {
|
||||
GenericRepeatedField* repeated =
|
||||
MutableRaw<GenericRepeatedField>(message, field);
|
||||
*reinterpret_cast<Type*>(repeated->GenericAdd()) = value;
|
||||
Message* message, const FieldDescriptor* field, Type value) const {
|
||||
MutableRaw<RepeatedField<Type> >(message, field)->Add(value);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
inline Type* GeneratedMessageReflection::AddField(
|
||||
Message* message, const FieldDescriptor* field) const {
|
||||
GenericRepeatedField* repeated =
|
||||
MutableRaw<GenericRepeatedField>(message, field);
|
||||
return reinterpret_cast<Type*>(repeated->GenericAdd());
|
||||
RepeatedPtrField<Type>* repeated =
|
||||
MutableRaw<RepeatedPtrField<Type> >(message, field);
|
||||
return repeated->Add();
|
||||
}
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
@ -142,7 +142,7 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
|
||||
void ClearField(Message* message, const FieldDescriptor* field) const;
|
||||
void RemoveLast(Message* message, const FieldDescriptor* field) const;
|
||||
void Swap(Message* message1, Message* message2) const;
|
||||
void SwapElements(Message* message, const FieldDescriptor* field,
|
||||
void SwapElements(Message* message, const FieldDescriptor* field,
|
||||
int index1, int index2) const;
|
||||
void ListFields(const Message& message,
|
||||
vector<const FieldDescriptor*>* output) const;
|
||||
@ -314,20 +314,24 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
|
||||
inline Type* MutableField(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
template <typename Type>
|
||||
inline const Type& GetRepeatedField(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
inline Type GetRepeatedField(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
template <typename Type>
|
||||
inline const Type& GetRepeatedPtrField(const Message& message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
template <typename Type>
|
||||
inline void SetRepeatedField(Message* message,
|
||||
const FieldDescriptor* field, int index,
|
||||
const Type& value) const;
|
||||
Type value) const;
|
||||
template <typename Type>
|
||||
inline Type* MutableRepeatedField(Message* message,
|
||||
const FieldDescriptor* field,
|
||||
int index) const;
|
||||
template <typename Type>
|
||||
inline void AddField(Message* message,
|
||||
const FieldDescriptor* field, const Type& value) const;
|
||||
const FieldDescriptor* field, Type value) const;
|
||||
template <typename Type>
|
||||
inline Type* AddField(Message* message,
|
||||
const FieldDescriptor* field) const;
|
||||
@ -388,11 +392,6 @@ inline To dynamic_cast_if_available(From from) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Compute the space used by a string, not including sizeof(string) itself.
|
||||
// This is slightly complicated because small strings store their data within
|
||||
// the string object but large strings do not.
|
||||
LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str);
|
||||
|
||||
// Helper for EnumType_Parse functions: try to parse the string 'name' as an
|
||||
// enum name of the given type, returning true and filling in value on success,
|
||||
// or returning false and leaving value unchanged on failure.
|
||||
@ -415,7 +414,6 @@ bool ParseNamedEnum(const EnumDescriptor* descriptor,
|
||||
// descriptor.h.
|
||||
LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value);
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
|
44
src/google/protobuf/generated_message_util.cc
Normal file
44
src/google/protobuf/generated_message_util.cc
Normal file
@ -0,0 +1,44 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
|
||||
#include <google/protobuf/generated_message_util.h>
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
65
src/google/protobuf/generated_message_util.h
Normal file
65
src/google/protobuf/generated_message_util.h
Normal file
@ -0,0 +1,65 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains miscellaneous helper code used by generated code --
|
||||
// including lite types -- but which should not be used directly by users.
|
||||
|
||||
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
|
||||
namespace google {
|
||||
namespace protobuf {
|
||||
namespace internal {
|
||||
|
||||
// Annotation for the compiler to emit a deprecation message if a field marked
|
||||
// with option 'deprecated=true' is used in the code.
|
||||
//
|
||||
// For internal use in the pb.cc files, deprecation warnings are suppressed
|
||||
// there.
|
||||
#undef DEPRECATED_PROTOBUF_FIELD
|
||||
#if !defined(INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION)
|
||||
# define DEPRECATED_PROTOBUF_FIELD GOOGLE_ATTRIBUTE_DEPRECATED
|
||||
#else
|
||||
# define DEPRECATED_PROTOBUF_FIELD
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace protobuf
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
|
@ -80,18 +80,49 @@ CodedInputStream::CodedInputStream(ZeroCopyInputStream* input)
|
||||
total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
|
||||
recursion_depth_(0),
|
||||
recursion_limit_(kDefaultRecursionLimit) {
|
||||
// Eagerly Refresh() so buffer space is immediately available.
|
||||
Refresh();
|
||||
}
|
||||
|
||||
CodedInputStream::CodedInputStream(const uint8* buffer, int size)
|
||||
: input_(NULL),
|
||||
buffer_(buffer),
|
||||
buffer_size_(size),
|
||||
total_bytes_read_(size),
|
||||
overflow_bytes_(0),
|
||||
last_tag_(0),
|
||||
legitimate_message_end_(false),
|
||||
aliasing_enabled_(false),
|
||||
current_limit_(size),
|
||||
buffer_size_after_limit_(0),
|
||||
total_bytes_limit_(kDefaultTotalBytesLimit),
|
||||
total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
|
||||
recursion_depth_(0),
|
||||
recursion_limit_(kDefaultRecursionLimit) {
|
||||
// Note that setting current_limit_ == size is important to prevent some
|
||||
// code paths from trying to access input_ and segfaulting.
|
||||
}
|
||||
|
||||
CodedInputStream::~CodedInputStream() {
|
||||
int backup_bytes = buffer_size_ + buffer_size_after_limit_ + overflow_bytes_;
|
||||
if (backup_bytes > 0) {
|
||||
// We still have bytes left over from the last buffer. Back up over
|
||||
// them.
|
||||
input_->BackUp(backup_bytes);
|
||||
if (input_ != NULL) {
|
||||
BackUpInputToCurrentPosition();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CodedInputStream::BackUpInputToCurrentPosition() {
|
||||
int backup_bytes = buffer_size_ + buffer_size_after_limit_ + overflow_bytes_;
|
||||
if (backup_bytes > 0) {
|
||||
input_->BackUp(backup_bytes);
|
||||
|
||||
// total_bytes_read_ doesn't include overflow_bytes_.
|
||||
total_bytes_read_ -= buffer_size_ + buffer_size_after_limit_;
|
||||
buffer_size_ = 0;
|
||||
buffer_size_after_limit_ = 0;
|
||||
overflow_bytes_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void CodedInputStream::RecomputeBufferLimits() {
|
||||
buffer_size_ += buffer_size_after_limit_;
|
||||
int closest_limit = min(current_limit_, total_bytes_limit_);
|
||||
@ -193,8 +224,10 @@ bool CodedInputStream::Skip(int count) {
|
||||
int bytes_until_limit = closest_limit - total_bytes_read_;
|
||||
if (bytes_until_limit < count) {
|
||||
// We hit the limit. Skip up to it then fail.
|
||||
total_bytes_read_ = closest_limit;
|
||||
input_->Skip(bytes_until_limit);
|
||||
if (bytes_until_limit > 0) {
|
||||
total_bytes_read_ = closest_limit;
|
||||
input_->Skip(bytes_until_limit);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -216,6 +249,7 @@ bool CodedInputStream::ReadRaw(void* buffer, int size) {
|
||||
memcpy(buffer, buffer_, buffer_size_);
|
||||
buffer = reinterpret_cast<uint8*>(buffer) + buffer_size_;
|
||||
size -= buffer_size_;
|
||||
Advance(buffer_size_);
|
||||
if (!Refresh()) return false;
|
||||
}
|
||||
|
||||
@ -247,6 +281,7 @@ bool CodedInputStream::ReadString(string* buffer, int size) {
|
||||
buffer->append(reinterpret_cast<const char*>(buffer_), buffer_size_);
|
||||
}
|
||||
size -= buffer_size_;
|
||||
Advance(buffer_size_);
|
||||
if (!Refresh()) return false;
|
||||
}
|
||||
|
||||
@ -441,11 +476,11 @@ bool CodedInputStream::ReadVarint64(uint64* value) {
|
||||
}
|
||||
|
||||
bool CodedInputStream::Refresh() {
|
||||
if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0) {
|
||||
// We've hit a limit. Stop.
|
||||
buffer_ += buffer_size_;
|
||||
buffer_size_ = 0;
|
||||
GOOGLE_DCHECK_EQ(buffer_size_, 0);
|
||||
|
||||
if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 ||
|
||||
total_bytes_read_ == current_limit_) {
|
||||
// We've hit a limit. Stop.
|
||||
int current_position = total_bytes_read_ - buffer_size_after_limit_;
|
||||
|
||||
if (current_position >= total_bytes_limit_ &&
|
||||
@ -570,10 +605,7 @@ void CodedOutputStream::WriteLittleEndian32(uint32 value) {
|
||||
bool use_fast = buffer_size_ >= sizeof(value);
|
||||
uint8* ptr = use_fast ? buffer_ : bytes;
|
||||
|
||||
ptr[0] = static_cast<uint8>(value );
|
||||
ptr[1] = static_cast<uint8>(value >> 8);
|
||||
ptr[2] = static_cast<uint8>(value >> 16);
|
||||
ptr[3] = static_cast<uint8>(value >> 24);
|
||||
WriteLittleEndian32ToArray(value, ptr);
|
||||
|
||||
if (use_fast) {
|
||||
Advance(sizeof(value));
|
||||
@ -582,32 +614,13 @@ void CodedOutputStream::WriteLittleEndian32(uint32 value) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8* CodedOutputStream::WriteLittleEndian32ToArray(
|
||||
uint32 value, uint8* target) {
|
||||
target[0] = static_cast<uint8>(value );
|
||||
target[1] = static_cast<uint8>(value >> 8);
|
||||
target[2] = static_cast<uint8>(value >> 16);
|
||||
target[3] = static_cast<uint8>(value >> 24);
|
||||
return target + sizeof(value);
|
||||
}
|
||||
|
||||
void CodedOutputStream::WriteLittleEndian64(uint64 value) {
|
||||
uint8 bytes[sizeof(value)];
|
||||
|
||||
uint32 part0 = static_cast<uint32>(value);
|
||||
uint32 part1 = static_cast<uint32>(value >> 32);
|
||||
|
||||
bool use_fast = buffer_size_ >= sizeof(value);
|
||||
uint8* ptr = use_fast ? buffer_ : bytes;
|
||||
|
||||
ptr[0] = static_cast<uint8>(part0 );
|
||||
ptr[1] = static_cast<uint8>(part0 >> 8);
|
||||
ptr[2] = static_cast<uint8>(part0 >> 16);
|
||||
ptr[3] = static_cast<uint8>(part0 >> 24);
|
||||
ptr[4] = static_cast<uint8>(part1 );
|
||||
ptr[5] = static_cast<uint8>(part1 >> 8);
|
||||
ptr[6] = static_cast<uint8>(part1 >> 16);
|
||||
ptr[7] = static_cast<uint8>(part1 >> 24);
|
||||
WriteLittleEndian64ToArray(value, ptr);
|
||||
|
||||
if (use_fast) {
|
||||
Advance(sizeof(value));
|
||||
@ -616,23 +629,6 @@ void CodedOutputStream::WriteLittleEndian64(uint64 value) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8* CodedOutputStream::WriteLittleEndian64ToArray(
|
||||
uint64 value, uint8* target) {
|
||||
uint32 part0 = static_cast<uint32>(value);
|
||||
uint32 part1 = static_cast<uint32>(value >> 32);
|
||||
|
||||
target[0] = static_cast<uint8>(part0 );
|
||||
target[1] = static_cast<uint8>(part0 >> 8);
|
||||
target[2] = static_cast<uint8>(part0 >> 16);
|
||||
target[3] = static_cast<uint8>(part0 >> 24);
|
||||
target[4] = static_cast<uint8>(part1 );
|
||||
target[5] = static_cast<uint8>(part1 >> 8);
|
||||
target[6] = static_cast<uint8>(part1 >> 16);
|
||||
target[7] = static_cast<uint8>(part1 >> 24);
|
||||
|
||||
return target + sizeof(value);
|
||||
}
|
||||
|
||||
inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline(
|
||||
uint32 value, uint8* target) {
|
||||
target[0] = static_cast<uint8>(value | 0x80);
|
||||
|
@ -110,6 +110,9 @@
|
||||
#define GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
|
||||
|
||||
#include <string>
|
||||
#ifndef _MSC_VER
|
||||
#include <sys/param.h>
|
||||
#endif // !_MSC_VER
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
@ -137,6 +140,11 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
|
||||
// Create a CodedInputStream that reads from the given ZeroCopyInputStream.
|
||||
explicit CodedInputStream(ZeroCopyInputStream* input);
|
||||
|
||||
// Create a CodedInputStream that reads from the given flat array. This is
|
||||
// faster than using an ArrayInputStream. PushLimit(size) is implied by
|
||||
// this constructor.
|
||||
explicit CodedInputStream(const uint8* buffer, int size);
|
||||
|
||||
// Destroy the CodedInputStream and position the underlying
|
||||
// ZeroCopyInputStream at the first unread byte. If an error occurred while
|
||||
// reading (causing a method to return false), then the exact position of
|
||||
@ -360,6 +368,9 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
|
||||
// Advance the buffer by a given number of bytes.
|
||||
void Advance(int amount);
|
||||
|
||||
// Back up input_ to the current buffer position.
|
||||
void BackUpInputToCurrentPosition();
|
||||
|
||||
// Recomputes the value of buffer_size_after_limit_. Must be called after
|
||||
// current_limit_ or total_bytes_limit_ changes.
|
||||
void RecomputeBufferLimits();
|
||||
@ -664,6 +675,41 @@ inline uint8* CodedOutputStream::WriteVarint32SignExtendedToArray(
|
||||
}
|
||||
}
|
||||
|
||||
inline uint8* CodedOutputStream::WriteLittleEndian32ToArray(uint32 value,
|
||||
uint8* target) {
|
||||
#if !defined(PROTOBUF_TEST_NOT_LITTLE_ENDIAN) && \
|
||||
defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
memcpy(target, &value, sizeof(value));
|
||||
#else
|
||||
target[0] = static_cast<uint8>(value );
|
||||
target[1] = static_cast<uint8>(value >> 8);
|
||||
target[2] = static_cast<uint8>(value >> 16);
|
||||
target[3] = static_cast<uint8>(value >> 24);
|
||||
#endif
|
||||
return target + sizeof(value);
|
||||
}
|
||||
|
||||
inline uint8* CodedOutputStream::WriteLittleEndian64ToArray(uint64 value,
|
||||
uint8* target) {
|
||||
#if !defined(PROTOBUF_TEST_NOT_LITTLE_ENDIAN) && \
|
||||
defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
memcpy(target, &value, sizeof(value));
|
||||
#else
|
||||
uint32 part0 = static_cast<uint32>(value);
|
||||
uint32 part1 = static_cast<uint32>(value >> 32);
|
||||
|
||||
target[0] = static_cast<uint8>(part0 );
|
||||
target[1] = static_cast<uint8>(part0 >> 8);
|
||||
target[2] = static_cast<uint8>(part0 >> 16);
|
||||
target[3] = static_cast<uint8>(part0 >> 24);
|
||||
target[4] = static_cast<uint8>(part1 );
|
||||
target[5] = static_cast<uint8>(part1 >> 8);
|
||||
target[6] = static_cast<uint8>(part1 >> 16);
|
||||
target[7] = static_cast<uint8>(part1 >> 24);
|
||||
#endif
|
||||
return target + sizeof(value);
|
||||
}
|
||||
|
||||
inline void CodedOutputStream::WriteTag(uint32 value) {
|
||||
WriteVarint32(value);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2009 Google Inc. All rights reserved.
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@ -29,8 +29,6 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: brianolson@google.com (Brian Olson)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains the implementation of classes GzipInputStream and
|
||||
// GzipOutputStream.
|
||||
@ -39,6 +37,7 @@
|
||||
|
||||
#if HAVE_ZLIB
|
||||
#include <google/protobuf/io/gzip_stream.h>
|
||||
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
|
||||
namespace google {
|
||||
@ -291,6 +290,6 @@ bool GzipOutputStream::Close() {
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
#endif // HAVE_ZLIB
|
||||
} // namespace google
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2009 Google Inc. All rights reserved.
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
@ -29,8 +29,6 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Author: brianolson@google.com (Brian Olson)
|
||||
// Based on original Protocol Buffers design by
|
||||
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||
//
|
||||
// This file contains the definition for classes GzipInputStream and
|
||||
// GzipOutputStream.
|
||||
@ -173,6 +171,6 @@ class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream {
|
||||
|
||||
} // namespace io
|
||||
} // namespace protobuf
|
||||
} // namespace google
|
||||
|
||||
} // namespace google
|
||||
#endif // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
|
||||
|
@ -571,7 +571,7 @@ bool Tokenizer::ParseInteger(const string& text, uint64 max_value,
|
||||
const char* ptr = text.c_str();
|
||||
int base = 10;
|
||||
if (ptr[0] == '0') {
|
||||
if (ptr[1] == 'x') {
|
||||
if (ptr[1] == 'x' || ptr[1] == 'X') {
|
||||
// This is hex.
|
||||
base = 16;
|
||||
ptr += 2;
|
||||
|
@ -487,6 +487,7 @@ TEST_F(TokenizerTest, ParseInteger) {
|
||||
EXPECT_EQ(0xabcdef12u, ParseInteger("0xABCDEF12"));
|
||||
EXPECT_EQ(kuint64max, ParseInteger("0xFFFFFFFFFFFFFFFF"));
|
||||
EXPECT_EQ(01234567, ParseInteger("01234567"));
|
||||
EXPECT_EQ(0X123, ParseInteger("0X123"));
|
||||
|
||||
// Test invalid integers that may still be tokenized as integers.
|
||||
EXPECT_EQ(0, ParseInteger("0x"));
|
||||
|
@ -60,7 +60,6 @@ namespace io {
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
// EINTR sucks.
|
||||
int close_no_eintr(int fd) {
|
||||
int result;
|
||||
@ -70,352 +69,8 @@ int close_no_eintr(int fd) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Default block size for Copying{In,Out}putStreamAdaptor.
|
||||
static const int kDefaultBlockSize = 8192;
|
||||
|
||||
} // namespace
|
||||
|
||||
// ===================================================================
|
||||
|
||||
ArrayInputStream::ArrayInputStream(const void* data, int size,
|
||||
int block_size)
|
||||
: data_(reinterpret_cast<const uint8*>(data)),
|
||||
size_(size),
|
||||
block_size_(block_size > 0 ? block_size : size),
|
||||
position_(0),
|
||||
last_returned_size_(0) {
|
||||
}
|
||||
|
||||
ArrayInputStream::~ArrayInputStream() {
|
||||
}
|
||||
|
||||
bool ArrayInputStream::Next(const void** data, int* size) {
|
||||
if (position_ < size_) {
|
||||
last_returned_size_ = min(block_size_, size_ - position_);
|
||||
*data = data_ + position_;
|
||||
*size = last_returned_size_;
|
||||
position_ += last_returned_size_;
|
||||
return true;
|
||||
} else {
|
||||
// We're at the end of the array.
|
||||
last_returned_size_ = 0; // Don't let caller back up.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayInputStream::BackUp(int count) {
|
||||
GOOGLE_CHECK_GT(last_returned_size_, 0)
|
||||
<< "BackUp() can only be called after a successful Next().";
|
||||
GOOGLE_CHECK_LE(count, last_returned_size_);
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
position_ -= count;
|
||||
last_returned_size_ = 0; // Don't let caller back up further.
|
||||
}
|
||||
|
||||
bool ArrayInputStream::Skip(int count) {
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
last_returned_size_ = 0; // Don't let caller back up.
|
||||
if (count > size_ - position_) {
|
||||
position_ = size_;
|
||||
return false;
|
||||
} else {
|
||||
position_ += count;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int64 ArrayInputStream::ByteCount() const {
|
||||
return position_;
|
||||
}
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size)
|
||||
: data_(reinterpret_cast<uint8*>(data)),
|
||||
size_(size),
|
||||
block_size_(block_size > 0 ? block_size : size),
|
||||
position_(0),
|
||||
last_returned_size_(0) {
|
||||
}
|
||||
|
||||
ArrayOutputStream::~ArrayOutputStream() {
|
||||
}
|
||||
|
||||
bool ArrayOutputStream::Next(void** data, int* size) {
|
||||
if (position_ < size_) {
|
||||
last_returned_size_ = min(block_size_, size_ - position_);
|
||||
*data = data_ + position_;
|
||||
*size = last_returned_size_;
|
||||
position_ += last_returned_size_;
|
||||
return true;
|
||||
} else {
|
||||
// We're at the end of the array.
|
||||
last_returned_size_ = 0; // Don't let caller back up.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ArrayOutputStream::BackUp(int count) {
|
||||
GOOGLE_CHECK_GT(last_returned_size_, 0)
|
||||
<< "BackUp() can only be called after a successful Next().";
|
||||
GOOGLE_CHECK_LE(count, last_returned_size_);
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
position_ -= count;
|
||||
last_returned_size_ = 0; // Don't let caller back up further.
|
||||
}
|
||||
|
||||
int64 ArrayOutputStream::ByteCount() const {
|
||||
return position_;
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
StringOutputStream::StringOutputStream(string* target)
|
||||
: target_(target) {
|
||||
}
|
||||
|
||||
StringOutputStream::~StringOutputStream() {
|
||||
}
|
||||
|
||||
bool StringOutputStream::Next(void** data, int* size) {
|
||||
int old_size = target_->size();
|
||||
|
||||
// Grow the string.
|
||||
if (old_size < target_->capacity()) {
|
||||
// Resize the string to match its capacity, since we can get away
|
||||
// without a memory allocation this way.
|
||||
STLStringResizeUninitialized(target_, target_->capacity());
|
||||
} else {
|
||||
// Size has reached capacity, so double the size. Also make sure
|
||||
// that the new size is at least kMinimumSize.
|
||||
STLStringResizeUninitialized(
|
||||
target_,
|
||||
max(old_size * 2,
|
||||
kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness.
|
||||
}
|
||||
|
||||
*data = string_as_array(target_) + old_size;
|
||||
*size = target_->size() - old_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
void StringOutputStream::BackUp(int count) {
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
GOOGLE_CHECK_LE(count, target_->size());
|
||||
target_->resize(target_->size() - count);
|
||||
}
|
||||
|
||||
int64 StringOutputStream::ByteCount() const {
|
||||
return target_->size();
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
|
||||
// ===================================================================
|
||||
|
||||
CopyingInputStream::~CopyingInputStream() {}
|
||||
|
||||
int CopyingInputStream::Skip(int count) {
|
||||
char junk[4096];
|
||||
int skipped = 0;
|
||||
while (skipped < count) {
|
||||
int bytes = Read(junk, min(count - skipped,
|
||||
implicit_cast<int>(sizeof(junk))));
|
||||
if (bytes <= 0) {
|
||||
// EOF or read error.
|
||||
return skipped;
|
||||
}
|
||||
skipped += bytes;
|
||||
}
|
||||
return skipped;
|
||||
}
|
||||
|
||||
CopyingInputStreamAdaptor::CopyingInputStreamAdaptor(
|
||||
CopyingInputStream* copying_stream, int block_size)
|
||||
: copying_stream_(copying_stream),
|
||||
owns_copying_stream_(false),
|
||||
failed_(false),
|
||||
position_(0),
|
||||
buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
|
||||
buffer_used_(0),
|
||||
backup_bytes_(0) {
|
||||
}
|
||||
|
||||
CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() {
|
||||
if (owns_copying_stream_) {
|
||||
delete copying_stream_;
|
||||
}
|
||||
}
|
||||
|
||||
bool CopyingInputStreamAdaptor::Next(const void** data, int* size) {
|
||||
if (failed_) {
|
||||
// Already failed on a previous read.
|
||||
return false;
|
||||
}
|
||||
|
||||
AllocateBufferIfNeeded();
|
||||
|
||||
if (backup_bytes_ > 0) {
|
||||
// We have data left over from a previous BackUp(), so just return that.
|
||||
*data = buffer_.get() + buffer_used_ - backup_bytes_;
|
||||
*size = backup_bytes_;
|
||||
backup_bytes_ = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read new data into the buffer.
|
||||
buffer_used_ = copying_stream_->Read(buffer_.get(), buffer_size_);
|
||||
if (buffer_used_ <= 0) {
|
||||
// EOF or read error. We don't need the buffer anymore.
|
||||
if (buffer_used_ < 0) {
|
||||
// Read error (not EOF).
|
||||
failed_ = true;
|
||||
}
|
||||
FreeBuffer();
|
||||
return false;
|
||||
}
|
||||
position_ += buffer_used_;
|
||||
|
||||
*size = buffer_used_;
|
||||
*data = buffer_.get();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CopyingInputStreamAdaptor::BackUp(int count) {
|
||||
GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL)
|
||||
<< " BackUp() can only be called after Next().";
|
||||
GOOGLE_CHECK_LE(count, buffer_used_)
|
||||
<< " Can't back up over more bytes than were returned by the last call"
|
||||
" to Next().";
|
||||
GOOGLE_CHECK_GE(count, 0)
|
||||
<< " Parameter to BackUp() can't be negative.";
|
||||
|
||||
backup_bytes_ = count;
|
||||
}
|
||||
|
||||
bool CopyingInputStreamAdaptor::Skip(int count) {
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
|
||||
if (failed_) {
|
||||
// Already failed on a previous read.
|
||||
return false;
|
||||
}
|
||||
|
||||
// First skip any bytes left over from a previous BackUp().
|
||||
if (backup_bytes_ >= count) {
|
||||
// We have more data left over than we're trying to skip. Just chop it.
|
||||
backup_bytes_ -= count;
|
||||
return true;
|
||||
}
|
||||
|
||||
count -= backup_bytes_;
|
||||
backup_bytes_ = 0;
|
||||
|
||||
int skipped = copying_stream_->Skip(count);
|
||||
position_ += skipped;
|
||||
return skipped == count;
|
||||
}
|
||||
|
||||
int64 CopyingInputStreamAdaptor::ByteCount() const {
|
||||
return position_ - backup_bytes_;
|
||||
}
|
||||
|
||||
void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() {
|
||||
if (buffer_.get() == NULL) {
|
||||
buffer_.reset(new uint8[buffer_size_]);
|
||||
}
|
||||
}
|
||||
|
||||
void CopyingInputStreamAdaptor::FreeBuffer() {
|
||||
GOOGLE_CHECK_EQ(backup_bytes_, 0);
|
||||
buffer_used_ = 0;
|
||||
buffer_.reset();
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
CopyingOutputStream::~CopyingOutputStream() {}
|
||||
|
||||
CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor(
|
||||
CopyingOutputStream* copying_stream, int block_size)
|
||||
: copying_stream_(copying_stream),
|
||||
owns_copying_stream_(false),
|
||||
failed_(false),
|
||||
position_(0),
|
||||
buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
|
||||
buffer_used_(0) {
|
||||
}
|
||||
|
||||
CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() {
|
||||
WriteBuffer();
|
||||
if (owns_copying_stream_) {
|
||||
delete copying_stream_;
|
||||
}
|
||||
}
|
||||
|
||||
bool CopyingOutputStreamAdaptor::Flush() {
|
||||
return WriteBuffer();
|
||||
}
|
||||
|
||||
bool CopyingOutputStreamAdaptor::Next(void** data, int* size) {
|
||||
if (buffer_used_ == buffer_size_) {
|
||||
if (!WriteBuffer()) return false;
|
||||
}
|
||||
|
||||
AllocateBufferIfNeeded();
|
||||
|
||||
*data = buffer_.get() + buffer_used_;
|
||||
*size = buffer_size_ - buffer_used_;
|
||||
buffer_used_ = buffer_size_;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CopyingOutputStreamAdaptor::BackUp(int count) {
|
||||
GOOGLE_CHECK_GE(count, 0);
|
||||
GOOGLE_CHECK_EQ(buffer_used_, buffer_size_)
|
||||
<< " BackUp() can only be called after Next().";
|
||||
GOOGLE_CHECK_LE(count, buffer_used_)
|
||||
<< " Can't back up over more bytes than were returned by the last call"
|
||||
" to Next().";
|
||||
|
||||
buffer_used_ -= count;
|
||||
}
|
||||
|
||||
int64 CopyingOutputStreamAdaptor::ByteCount() const {
|
||||
return position_ + buffer_used_;
|
||||
}
|
||||
|
||||
bool CopyingOutputStreamAdaptor::WriteBuffer() {
|
||||
if (failed_) {
|
||||
// Already failed on a previous write.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer_used_ == 0) return true;
|
||||
|
||||
if (copying_stream_->Write(buffer_.get(), buffer_used_)) {
|
||||
position_ += buffer_used_;
|
||||
buffer_used_ = 0;
|
||||
return true;
|
||||
} else {
|
||||
failed_ = true;
|
||||
FreeBuffer();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() {
|
||||
if (buffer_ == NULL) {
|
||||
buffer_.reset(new uint8[buffer_size_]);
|
||||
}
|
||||
}
|
||||
|
||||
void CopyingOutputStreamAdaptor::FreeBuffer() {
|
||||
buffer_used_ = 0;
|
||||
buffer_.reset();
|
||||
}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user