Commit aa8ef98a authored by Feng Xiao's avatar Feng Xiao

Merge pull request #91 from xfxyjwf/android_nano

Merge nano proto into protobuf repository.
parents 8a87fb8e 9e65d4bf
This diff is collapsed.
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.google</groupId>
<artifactId>google</artifactId>
<version>1</version>
</parent>
<groupId>com.google.protobuf.nano</groupId>
<artifactId>protobuf-javanano</artifactId>
<version>2.6.2-pre</version>
<packaging>bundle</packaging>
<name>Protocol Buffer JavaNano API</name>
<description>
Protocol Buffers are a way of encoding structured data in an efficient yet
extensible format.
</description>
<inceptionYear>2008</inceptionYear>
<url>https://developers.google.com/protocol-buffers/</url>
<licenses>
<license>
<name>New BSD license</name>
<url>http://www.opensource.org/licenses/bsd-license.php</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<url>https://github.com/google/protobuf</url>
<connection>
scm:git:https://github.com/google/protobuf.git
</connection>
</scm>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymockclassextension</artifactId>
<version>2.2.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>generate-test-sources</id>
<phase>generate-test-sources</phase>
<configuration>
<tasks>
<mkdir dir="target/generated-test-sources" />
<exec executable="../src/protoc">
<arg value="--javanano_out=generate_equals=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_simple_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_stringutf8_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_recursive_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_import_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_single_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_multiple_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=store_unknown_fields=true,generate_equals=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_extension_singular_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_extension_repeated_nano.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=store_unknown_fields=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=java_nano_generate_has=true,generate_equals=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_has_nano.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=optional_field_style=accessors,generate_equals=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_accessors_nano.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=enum_style=java:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_enum_class_multiple_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_repeated_packables_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=
optional_field_style=accessors,
java_outer_classname=google/protobuf/nano/unittest_enum_validity_nano.proto|EnumValidityAccessors
:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=optional_field_style=reftypes,generate_equals=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto" />
</exec>
</tasks>
<testSourceRoot>target/generated-test-sources</testSourceRoot>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
<Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
<Export-Package>com.google.protobuf;version=2.6.2-pre</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
// Protocol Buffers - Google's data interchange format
// Copyright 2013 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.nano;
import java.io.IOException;
/**
* Base class of those Protocol Buffer messages that need to store unknown fields,
* such as extensions.
*/
public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
extends MessageNano {
/**
* A container for fields unknown to the message, including extensions. Extension fields can
* can be accessed through the {@link #getExtension} and {@link #setExtension} methods.
*/
protected FieldArray unknownFieldData;
@Override
protected int computeSerializedSize() {
int size = 0;
if (unknownFieldData != null) {
for (int i = 0; i < unknownFieldData.size(); i++) {
FieldData field = unknownFieldData.dataAt(i);
size += field.computeSerializedSize();
}
}
return size;
}
@Override
public void writeTo(CodedOutputByteBufferNano output) throws IOException {
if (unknownFieldData == null) {
return;
}
for (int i = 0; i < unknownFieldData.size(); i++) {
FieldData field = unknownFieldData.dataAt(i);
field.writeTo(output);
}
}
/**
* Checks if there is a value stored for the specified extension in this
* message.
*/
public final boolean hasExtension(Extension<M, ?> extension) {
if (unknownFieldData == null) {
return false;
}
FieldData field = unknownFieldData.get(WireFormatNano.getTagFieldNumber(extension.tag));
return field != null;
}
/**
* Gets the value stored in the specified extension of this message.
*/
public final <T> T getExtension(Extension<M, T> extension) {
if (unknownFieldData == null) {
return null;
}
FieldData field = unknownFieldData.get(WireFormatNano.getTagFieldNumber(extension.tag));
return field == null ? null : field.getValue(extension);
}
/**
* Sets the value of the specified extension of this message.
*/
public final <T> M setExtension(Extension<M, T> extension, T value) {
int fieldNumber = WireFormatNano.getTagFieldNumber(extension.tag);
if (value == null) {
if (unknownFieldData != null) {
unknownFieldData.remove(fieldNumber);
if (unknownFieldData.isEmpty()) {
unknownFieldData = null;
}
}
} else {
FieldData field = null;
if (unknownFieldData == null) {
unknownFieldData = new FieldArray();
} else {
field = unknownFieldData.get(fieldNumber);
}
if (field == null) {
unknownFieldData.put(fieldNumber, new FieldData(extension, value));
} else {
field.setValue(extension, value);
}
}
@SuppressWarnings("unchecked") // Generated code should guarantee type safety
M typedThis = (M) this;
return typedThis;
}
/**
* Stores the binary data of an unknown field.
*
* <p>Generated messages will call this for unknown fields if the store_unknown_fields
* option is on.
*
* <p>Note that the tag might be a end-group tag (rather than the start of an unknown field) in
* which case we do not want to add an unknown field entry.
*
* @param input the input buffer.
* @param tag the tag of the field.
* @return {@literal true} unless the tag is an end-group tag.
*/
protected final boolean storeUnknownField(CodedInputByteBufferNano input, int tag)
throws IOException {
int startPos = input.getPosition();
if (!input.skipField(tag)) {
return false; // This wasn't an unknown field, it's an end-group tag.
}
int fieldNumber = WireFormatNano.getTagFieldNumber(tag);
int endPos = input.getPosition();
byte[] bytes = input.getData(startPos, endPos - startPos);
UnknownFieldData unknownField = new UnknownFieldData(tag, bytes);
FieldData field = null;
if (unknownFieldData == null) {
unknownFieldData = new FieldArray();
} else {
field = unknownFieldData.get(fieldNumber);
}
if (field == null) {
field = new FieldData();
unknownFieldData.put(fieldNumber, field);
}
field.addUnknownField(unknownField);
return true;
}
/**
* Returns whether the stored unknown field data in this message is equivalent to that in the
* other message.
*
* @param other the other message.
* @return whether the two sets of unknown field data are equal.
*/
protected final boolean unknownFieldDataEquals(M other) {
if (unknownFieldData == null || unknownFieldData.isEmpty()) {
return other.unknownFieldData == null || other.unknownFieldData.isEmpty();
} else {
return unknownFieldData.equals(other.unknownFieldData);
}
}
/**
* Computes the hashcode representing the unknown field data stored in this message.
*
* @return the hashcode for the unknown field data.
*/
protected final int unknownFieldDataHashCode() {
return (unknownFieldData == null || unknownFieldData.isEmpty()
? 0 : unknownFieldData.hashCode());
}
}
This diff is collapsed.
// Protocol Buffers - Google's data interchange format
// Copyright 2014 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.nano;
/**
* A custom version of {@link android.util.SparseArray} with the minimal API
* for storing {@link FieldData} objects.
*
* Based on {@link android.support.v4.util.SpareArrayCompat}.
*/
class FieldArray {
private static final FieldData DELETED = new FieldData();
private boolean mGarbage = false;
private int[] mFieldNumbers;
private FieldData[] mData;
private int mSize;
/**
* Creates a new FieldArray containing no fields.
*/
public FieldArray() {
this(10);
}
/**
* Creates a new FieldArray containing no mappings that will not
* require any additional memory allocation to store the specified
* number of mappings.
*/
public FieldArray(int initialCapacity) {
initialCapacity = idealIntArraySize(initialCapacity);
mFieldNumbers = new int[initialCapacity];
mData = new FieldData[initialCapacity];
mSize = 0;
}
/**
* Gets the FieldData mapped from the specified fieldNumber, or <code>null</code>
* if no such mapping has been made.
*/
public FieldData get(int fieldNumber) {
int i = binarySearch(fieldNumber);
if (i < 0 || mData[i] == DELETED) {
return null;
} else {
return mData[i];
}
}
/**
* Removes the data from the specified fieldNumber, if there was any.
*/
public void remove(int fieldNumber) {
int i = binarySearch(fieldNumber);
if (i >= 0 && mData[i] != DELETED) {
mData[i] = DELETED;
mGarbage = true;
}
}
private void gc() {
int n = mSize;
int o = 0;
int[] keys = mFieldNumbers;
FieldData[] values = mData;
for (int i = 0; i < n; i++) {
FieldData val = values[i];
if (val != DELETED) {
if (i != o) {
keys[o] = keys[i];
values[o] = val;
values[i] = null;
}
o++;
}
}
mGarbage = false;
mSize = o;
}
/**
* Adds a mapping from the specified fieldNumber to the specified data,
* replacing the previous mapping if there was one.
*/
public void put(int fieldNumber, FieldData data) {
int i = binarySearch(fieldNumber);
if (i >= 0) {
mData[i] = data;
} else {
i = ~i;
if (i < mSize && mData[i] == DELETED) {
mFieldNumbers[i] = fieldNumber;
mData[i] = data;
return;
}
if (mGarbage && mSize >= mFieldNumbers.length) {
gc();
// Search again because indices may have changed.
i = ~ binarySearch(fieldNumber);
}
if (mSize >= mFieldNumbers.length) {
int n = idealIntArraySize(mSize + 1);
int[] nkeys = new int[n];
FieldData[] nvalues = new FieldData[n];
System.arraycopy(mFieldNumbers, 0, nkeys, 0, mFieldNumbers.length);
System.arraycopy(mData, 0, nvalues, 0, mData.length);
mFieldNumbers = nkeys;
mData = nvalues;
}
if (mSize - i != 0) {
System.arraycopy(mFieldNumbers, i, mFieldNumbers, i + 1, mSize - i);
System.arraycopy(mData, i, mData, i + 1, mSize - i);
}
mFieldNumbers[i] = fieldNumber;
mData[i] = data;
mSize++;
}
}
/**
* Returns the number of key-value mappings that this FieldArray
* currently stores.
*/
public int size() {
if (mGarbage) {
gc();
}
return mSize;
}
public boolean isEmpty() {
return size() == 0;
}
/**
* Given an index in the range <code>0...size()-1</code>, returns
* the value from the <code>index</code>th key-value mapping that this
* FieldArray stores.
*/
public FieldData dataAt(int index) {
if (mGarbage) {
gc();
}
return mData[index];
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof FieldArray)) {
return false;
}
FieldArray other = (FieldArray) o;
if (size() != other.size()) { // size() will call gc() if necessary.
return false;
}
return arrayEquals(mFieldNumbers, other.mFieldNumbers, mSize) &&
arrayEquals(mData, other.mData, mSize);
}
@Override
public int hashCode() {
if (mGarbage) {
gc();
}
int result = 17;
for (int i = 0; i < mSize; i++) {
result = 31 * result + mFieldNumbers[i];
result = 31 * result + mData[i].hashCode();
}
return result;
}
private int idealIntArraySize(int need) {
return idealByteArraySize(need * 4) / 4;
}
private int idealByteArraySize(int need) {
for (int i = 4; i < 32; i++)
if (need <= (1 << i) - 12)
return (1 << i) - 12;
return need;
}
private int binarySearch(int value) {
int lo = 0;
int hi = mSize - 1;
while (lo <= hi) {
int mid = (lo + hi) >>> 1;
int midVal = mFieldNumbers[mid];
if (midVal < value) {
lo = mid + 1;
} else if (midVal > value) {
hi = mid - 1;
} else {
return mid; // value found
}
}
return ~lo; // value not present
}
private boolean arrayEquals(int[] a, int[] b, int size) {
for (int i = 0; i < size; i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
}
private boolean arrayEquals(FieldData[] a, FieldData[] b, int size) {
for (int i = 0; i < size; i++) {
if (!a[i].equals(b[i])) {
return false;
}
}
return true;
}
}
// Protocol Buffers - Google's data interchange format
// Copyright 2014 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.nano;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Stores unknown fields. These might be extensions or fields that the generated API doesn't
* know about yet.
*/
class FieldData {
private Extension<?, ?> cachedExtension;
private Object value;
/** The serialised values for this object. Will be cleared if getValue is called */
private List<UnknownFieldData> unknownFieldData;
<T> FieldData(Extension<?, T> extension, T newValue) {
cachedExtension = extension;
value = newValue;
}
FieldData() {
unknownFieldData = new ArrayList<UnknownFieldData>();
}
void addUnknownField(UnknownFieldData unknownField) {
unknownFieldData.add(unknownField);
}
UnknownFieldData getUnknownField(int index) {
if (unknownFieldData == null) {
return null;
}
if (index < unknownFieldData.size()) {
return unknownFieldData.get(index);
}
return null;
}
int getUnknownFieldSize() {
if (unknownFieldData == null) {
return 0;
}
return unknownFieldData.size();
}
<T> T getValue(Extension<?, T> extension) {
if (value != null){
if (cachedExtension != extension) { // Extension objects are singletons.
throw new IllegalStateException(
"Tried to getExtension with a differernt Extension.");
}
} else {
cachedExtension = extension;
value = extension.getValueFrom(unknownFieldData);
unknownFieldData = null;
}
return (T) value;
}
<T> void setValue(Extension<?, T> extension, T newValue) {
cachedExtension = extension;
value = newValue;
unknownFieldData = null;
}
int computeSerializedSize() {
int size = 0;
if (value != null) {
size = cachedExtension.computeSerializedSize(value);
} else {
for (UnknownFieldData unknownField : unknownFieldData) {
size += unknownField.computeSerializedSize();
}
}
return size;
}
void writeTo(CodedOutputByteBufferNano output) throws IOException {
if (value != null) {
cachedExtension.writeTo(value, output);
} else {
for (UnknownFieldData unknownField : unknownFieldData) {
unknownField.writeTo(output);
}
}
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof FieldData)) {
return false;
}
FieldData other = (FieldData) o;
if (value != null && other.value != null) {
// If both objects have deserialized values, compare those.
// Since unknown fields are only compared if messages have generated equals methods
// we know this will be a meaningful comparison (not identity) for all values.
if (cachedExtension != other.cachedExtension) { // Extension objects are singletons.
return false;
}
if (!cachedExtension.clazz.isArray()) {
// Can't test (!cachedExtension.repeated) due to 'bytes' -> 'byte[]'
return value.equals(other.value);
}
if (value instanceof byte[]) {
return Arrays.equals((byte[]) value, (byte[]) other.value);
} else if (value instanceof int[]) {
return Arrays.equals((int[]) value, (int[]) other.value);
} else if (value instanceof long[]) {
return Arrays.equals((long[]) value, (long[]) other.value);
} else if (value instanceof float[]) {
return Arrays.equals((float[]) value, (float[]) other.value);
} else if (value instanceof double[]) {
return Arrays.equals((double[]) value, (double[]) other.value);
} else if (value instanceof boolean[]) {
return Arrays.equals((boolean[]) value, (boolean[]) other.value);
} else {
return Arrays.deepEquals((Object[]) value, (Object[]) other.value);
}
}
if (unknownFieldData != null && other.unknownFieldData != null) {
// If both objects have byte arrays compare those directly.
return unknownFieldData.equals(other.unknownFieldData);
}
try {
// As a last resort, serialize and compare the resulting byte arrays.
return Arrays.equals(toByteArray(), other.toByteArray());
} catch (IOException e) {
// Should not happen.
throw new IllegalStateException(e);
}
}
@Override
public int hashCode() {
int result = 17;
try {
// The only way to generate a consistent hash is to use the serialized form.
result = 31 * result + Arrays.hashCode(toByteArray());
} catch (IOException e) {
// Should not happen.
throw new IllegalStateException(e);
}
return result;
}
private byte[] toByteArray() throws IOException {
byte[] result = new byte[computeSerializedSize()];
CodedOutputByteBufferNano output = CodedOutputByteBufferNano.newInstance(result);
writeTo(output);
return result;
}
}
// Protocol Buffers - Google's data interchange format
// Copyright 2013 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.nano;
import java.io.IOException;
/**
* Thrown when a protocol message being parsed is invalid in some way,
* e.g. it contains a malformed varint or a negative byte length.
*
* @author kenton@google.com Kenton Varda
*/
public class InvalidProtocolBufferNanoException extends IOException {
private static final long serialVersionUID = -1616151763072450476L;
public InvalidProtocolBufferNanoException(final String description) {
super(description);
}
static InvalidProtocolBufferNanoException truncatedMessage() {
return new InvalidProtocolBufferNanoException(
"While parsing a protocol message, the input ended unexpectedly " +
"in the middle of a field. This could mean either than the " +
"input has been truncated or that an embedded message " +
"misreported its own length.");
}
static InvalidProtocolBufferNanoException negativeSize() {
return new InvalidProtocolBufferNanoException(
"CodedInputStream encountered an embedded string or message " +
"which claimed to have negative size.");
}
static InvalidProtocolBufferNanoException malformedVarint() {
return new InvalidProtocolBufferNanoException(
"CodedInputStream encountered a malformed varint.");
}
static InvalidProtocolBufferNanoException invalidTag() {
return new InvalidProtocolBufferNanoException(
"Protocol message contained an invalid tag (zero).");
}
static InvalidProtocolBufferNanoException invalidEndTag() {
return new InvalidProtocolBufferNanoException(
"Protocol message end-group tag did not match expected tag.");
}
static InvalidProtocolBufferNanoException invalidWireType() {
return new InvalidProtocolBufferNanoException(
"Protocol message tag had invalid wire type.");
}
static InvalidProtocolBufferNanoException recursionLimitExceeded() {
return new InvalidProtocolBufferNanoException(
"Protocol message had too many levels of nesting. May be malicious. " +
"Use CodedInputStream.setRecursionLimit() to increase the depth limit.");
}
static InvalidProtocolBufferNanoException sizeLimitExceeded() {
return new InvalidProtocolBufferNanoException(
"Protocol message was too large. May be malicious. " +
"Use CodedInputStream.setSizeLimit() to increase the size limit.");
}
}
// Protocol Buffers - Google's data interchange format
// Copyright 2013 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.nano;
import java.io.IOException;
import java.util.Arrays;
/**
* Abstract interface implemented by Protocol Message objects.
*
* @author wink@google.com Wink Saville
*/
public abstract class MessageNano {
protected volatile int cachedSize = -1;
/**
* Get the number of bytes required to encode this message.
* Returns the cached size or calls getSerializedSize which
* sets the cached size. This is used internally when serializing
* so the size is only computed once. If a member is modified
* then this could be stale call getSerializedSize if in doubt.
*/
public int getCachedSize() {
if (cachedSize < 0) {
// getSerializedSize sets cachedSize
getSerializedSize();
}
return cachedSize;
}
/**
* Computes the number of bytes required to encode this message.
* The size is cached and the cached result can be retrieved
* using getCachedSize().
*/
public int getSerializedSize() {
int size = computeSerializedSize();
cachedSize = size;
return size;
}
/**
* Computes the number of bytes required to encode this message. This does not update the
* cached size.
*/
protected int computeSerializedSize() {
// This is overridden if the generated message has serialized fields.
return 0;
}
/**
* Serializes the message and writes it to {@code output}.
*
* @param output the output to receive the serialized form.
* @throws IOException if an error occurred writing to {@code output}.
*/
public void writeTo(CodedOutputByteBufferNano output) throws IOException {
// Does nothing by default. Overridden by subclasses which have data to write.
}
/**
* Parse {@code input} as a message of this type and merge it with the
* message being built.
*/
public abstract MessageNano mergeFrom(CodedInputByteBufferNano input) throws IOException;
/**
* Serialize to a byte array.
* @return byte array with the serialized data.
*/
public static final byte[] toByteArray(MessageNano msg) {
final byte[] result = new byte[msg.getSerializedSize()];
toByteArray(msg, result, 0, result.length);
return result;
}
/**
* Serialize to a byte array starting at offset through length. The
* method getSerializedSize must have been called prior to calling
* this method so the proper length is know. If an attempt to
* write more than length bytes OutOfSpaceException will be thrown
* and if length bytes are not written then IllegalStateException
* is thrown.
*/
public static final void toByteArray(MessageNano msg, byte[] data, int offset, int length) {
try {
final CodedOutputByteBufferNano output =
CodedOutputByteBufferNano.newInstance(data, offset, length);
msg.writeTo(output);
output.checkNoSpaceLeft();
} catch (IOException e) {
throw new RuntimeException("Serializing to a byte array threw an IOException "
+ "(should never happen).", e);
}
}
/**
* Parse {@code data} as a message of this type and merge it with the
* message being built.
*/
public static final <T extends MessageNano> T mergeFrom(T msg, final byte[] data)
throws InvalidProtocolBufferNanoException {
return mergeFrom(msg, data, 0, data.length);
}
/**
* Parse {@code data} as a message of this type and merge it with the
* message being built.
*/
public static final <T extends MessageNano> T mergeFrom(T msg, final byte[] data,
final int off, final int len) throws InvalidProtocolBufferNanoException {
try {
final CodedInputByteBufferNano input =
CodedInputByteBufferNano.newInstance(data, off, len);
msg.mergeFrom(input);
input.checkLastTagWas(0);
return msg;
} catch (InvalidProtocolBufferNanoException e) {
throw e;
} catch (IOException e) {
throw new RuntimeException("Reading from a byte array threw an IOException (should "
+ "never happen).");
}
}
/**
* Compares two {@code MessageNano}s and returns true if the message's are the same class and
* have serialized form equality (i.e. all of the field values are the same).
*/
public static final boolean messageNanoEquals(MessageNano a, MessageNano b) {
if (a == b) {
return true;
}
if (a == null || b == null) {
return false;
}
if (a.getClass() != b.getClass()) {
return false;
}
final int serializedSize = a.getSerializedSize();
if (b.getSerializedSize() != serializedSize) {
return false;
}
final byte[] aByteArray = new byte[serializedSize];
final byte[] bByteArray = new byte[serializedSize];
toByteArray(a, aByteArray, 0, serializedSize);
toByteArray(b, bByteArray, 0, serializedSize);
return Arrays.equals(aByteArray, bByteArray);
}
/**
* Returns a string that is (mostly) compatible with ProtoBuffer's TextFormat. Note that groups
* (which are deprecated) are not serialized with the correct field name.
*
* <p>This is implemented using reflection, so it is not especially fast nor is it guaranteed
* to find all fields if you have method removal turned on for proguard.
*/
@Override
public String toString() {
return MessageNanoPrinter.print(this);
}
}
// Protocol Buffers - Google's data interchange format
// Copyright 2013 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.nano;
import java.io.IOException;
import java.util.Arrays;
/**
* Stores unknown fields. These might be extensions or fields that the generated
* API doesn't know about yet.
*
* @author bduff@google.com (Brian Duff)
*/
final class UnknownFieldData {
final int tag;
final byte[] bytes;
UnknownFieldData(int tag, byte[] bytes) {
this.tag = tag;
this.bytes = bytes;
}
int computeSerializedSize() {
int size = 0;
size += CodedOutputByteBufferNano.computeRawVarint32Size(tag);
size += bytes.length;
return size;
}
void writeTo(CodedOutputByteBufferNano output) throws IOException {
output.writeRawVarint32(tag);
output.writeRawBytes(bytes);
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof UnknownFieldData)) {
return false;
}
UnknownFieldData other = (UnknownFieldData) o;
return tag == other.tag && Arrays.equals(bytes, other.bytes);
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + tag;
result = 31 * result + Arrays.hashCode(bytes);
return result;
}
}
// Protocol Buffers - Google's data interchange format
// Copyright 2013 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.nano;
import java.io.IOException;
/**
* This class is used internally by the Protocol Buffer library and generated
* message implementations. It is public only because those generated messages
* do not reside in the {@code protobuf} package. Others should not use this
* class directly.
*
* This class contains constants and helper functions useful for dealing with
* the Protocol Buffer wire format.
*
* @author kenton@google.com Kenton Varda
*/
public final class WireFormatNano {
// Do not allow instantiation.
private WireFormatNano() {}
static final int WIRETYPE_VARINT = 0;
static final int WIRETYPE_FIXED64 = 1;
static final int WIRETYPE_LENGTH_DELIMITED = 2;
static final int WIRETYPE_START_GROUP = 3;
static final int WIRETYPE_END_GROUP = 4;
static final int WIRETYPE_FIXED32 = 5;
static final int TAG_TYPE_BITS = 3;
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(final int tag) {
return tag & TAG_TYPE_MASK;
}
/** Given a tag value, determines the field number (the upper 29 bits). */
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(final int fieldNumber, final int wireType) {
return (fieldNumber << TAG_TYPE_BITS) | wireType;
}
public static final int EMPTY_INT_ARRAY[] = {};
public static final long EMPTY_LONG_ARRAY[] = {};
public static final float EMPTY_FLOAT_ARRAY[] = {};
public static final double EMPTY_DOUBLE_ARRAY[] = {};
public static final boolean EMPTY_BOOLEAN_ARRAY[] = {};
public static final String EMPTY_STRING_ARRAY[] = {};
public static final byte[] EMPTY_BYTES_ARRAY[] = {};
public static final byte[] EMPTY_BYTES = {};
/**
* Parses an unknown field. This implementation skips the field.
*
* <p>Generated messages will call this for unknown fields if the store_unknown_fields
* option is off.
*
* @return {@literal true} unless the tag is an end-group tag.
*/
public static boolean parseUnknownField(
final CodedInputByteBufferNano input,
final int tag) throws IOException {
return input.skipField(tag);
}
/**
* Computes the array length of a repeated field. We assume that in the common case repeated
* fields are contiguously serialized but we still correctly handle interspersed values of a
* repeated field (but with extra allocations).
*
* Rewinds to current input position before returning.
*
* @param input stream input, pointing to the byte after the first tag
* @param tag repeated field tag just read
* @return length of array
* @throws IOException
*/
public static final int getRepeatedFieldArrayLength(
final CodedInputByteBufferNano input,
final int tag) throws IOException {
int arrayLength = 1;
int startPos = input.getPosition();
input.skipField(tag);
while (input.readTag() == tag) {
input.skipField(tag);
arrayLength++;
}
input.rewindToPosition(startPos);
return arrayLength;
}
}
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