Commit 80b1d62b authored by kenton@google.com's avatar kenton@google.com

Submit recent changes from internal branch, including "lite mode" for

C++ and Java.  See CHANGES.txt for more details.
parent d2fd0638
????-??-?? 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>
......
......@@ -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);
}
......
......@@ -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;
}
}
......
// 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;
}
}
}
// 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);
}
......
This diff is collapsed.
......@@ -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);
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -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
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment