Commit 4de8f551 authored by jieluo@google.com's avatar jieluo@google.com

down integrate to svn

parent c5553a3d
......@@ -78,6 +78,7 @@ EXTRA_DIST = \
java/src/main/java/com/google/protobuf/CodedOutputStream.java \
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/Extension.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 \
......@@ -86,6 +87,7 @@ EXTRA_DIST = \
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/LazyField.java \
java/src/main/java/com/google/protobuf/LazyFieldLite.java \
java/src/main/java/com/google/protobuf/LazyStringArrayList.java \
java/src/main/java/com/google/protobuf/LazyStringList.java \
java/src/main/java/com/google/protobuf/LiteralByteString.java \
......@@ -93,8 +95,10 @@ EXTRA_DIST = \
java/src/main/java/com/google/protobuf/MessageLite.java \
java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java \
java/src/main/java/com/google/protobuf/MessageOrBuilder.java \
java/src/main/java/com/google/protobuf/MessageReflection.java \
java/src/main/java/com/google/protobuf/Parser.java \
java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java \
java/src/main/java/com/google/protobuf/ProtocolStringList.java \
java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java \
java/src/main/java/com/google/protobuf/RopeByteString.java \
java/src/main/java/com/google/protobuf/RpcCallback.java \
......@@ -114,6 +118,7 @@ EXTRA_DIST = \
java/src/test/java/com/google/protobuf/AbstractMessageTest.java \
java/src/test/java/com/google/protobuf/BoundedByteStringTest.java \
java/src/test/java/com/google/protobuf/ByteStringTest.java \
java/src/test/java/com/google/protobuf/CheckUtf8Test.java \
java/src/test/java/com/google/protobuf/CodedInputStreamTest.java \
java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java \
java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java \
......@@ -123,8 +128,12 @@ EXTRA_DIST = \
java/src/test/java/com/google/protobuf/GeneratedMessageTest.java \
java/src/test/java/com/google/protobuf/IsValidUtf8Test.java \
java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java \
java/src/test/java/com/google/protobuf/LazyFieldTest.java \
java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java \
java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java \
java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java \
java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java \
java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java \
java/src/test/java/com/google/protobuf/LiteralByteStringTest.java \
java/src/test/java/com/google/protobuf/LiteTest.java \
java/src/test/java/com/google/protobuf/MessageTest.java \
......@@ -142,13 +151,21 @@ EXTRA_DIST = \
java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java \
java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java \
java/src/test/java/com/google/protobuf/WireFormatTest.java \
java/src/test/java/com/google/protobuf/lazy_fields_lite.proto \
java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto \
java/src/test/java/com/google/protobuf/multiple_files_test.proto \
java/src/test/java/com/google/protobuf/nested_builders_test.proto \
java/src/test/java/com/google/protobuf/nested_extension_lite.proto \
java/src/test/java/com/google/protobuf/nested_extension.proto \
java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto \
java/src/test/java/com/google/protobuf/non_nested_extension.proto \
java/src/test/java/com/google/protobuf/outer_class_name_test.proto \
java/src/test/java/com/google/protobuf/outer_class_name_test2.proto \
java/src/test/java/com/google/protobuf/outer_class_name_test3.proto \
java/src/test/java/com/google/protobuf/test_bad_identifiers.proto \
java/src/test/java/com/google/protobuf/test_check_utf8.proto \
java/src/test/java/com/google/protobuf/test_check_utf8_size.proto \
java/src/test/java/com/google/protobuf/test_custom_options.proto \
java/pom.xml \
java/README.txt \
python/google/protobuf/internal/generator_test.py \
......@@ -182,11 +199,6 @@ EXTRA_DIST = \
python/google/protobuf/internal/wire_format.py \
python/google/protobuf/internal/wire_format_test.py \
python/google/protobuf/internal/__init__.py \
python/google/protobuf/pyext/python-proto2.cc \
python/google/protobuf/pyext/python_descriptor.cc \
python/google/protobuf/pyext/python_descriptor.h \
python/google/protobuf/pyext/python_protobuf.cc \
python/google/protobuf/pyext/python_protobuf.h \
python/google/protobuf/descriptor.py \
python/google/protobuf/descriptor_database.py \
python/google/protobuf/descriptor_pool.py \
......
......@@ -30,7 +30,7 @@ list_people_cpp: list_people.cc protoc_middleman
c++ list_people.cc addressbook.pb.cc -o list_people_cpp `pkg-config --cflags --libs protobuf`
javac_middleman: AddPerson.java ListPeople.java protoc_middleman
javac AddPerson.java ListPeople.java com/example/tutorial/AddressBookProtos.java
javac AddPerson.java ListPeople.java com/example/tutorial/AddressBookProtos.java com/example/tutorial/AddressBookProtosInternalDescriptors.java
@touch javac_middleman
add_person_java: javac_middleman
......
......@@ -104,6 +104,8 @@
<arg value="../src/google/protobuf/unittest_import.proto" />
<arg value="../src/google/protobuf/unittest_import_public.proto" />
<arg value="../src/google/protobuf/unittest_mset.proto" />
<arg value="src/test/java/com/google/protobuf/lazy_fields_lite.proto" />
<arg value="src/test/java/com/google/protobuf/lite_equals_and_hash.proto" />
<arg
value="src/test/java/com/google/protobuf/multiple_files_test.proto" />
<arg value="src/test/java/com/google/protobuf/nested_builders_test.proto" />
......@@ -111,7 +113,13 @@
<arg value="src/test/java/com/google/protobuf/nested_extension_lite.proto" />
<arg value="src/test/java/com/google/protobuf/non_nested_extension.proto" />
<arg value="src/test/java/com/google/protobuf/non_nested_extension_lite.proto" />
<arg value="src/test/java/com/google/protobuf/outer_class_name_test.proto" />
<arg value="src/test/java/com/google/protobuf/outer_class_name_test2.proto" />
<arg value="src/test/java/com/google/protobuf/outer_class_name_test3.proto" />
<arg value="src/test/java/com/google/protobuf/test_bad_identifiers.proto" />
<arg value="src/test/java/com/google/protobuf/test_check_utf8.proto" />
<arg value="src/test/java/com/google/protobuf/test_check_utf8_size.proto" />
<arg value="src/test/java/com/google/protobuf/test_custom_options.proto" />
<arg
value="../src/google/protobuf/unittest_optimize_for.proto" />
<arg
......@@ -179,6 +187,8 @@
<include>**/RopeByteString.java</include>
<include>**/Utf8.java</include>
<include>**/LazyField.java</include>
<include>**/LazyFieldLite.java</include>
<include>**/ProtocolStringList.java</include>
</includes>
<testIncludes>
<testInclude>**/LiteTest.java</testInclude>
......
......@@ -44,6 +44,8 @@ import java.util.Collection;
* @author kenton@google.com Kenton Varda
*/
public abstract class AbstractMessageLite implements MessageLite {
protected int memoizedHashCode = 0;
public ByteString toByteString() {
try {
final ByteString.CodedBuilder out =
......@@ -91,6 +93,7 @@ public abstract class AbstractMessageLite implements MessageLite {
codedOutput.flush();
}
/**
* Package private helper method for AbstractParser to create
* UninitializedMessageException.
......@@ -99,6 +102,13 @@ public abstract class AbstractMessageLite implements MessageLite {
return new UninitializedMessageException(this);
}
protected static void checkByteStringIsUtf8(ByteString byteString)
throws IllegalArgumentException {
if (!byteString.isValidUtf8()) {
throw new IllegalArgumentException("Byte string is not UTF-8.");
}
}
/**
* A partial implementation of the {@link Message.Builder} interface which
* implements as many methods of that interface as possible in terms of
......@@ -311,7 +321,8 @@ public abstract class AbstractMessageLite implements MessageLite {
* used by generated code. Users should ignore it.
*
* @throws NullPointerException if any of the elements of {@code values} is
* null.
* null. When that happens, some elements of {@code values} may have already
* been added to the result {@code list}.
*/
protected static <T> void addAll(final Iterable<T> values,
final Collection<? super T> list) {
......@@ -319,14 +330,15 @@ public abstract class AbstractMessageLite implements MessageLite {
// For StringOrByteStringLists, check the underlying elements to avoid
// forcing conversions of ByteStrings to Strings.
checkForNullValues(((LazyStringList) values).getUnderlyingElements());
} else {
list.addAll((Collection<T>) values);
} else if (values instanceof Collection) {
checkForNullValues(values);
}
if (values instanceof Collection) {
final Collection<T> collection = (Collection<T>) values;
list.addAll(collection);
list.addAll((Collection<T>) values);
} else {
for (final T value : values) {
if (value == null) {
throw new NullPointerException();
}
list.add(value);
}
}
......
......@@ -110,10 +110,6 @@ public abstract class AbstractParser<MessageType extends MessageLite>
return message;
} catch (InvalidProtocolBufferException e) {
throw e;
} catch (IOException e) {
throw new RuntimeException(
"Reading from a ByteString threw an IOException (should " +
"never happen).", e);
}
}
......@@ -147,10 +143,6 @@ public abstract class AbstractParser<MessageType extends MessageLite>
return message;
} catch (InvalidProtocolBufferException e) {
throw e;
} catch (IOException e) {
throw new RuntimeException(
"Reading from a byte array threw an IOException (should " +
"never happen).", e);
}
}
......
......@@ -177,6 +177,20 @@ public abstract class ByteString implements Iterable<Byte> {
substring(0, prefix.size()).equals(prefix);
}
/**
* Tests if this bytestring ends with the specified suffix.
* Similar to {@link String#endsWith(String)}
*
* @param suffix the suffix.
* @return <code>true</code> if the byte sequence represented by the
* argument is a suffix of the byte sequence represented by
* this string; <code>false</code> otherwise.
*/
public boolean endsWith(ByteString suffix) {
return size() >= suffix.size() &&
substring(size() - suffix.size()).equals(suffix);
}
// =================================================================
// byte[] -> ByteString
......@@ -512,6 +526,9 @@ public abstract class ByteString implements Iterable<Byte> {
*/
public byte[] toByteArray() {
int size = size();
if (size == 0) {
return Internal.EMPTY_BYTE_ARRAY;
}
byte[] result = new byte[size];
copyToInternal(result, 0, 0, size);
return result;
......@@ -525,6 +542,41 @@ public abstract class ByteString implements Iterable<Byte> {
* @throws IOException if an I/O error occurs.
*/
public abstract void writeTo(OutputStream out) throws IOException;
/**
* Writes a specified part of this byte string to an output stream.
*
* @param out the output stream to which to write the data.
* @param sourceOffset offset within these bytes
* @param numberToWrite number of bytes to write
* @throws IOException if an I/O error occurs.
* @throws IndexOutOfBoundsException if an offset or size is negative or too
* large
*/
void writeTo(OutputStream out, int sourceOffset, int numberToWrite)
throws IOException {
if (sourceOffset < 0) {
throw new IndexOutOfBoundsException("Source offset < 0: " + sourceOffset);
}
if (numberToWrite < 0) {
throw new IndexOutOfBoundsException("Length < 0: " + numberToWrite);
}
if (sourceOffset + numberToWrite > size()) {
throw new IndexOutOfBoundsException(
"Source end offset exceeded: " + (sourceOffset + numberToWrite));
}
if (numberToWrite > 0) {
writeToInternal(out, sourceOffset, numberToWrite);
}
}
/**
* Internal version of {@link #writeTo(OutputStream,int,int)} that assumes
* all error checking has already been done.
*/
abstract void writeToInternal(OutputStream out, int sourceOffset,
int numberToWrite) throws IOException;
/**
* Constructs a read-only {@code java.nio.ByteBuffer} whose content
......
......@@ -32,6 +32,7 @@ package com.google.protobuf;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.OneofDescriptor;
import java.io.InputStream;
import java.io.IOException;
......@@ -47,16 +48,25 @@ import java.util.Map;
public final class DynamicMessage extends AbstractMessage {
private final Descriptor type;
private final FieldSet<FieldDescriptor> fields;
private final FieldDescriptor[] oneofCases;
private final UnknownFieldSet unknownFields;
private int memoizedSize = -1;
/**
* Construct a {@code DynamicMessage} using the given {@code FieldSet}.
* oneofCases stores the FieldDescriptor for each oneof to indicate
* which field is set. Caller should make sure the array is immutable.
*
* This contructor is package private and will be used in
* {@code DynamicMutableMessage} to convert a mutable message to an immutable
* message.
*/
private DynamicMessage(Descriptor type, FieldSet<FieldDescriptor> fields,
UnknownFieldSet unknownFields) {
DynamicMessage(Descriptor type, FieldSet<FieldDescriptor> fields,
FieldDescriptor[] oneofCases,
UnknownFieldSet unknownFields) {
this.type = type;
this.fields = fields;
this.oneofCases = oneofCases;
this.unknownFields = unknownFields;
}
......@@ -65,10 +75,14 @@ public final class DynamicMessage extends AbstractMessage {
* given type.
*/
public static DynamicMessage getDefaultInstance(Descriptor type) {
int oneofDeclCount = type.toProto().getOneofDeclCount();
FieldDescriptor[] oneofCases = new FieldDescriptor[oneofDeclCount];
return new DynamicMessage(type, FieldSet.<FieldDescriptor>emptySet(),
oneofCases,
UnknownFieldSet.getDefaultInstance());
}
/** Parse a message of the given type from the given input stream. */
public static DynamicMessage parseFrom(Descriptor type,
CodedInputStream input)
......@@ -152,6 +166,20 @@ public final class DynamicMessage extends AbstractMessage {
return fields.getAllFields();
}
public boolean hasOneof(OneofDescriptor oneof) {
verifyOneofContainingType(oneof);
FieldDescriptor field = oneofCases[oneof.getIndex()];
if (field == null) {
return false;
}
return true;
}
public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
verifyOneofContainingType(oneof);
return oneofCases[oneof.getIndex()];
}
public boolean hasField(FieldDescriptor field) {
verifyContainingType(field);
return fields.hasField(field);
......@@ -186,8 +214,8 @@ public final class DynamicMessage extends AbstractMessage {
return unknownFields;
}
private static boolean isInitialized(Descriptor type,
FieldSet<FieldDescriptor> fields) {
static boolean isInitialized(Descriptor type,
FieldSet<FieldDescriptor> fields) {
// Check that all required fields are present.
for (final FieldDescriptor field : type.getFields()) {
if (field.isRequired()) {
......@@ -270,6 +298,14 @@ public final class DynamicMessage extends AbstractMessage {
}
}
/** Verifies that the oneof is an oneof of this message. */
private void verifyOneofContainingType(OneofDescriptor oneof) {
if (oneof.getContainingType() != type) {
throw new IllegalArgumentException(
"OneofDescriptor does not match message type.");
}
}
// =================================================================
/**
......@@ -278,6 +314,7 @@ public final class DynamicMessage extends AbstractMessage {
public static final class Builder extends AbstractMessage.Builder<Builder> {
private final Descriptor type;
private FieldSet<FieldDescriptor> fields;
private final FieldDescriptor[] oneofCases;
private UnknownFieldSet unknownFields;
/** Construct a {@code Builder} for the given type. */
......@@ -285,6 +322,7 @@ public final class DynamicMessage extends AbstractMessage {
this.type = type;
this.fields = FieldSet.newFieldSet();
this.unknownFields = UnknownFieldSet.getDefaultInstance();
this.oneofCases = new FieldDescriptor[type.toProto().getOneofDeclCount()];
}
// ---------------------------------------------------------------
......@@ -313,6 +351,17 @@ public final class DynamicMessage extends AbstractMessage {
ensureIsMutable();
fields.mergeFrom(otherDynamicMessage.fields);
mergeUnknownFields(otherDynamicMessage.unknownFields);
for (int i = 0; i < oneofCases.length; i++) {
if (oneofCases[i] == null) {
oneofCases[i] = otherDynamicMessage.oneofCases[i];
} else {
if ((otherDynamicMessage.oneofCases[i] != null)
&& (oneofCases[i] != otherDynamicMessage.oneofCases[i])) {
fields.clearField(oneofCases[i]);
oneofCases[i] = otherDynamicMessage.oneofCases[i];
}
}
}
return this;
} else {
return super.mergeFrom(other);
......@@ -322,7 +371,8 @@ public final class DynamicMessage extends AbstractMessage {
public DynamicMessage build() {
if (!isInitialized()) {
throw newUninitializedMessageException(
new DynamicMessage(type, fields, unknownFields));
new DynamicMessage(type, fields,
java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields));
}
return buildPartial();
}
......@@ -335,7 +385,8 @@ public final class DynamicMessage extends AbstractMessage {
private DynamicMessage buildParsed() throws InvalidProtocolBufferException {
if (!isInitialized()) {
throw newUninitializedMessageException(
new DynamicMessage(type, fields, unknownFields))
new DynamicMessage(type, fields,
java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields))
.asInvalidProtocolBufferException();
}
return buildPartial();
......@@ -344,7 +395,8 @@ public final class DynamicMessage extends AbstractMessage {
public DynamicMessage buildPartial() {
fields.makeImmutable();
DynamicMessage result =
new DynamicMessage(type, fields, unknownFields);
new DynamicMessage(type, fields,
java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields);
return result;
}
......@@ -353,6 +405,7 @@ public final class DynamicMessage extends AbstractMessage {
Builder result = new Builder(type);
result.fields.mergeFrom(fields);
result.mergeUnknownFields(unknownFields);
System.arraycopy(oneofCases, 0, result.oneofCases, 0 , oneofCases.length);
return result;
}
......@@ -383,6 +436,29 @@ public final class DynamicMessage extends AbstractMessage {
return new Builder(field.getMessageType());
}
public boolean hasOneof(OneofDescriptor oneof) {
verifyOneofContainingType(oneof);
FieldDescriptor field = oneofCases[oneof.getIndex()];
if (field == null) {
return false;
}
return true;
}
public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
verifyOneofContainingType(oneof);
return oneofCases[oneof.getIndex()];
}
public Builder clearOneof(OneofDescriptor oneof) {
verifyOneofContainingType(oneof);
FieldDescriptor field = oneofCases[oneof.getIndex()];
if (field != null) {
clearField(field);
}
return this;
}
public boolean hasField(FieldDescriptor field) {
verifyContainingType(field);
return fields.hasField(field);
......@@ -392,7 +468,9 @@ public final class DynamicMessage extends AbstractMessage {
verifyContainingType(field);
Object result = fields.getField(field);
if (result == null) {
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
if (field.isRepeated()) {
result = Collections.emptyList();
} else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
result = getDefaultInstance(field.getMessageType());
} else {
result = field.getDefaultValue();
......@@ -404,6 +482,15 @@ public final class DynamicMessage extends AbstractMessage {
public Builder setField(FieldDescriptor field, Object value) {
verifyContainingType(field);
ensureIsMutable();
OneofDescriptor oneofDescriptor = field.getContainingOneof();
if (oneofDescriptor != null) {
int index = oneofDescriptor.getIndex();
FieldDescriptor oldField = oneofCases[index];
if ((oldField != null) && (oldField != field)) {
fields.clearField(oldField);
}
oneofCases[index] = field;
}
fields.setField(field, value);
return this;
}
......@@ -411,6 +498,13 @@ public final class DynamicMessage extends AbstractMessage {
public Builder clearField(FieldDescriptor field) {
verifyContainingType(field);
ensureIsMutable();
OneofDescriptor oneofDescriptor = field.getContainingOneof();
if (oneofDescriptor != null) {
int index = oneofDescriptor.getIndex();
if (oneofCases[index] == field) {
oneofCases[index] = null;
}
}
fields.clearField(field);
return this;
}
......@@ -466,6 +560,14 @@ public final class DynamicMessage extends AbstractMessage {
}
}
/** Verifies that the oneof is an oneof of this message. */
private void verifyOneofContainingType(OneofDescriptor oneof) {
if (oneof.getContainingType() != type) {
throw new IllegalArgumentException(
"OneofDescriptor does not match message type.");
}
}
private void ensureIsMutable() {
if (fields.isImmutable()) {
fields = fields.clone();
......
// 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;
/**
* Interface that generated extensions implement.
*
* @author liujisi@google.com (Jisi Liu)
*/
public abstract class Extension<ContainingType extends MessageLite, Type> {
/** Returns the field number of the extension. */
public abstract int getNumber();
/** Returns the type of the field. */
public abstract WireFormat.FieldType getLiteType();
/** Returns whether it is a repeated field. */
public abstract boolean isRepeated();
/** Returns the descriptor of the extension. */
public abstract Descriptors.FieldDescriptor getDescriptor();
/** Returns the default value of the extension field. */
public abstract Type getDefaultValue();
/**
* Returns the default instance of the extension field, if it's a message
* extension.
*/
public abstract MessageLite getMessageDefaultInstance();
// All the methods below are extension implementation details.
/**
* The API type that the extension is used for.
*/
protected enum ExtensionType {
IMMUTABLE,
MUTABLE,
PROTO1,
}
protected ExtensionType getExtensionType() {
// TODO(liujisi): make this abstract after we fix proto1.
return ExtensionType.IMMUTABLE;
}
/**
* Type of a message extension.
*/
public enum MessageType {
PROTO1,
PROTO2,
}
/**
* If the extension is a message extension (i.e., getLiteType() == MESSAGE),
* returns the type of the message, otherwise undefined.
*/
public MessageType getMessageType() {
return MessageType.PROTO2;
}
protected abstract Object fromReflectionType(Object value);
protected abstract Object singularFromReflectionType(Object value);
protected abstract Object toReflectionType(Object value);
protected abstract Object singularToReflectionType(Object value);
}
......@@ -146,6 +146,7 @@ final class FieldSet<FieldDescriptorType extends
return clone;
}
// =================================================================
/** See {@link Message.Builder#clear()}. */
......@@ -376,10 +377,13 @@ final class FieldSet<FieldDescriptorType extends
case DOUBLE: isValid = value instanceof Double ; break;
case BOOLEAN: isValid = value instanceof Boolean ; break;
case STRING: isValid = value instanceof String ; break;
case BYTE_STRING: isValid = value instanceof ByteString; break;
case BYTE_STRING:
isValid = value instanceof ByteString || value instanceof byte[];
break;
case ENUM:
// TODO(kenton): Caller must do type checking here, I guess.
isValid = value instanceof Internal.EnumLite;
isValid =
(value instanceof Integer || value instanceof Internal.EnumLite);
break;
case MESSAGE:
// TODO(kenton): Caller must do type checking here, I guess.
......@@ -483,6 +487,17 @@ final class FieldSet<FieldDescriptorType extends
}
}
private Object cloneIfMutable(Object value) {
if (value instanceof byte[]) {
byte[] bytes = (byte[]) value;
byte[] copy = new byte[bytes.length];
System.arraycopy(bytes, 0, copy, 0, bytes.length);
return copy;
} else {
return value;
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void mergeFromField(
final Map.Entry<FieldDescriptorType, Object> entry) {
......@@ -495,28 +510,26 @@ final class FieldSet<FieldDescriptorType extends
if (descriptor.isRepeated()) {
Object value = getField(descriptor);
if (value == null) {
// Our list is empty, but we still need to make a defensive copy of
// the other list since we don't know if the other FieldSet is still
// mutable.
fields.put(descriptor, new ArrayList((List) otherValue));
} else {
// Concatenate the lists.
((List) value).addAll((List) otherValue);
value = new ArrayList();
}
for (Object element : (List) otherValue) {
((List) value).add(cloneIfMutable(element));
}
fields.put(descriptor, value);
} else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
Object value = getField(descriptor);
if (value == null) {
fields.put(descriptor, otherValue);
fields.put(descriptor, cloneIfMutable(otherValue));
} else {
// Merge the messages.
fields.put(
descriptor,
descriptor.internalMergeFrom(
value = descriptor.internalMergeFrom(
((MessageLite) value).toBuilder(), (MessageLite) otherValue)
.build());
.build();
fields.put(descriptor, value);
}
} else {
fields.put(descriptor, otherValue);
fields.put(descriptor, cloneIfMutable(otherValue));
}
}
......@@ -524,11 +537,13 @@ final class FieldSet<FieldDescriptorType extends
// other class. Probably WireFormat.
/**
* Read a field of any primitive type from a CodedInputStream. Enums,
* groups, and embedded messages are not handled by this method.
* Read a field of any primitive type for immutable messages from a
* CodedInputStream. Enums, groups, and embedded messages are not handled by
* this method.
*
* @param input The stream from which to read.
* @param type Declared type of the field.
* @param checkUtf8 When true, check that the input is valid utf8.
* @return An object representing the field's value, of the exact
* type which would be returned by
* {@link Message#getField(Descriptors.FieldDescriptor)} for
......@@ -536,7 +551,8 @@ final class FieldSet<FieldDescriptorType extends
*/
public static Object readPrimitiveField(
CodedInputStream input,
final WireFormat.FieldType type) throws IOException {
final WireFormat.FieldType type,
boolean checkUtf8) throws IOException {
switch (type) {
case DOUBLE : return input.readDouble ();
case FLOAT : return input.readFloat ();
......@@ -546,7 +562,11 @@ final class FieldSet<FieldDescriptorType extends
case FIXED64 : return input.readFixed64 ();
case FIXED32 : return input.readFixed32 ();
case BOOL : return input.readBool ();
case STRING : return input.readString ();
case STRING : if (checkUtf8) {
return input.readStringRequireUtf8();
} else {
return input.readString();
}
case BYTES : return input.readBytes ();
case UINT32 : return input.readUInt32 ();
case SFIXED32: return input.readSFixed32();
......@@ -571,6 +591,7 @@ final class FieldSet<FieldDescriptorType extends
"There is no way to get here, but the compiler thinks otherwise.");
}
/** See {@link Message#writeTo(CodedOutputStream)}. */
public void writeTo(final CodedOutputStream output)
throws IOException {
......@@ -605,8 +626,12 @@ final class FieldSet<FieldDescriptorType extends
final FieldDescriptorType descriptor = entry.getKey();
if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE &&
!descriptor.isRepeated() && !descriptor.isPacked()) {
Object value = entry.getValue();
if (value instanceof LazyField) {
value = ((LazyField) value).getValue();
}
output.writeMessageSetExtension(entry.getKey().getNumber(),
(MessageLite) entry.getValue());
(MessageLite) value);
} else {
writeField(descriptor, entry.getValue(), output);
}
......@@ -630,7 +655,7 @@ final class FieldSet<FieldDescriptorType extends
// Special case for groups, which need a start and end tag; other fields
// can just use writeTag() and writeFieldNoTag().
if (type == WireFormat.FieldType.GROUP) {
output.writeGroup(number, (MessageLite) value);
output.writeGroup(number, (MessageLite) value);
} else {
output.writeTag(number, getWireFormatForFieldType(type, false));
writeElementNoTag(output, type, value);
......@@ -663,7 +688,13 @@ final class FieldSet<FieldDescriptorType extends
case STRING : output.writeStringNoTag ((String ) value); break;
case GROUP : output.writeGroupNoTag ((MessageLite) value); break;
case MESSAGE : output.writeMessageNoTag ((MessageLite) value); break;
case BYTES : output.writeBytesNoTag ((ByteString ) value); break;
case BYTES:
if (value instanceof ByteString) {
output.writeBytesNoTag((ByteString) value);
} else {
output.writeByteArrayNoTag((byte[]) value);
}
break;
case UINT32 : output.writeUInt32NoTag ((Integer ) value); break;
case SFIXED32: output.writeSFixed32NoTag((Integer ) value); break;
case SFIXED64: output.writeSFixed64NoTag((Long ) value); break;
......@@ -671,7 +702,11 @@ final class FieldSet<FieldDescriptorType extends
case SINT64 : output.writeSInt64NoTag ((Long ) value); break;
case ENUM:
output.writeEnumNoTag(((Internal.EnumLite) value).getNumber());
if (value instanceof Internal.EnumLite) {
output.writeEnumNoTag(((Internal.EnumLite) value).getNumber());
} else {
output.writeEnumNoTag(((Integer) value).intValue());
}
break;
}
}
......@@ -778,7 +813,9 @@ final class FieldSet<FieldDescriptorType extends
final int number, final Object value) {
int tagSize = CodedOutputStream.computeTagSize(number);
if (type == WireFormat.FieldType.GROUP) {
tagSize *= 2;
// Only count the end group tag for proto2 messages as for proto1 the end
// group tag will be counted as a part of getSerializedSize().
tagSize *= 2;
}
return tagSize + computeElementSizeNoTag(type, value);
}
......@@ -808,7 +845,12 @@ final class FieldSet<FieldDescriptorType extends
case BOOL : return CodedOutputStream.computeBoolSizeNoTag ((Boolean )value);
case STRING : return CodedOutputStream.computeStringSizeNoTag ((String )value);
case GROUP : return CodedOutputStream.computeGroupSizeNoTag ((MessageLite)value);
case BYTES : return CodedOutputStream.computeBytesSizeNoTag ((ByteString )value);
case BYTES :
if (value instanceof ByteString) {
return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
} else {
return CodedOutputStream.computeByteArraySizeNoTag((byte[]) value);
}
case UINT32 : return CodedOutputStream.computeUInt32SizeNoTag ((Integer )value);
case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer )value);
case SFIXED64: return CodedOutputStream.computeSFixed64SizeNoTag((Long )value);
......@@ -823,8 +865,12 @@ final class FieldSet<FieldDescriptorType extends
}
case ENUM:
return CodedOutputStream.computeEnumSizeNoTag(
((Internal.EnumLite) value).getNumber());
if (value instanceof Internal.EnumLite) {
return CodedOutputStream.computeEnumSizeNoTag(
((Internal.EnumLite) value).getNumber());
} else {
return CodedOutputStream.computeEnumSizeNoTag((Integer) value);
}
}
throw new RuntimeException(
......
......@@ -111,4 +111,12 @@ public class InvalidProtocolBufferException extends IOException {
"Protocol message was too large. May be malicious. " +
"Use CodedInputStream.setSizeLimit() to increase the size limit.");
}
static InvalidProtocolBufferException parseFailure() {
return new InvalidProtocolBufferException("Failed to parse the message.");
}
static InvalidProtocolBufferException invalidUtf8() {
return new InvalidProtocolBufferException("Protocol message had invalid UTF-8.");
}
}
......@@ -53,6 +53,7 @@ public interface Message extends MessageLite, MessageOrBuilder {
// (From MessageLite, re-declared here only for return type covariance.)
Parser<? extends Message> getParserForType();
// -----------------------------------------------------------------
// Comparison and hashing
......@@ -179,6 +180,12 @@ public interface Message extends MessageLite, MessageOrBuilder {
*/
Builder clearField(Descriptors.FieldDescriptor field);
/**
* Clears the oneof. This is exactly equivalent to calling the generated
* "clear" accessor method corresponding to the oneof.
*/
Builder clearOneof(Descriptors.OneofDescriptor oneof);
/**
* Sets an element of a repeated field to the given value. The value must
* be of the correct type for this field, i.e. the same type that
......
......@@ -128,6 +128,7 @@ public interface MessageLite extends MessageLiteOrBuilder {
*/
void writeDelimitedTo(OutputStream output) throws IOException;
// =================================================================
// Builders
......
This diff is collapsed.
......@@ -35,6 +35,8 @@ import java.io.InputStream;
/**
* Abstract interface for parsing Protocol Messages.
*
* The implementation should be stateless and thread-safe.
*
* @author liujisi@google.com (Pherl Liu)
*/
public interface Parser<MessageType> {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -38,6 +38,7 @@ import "com/google/protobuf/non_nested_extension.proto";
package protobuf_unittest;
message MyNestedExtension {
extend MessageToBeExtended {
optional MessageToBeExtended recursiveExtension = 2;
......
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.
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