diff options
Diffstat (limited to 'javanano/src/main/java/com/google/protobuf/nano')
13 files changed, 0 insertions, 4695 deletions
diff --git a/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java b/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java deleted file mode 100644 index f3993155..00000000 --- a/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java +++ /dev/null @@ -1,683 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf.nano; - -import java.io.IOException; - -/** - * Reads and decodes protocol message fields. - * - * This class contains two kinds of methods: methods that read specific - * protocol message constructs and field types (e.g. {@link #readTag()} and - * {@link #readInt32()}) and methods that read low-level values (e.g. - * {@link #readRawVarint32()} and {@link #readRawBytes}). If you are reading - * encoded protocol messages, you should use the former methods, but if you are - * reading some other format of your own design, use the latter. - * - * @author kenton@google.com Kenton Varda - */ -public final class CodedInputByteBufferNano { - /** - * Create a new CodedInputStream wrapping the given byte array. - */ - public static CodedInputByteBufferNano newInstance(final byte[] buf) { - return newInstance(buf, 0, buf.length); - } - - /** - * Create a new CodedInputStream wrapping the given byte array slice. - */ - public static CodedInputByteBufferNano newInstance(final byte[] buf, final int off, - final int len) { - return new CodedInputByteBufferNano(buf, off, len); - } - - // ----------------------------------------------------------------- - - /** - * Attempt to read a field tag, returning zero if we have reached EOF. - * Protocol message parsers use this to read tags, since a protocol message - * may legally end wherever a tag occurs, and zero is not a valid tag number. - */ - public int readTag() throws IOException { - if (isAtEnd()) { - lastTag = 0; - return 0; - } - - lastTag = readRawVarint32(); - if (lastTag == 0) { - // If we actually read zero, that's not a valid tag. - throw InvalidProtocolBufferNanoException.invalidTag(); - } - return lastTag; - } - - /** - * Verifies that the last call to readTag() returned the given tag value. - * This is used to verify that a nested group ended with the correct - * end tag. - * - * @throws InvalidProtocolBufferNanoException {@code value} does not match the - * last tag. - */ - public void checkLastTagWas(final int value) - throws InvalidProtocolBufferNanoException { - if (lastTag != value) { - throw InvalidProtocolBufferNanoException.invalidEndTag(); - } - } - - /** - * Reads and discards a single field, given its tag value. - * - * @return {@code false} if the tag is an endgroup tag, in which case - * nothing is skipped. Otherwise, returns {@code true}. - */ - public boolean skipField(final int tag) throws IOException { - switch (WireFormatNano.getTagWireType(tag)) { - case WireFormatNano.WIRETYPE_VARINT: - readInt32(); - return true; - case WireFormatNano.WIRETYPE_FIXED64: - readRawLittleEndian64(); - return true; - case WireFormatNano.WIRETYPE_LENGTH_DELIMITED: - skipRawBytes(readRawVarint32()); - return true; - case WireFormatNano.WIRETYPE_START_GROUP: - skipMessage(); - checkLastTagWas( - WireFormatNano.makeTag(WireFormatNano.getTagFieldNumber(tag), - WireFormatNano.WIRETYPE_END_GROUP)); - return true; - case WireFormatNano.WIRETYPE_END_GROUP: - return false; - case WireFormatNano.WIRETYPE_FIXED32: - readRawLittleEndian32(); - return true; - default: - throw InvalidProtocolBufferNanoException.invalidWireType(); - } - } - - /** - * Reads and discards an entire message. This will read either until EOF - * or until an endgroup tag, whichever comes first. - */ - public void skipMessage() throws IOException { - while (true) { - final int tag = readTag(); - if (tag == 0 || !skipField(tag)) { - return; - } - } - } - - // ----------------------------------------------------------------- - - /** Read a {@code double} field value from the stream. */ - public double readDouble() throws IOException { - return Double.longBitsToDouble(readRawLittleEndian64()); - } - - /** Read a {@code float} field value from the stream. */ - public float readFloat() throws IOException { - return Float.intBitsToFloat(readRawLittleEndian32()); - } - - /** Read a {@code uint64} field value from the stream. */ - public long readUInt64() throws IOException { - return readRawVarint64(); - } - - /** Read an {@code int64} field value from the stream. */ - public long readInt64() throws IOException { - return readRawVarint64(); - } - - /** Read an {@code int32} field value from the stream. */ - public int readInt32() throws IOException { - return readRawVarint32(); - } - - /** Read a {@code fixed64} field value from the stream. */ - public long readFixed64() throws IOException { - return readRawLittleEndian64(); - } - - /** Read a {@code fixed32} field value from the stream. */ - public int readFixed32() throws IOException { - return readRawLittleEndian32(); - } - - /** Read a {@code bool} field value from the stream. */ - public boolean readBool() throws IOException { - return readRawVarint32() != 0; - } - - /** Read a {@code string} field value from the stream. */ - public String readString() throws IOException { - final int size = readRawVarint32(); - if (size <= (bufferSize - bufferPos) && size > 0) { - // Fast path: We already have the bytes in a contiguous buffer, so - // just copy directly from it. - final String result = new String(buffer, bufferPos, size, InternalNano.UTF_8); - bufferPos += size; - return result; - } else { - // Slow path: Build a byte array first then copy it. - return new String(readRawBytes(size), InternalNano.UTF_8); - } - } - - /** Read a {@code group} field value from the stream. */ - public void readGroup(final MessageNano msg, final int fieldNumber) - throws IOException { - if (recursionDepth >= recursionLimit) { - throw InvalidProtocolBufferNanoException.recursionLimitExceeded(); - } - ++recursionDepth; - msg.mergeFrom(this); - checkLastTagWas( - WireFormatNano.makeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP)); - --recursionDepth; - } - - public void readMessage(final MessageNano msg) - throws IOException { - final int length = readRawVarint32(); - if (recursionDepth >= recursionLimit) { - throw InvalidProtocolBufferNanoException.recursionLimitExceeded(); - } - final int oldLimit = pushLimit(length); - ++recursionDepth; - msg.mergeFrom(this); - checkLastTagWas(0); - --recursionDepth; - popLimit(oldLimit); - } - - /** Read a {@code bytes} field value from the stream. */ - public byte[] readBytes() throws IOException { - final int size = readRawVarint32(); - if (size <= (bufferSize - bufferPos) && size > 0) { - // Fast path: We already have the bytes in a contiguous buffer, so - // just copy directly from it. - final byte[] result = new byte[size]; - System.arraycopy(buffer, bufferPos, result, 0, size); - bufferPos += size; - return result; - } else if (size == 0) { - return WireFormatNano.EMPTY_BYTES; - } else { - // Slow path: Build a byte array first then copy it. - return readRawBytes(size); - } - } - - /** Read a {@code uint32} field value from the stream. */ - public int readUInt32() throws IOException { - return readRawVarint32(); - } - - /** - * Read an enum field value from the stream. Caller is responsible - * for converting the numeric value to an actual enum. - */ - public int readEnum() throws IOException { - return readRawVarint32(); - } - - /** Read an {@code sfixed32} field value from the stream. */ - public int readSFixed32() throws IOException { - return readRawLittleEndian32(); - } - - /** Read an {@code sfixed64} field value from the stream. */ - public long readSFixed64() throws IOException { - return readRawLittleEndian64(); - } - - /** Read an {@code sint32} field value from the stream. */ - public int readSInt32() throws IOException { - return decodeZigZag32(readRawVarint32()); - } - - /** Read an {@code sint64} field value from the stream. */ - public long readSInt64() throws IOException { - return decodeZigZag64(readRawVarint64()); - } - - // ================================================================= - - /** - * Read a raw Varint from the stream. If larger than 32 bits, discard the - * upper bits. - */ - public int readRawVarint32() throws IOException { - byte tmp = readRawByte(); - if (tmp >= 0) { - return tmp; - } - int result = tmp & 0x7f; - if ((tmp = readRawByte()) >= 0) { - result |= tmp << 7; - } else { - result |= (tmp & 0x7f) << 7; - if ((tmp = readRawByte()) >= 0) { - result |= tmp << 14; - } else { - result |= (tmp & 0x7f) << 14; - if ((tmp = readRawByte()) >= 0) { - result |= tmp << 21; - } else { - result |= (tmp & 0x7f) << 21; - result |= (tmp = readRawByte()) << 28; - if (tmp < 0) { - // Discard upper 32 bits. - for (int i = 0; i < 5; i++) { - if (readRawByte() >= 0) { - return result; - } - } - throw InvalidProtocolBufferNanoException.malformedVarint(); - } - } - } - } - return result; - } - - /** Read a raw Varint from the stream. */ - public long readRawVarint64() throws IOException { - int shift = 0; - long result = 0; - while (shift < 64) { - final byte b = readRawByte(); - result |= (long)(b & 0x7F) << shift; - if ((b & 0x80) == 0) { - return result; - } - shift += 7; - } - throw InvalidProtocolBufferNanoException.malformedVarint(); - } - - /** Read a 32-bit little-endian integer from the stream. */ - public int readRawLittleEndian32() throws IOException { - final byte b1 = readRawByte(); - final byte b2 = readRawByte(); - final byte b3 = readRawByte(); - final byte b4 = readRawByte(); - return ((b1 & 0xff) ) | - ((b2 & 0xff) << 8) | - ((b3 & 0xff) << 16) | - ((b4 & 0xff) << 24); - } - - /** Read a 64-bit little-endian integer from the stream. */ - public long readRawLittleEndian64() throws IOException { - final byte b1 = readRawByte(); - final byte b2 = readRawByte(); - final byte b3 = readRawByte(); - final byte b4 = readRawByte(); - final byte b5 = readRawByte(); - final byte b6 = readRawByte(); - final byte b7 = readRawByte(); - final byte b8 = readRawByte(); - return (((long)b1 & 0xff) ) | - (((long)b2 & 0xff) << 8) | - (((long)b3 & 0xff) << 16) | - (((long)b4 & 0xff) << 24) | - (((long)b5 & 0xff) << 32) | - (((long)b6 & 0xff) << 40) | - (((long)b7 & 0xff) << 48) | - (((long)b8 & 0xff) << 56); - } - - /** - * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers - * into values that can be efficiently encoded with varint. (Otherwise, - * negative values must be sign-extended to 64 bits to be varint encoded, - * thus always taking 10 bytes on the wire.) - * - * @param n An unsigned 32-bit integer, stored in a signed int because - * Java has no explicit unsigned support. - * @return A signed 32-bit integer. - */ - public static int decodeZigZag32(final int n) { - return (n >>> 1) ^ -(n & 1); - } - - /** - * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers - * into values that can be efficiently encoded with varint. (Otherwise, - * negative values must be sign-extended to 64 bits to be varint encoded, - * thus always taking 10 bytes on the wire.) - * - * @param n An unsigned 64-bit integer, stored in a signed int because - * Java has no explicit unsigned support. - * @return A signed 64-bit integer. - */ - public static long decodeZigZag64(final long n) { - return (n >>> 1) ^ -(n & 1); - } - - // ----------------------------------------------------------------- - - private final byte[] buffer; - private int bufferStart; - private int bufferSize; - private int bufferSizeAfterLimit; - private int bufferPos; - private int lastTag; - - /** The absolute position of the end of the current message. */ - private int currentLimit = Integer.MAX_VALUE; - - /** See setRecursionLimit() */ - private int recursionDepth; - private int recursionLimit = DEFAULT_RECURSION_LIMIT; - - /** See setSizeLimit() */ - private int sizeLimit = DEFAULT_SIZE_LIMIT; - - private static final int DEFAULT_RECURSION_LIMIT = 64; - private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB - - private CodedInputByteBufferNano(final byte[] buffer, final int off, final int len) { - this.buffer = buffer; - bufferStart = off; - bufferSize = off + len; - bufferPos = off; - } - - /** - * Set the maximum message recursion depth. In order to prevent malicious - * messages from causing stack overflows, {@code CodedInputStream} limits - * how deeply messages may be nested. The default limit is 64. - * - * @return the old limit. - */ - public int setRecursionLimit(final int limit) { - if (limit < 0) { - throw new IllegalArgumentException( - "Recursion limit cannot be negative: " + limit); - } - final int oldLimit = recursionLimit; - recursionLimit = limit; - return oldLimit; - } - - /** - * Set the maximum message size. In order to prevent malicious - * messages from exhausting memory or causing integer overflows, - * {@code CodedInputStream} limits how large a message may be. - * The default limit is 64MB. You should set this limit as small - * as you can without harming your app's functionality. Note that - * size limits only apply when reading from an {@code InputStream}, not - * when constructed around a raw byte array. - * <p> - * If you want to read several messages from a single CodedInputStream, you - * could call {@link #resetSizeCounter()} after each one to avoid hitting the - * size limit. - * - * @return the old limit. - */ - public int setSizeLimit(final int limit) { - if (limit < 0) { - throw new IllegalArgumentException( - "Size limit cannot be negative: " + limit); - } - final int oldLimit = sizeLimit; - sizeLimit = limit; - return oldLimit; - } - - /** - * Resets the current size counter to zero (see {@link #setSizeLimit(int)}). - */ - public void resetSizeCounter() { - } - - /** - * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This - * is called when descending into a length-delimited embedded message. - * - * @return the old limit. - */ - public int pushLimit(int byteLimit) throws InvalidProtocolBufferNanoException { - if (byteLimit < 0) { - throw InvalidProtocolBufferNanoException.negativeSize(); - } - byteLimit += bufferPos; - final int oldLimit = currentLimit; - if (byteLimit > oldLimit) { - throw InvalidProtocolBufferNanoException.truncatedMessage(); - } - currentLimit = byteLimit; - - recomputeBufferSizeAfterLimit(); - - return oldLimit; - } - - private void recomputeBufferSizeAfterLimit() { - bufferSize += bufferSizeAfterLimit; - final int bufferEnd = bufferSize; - if (bufferEnd > currentLimit) { - // Limit is in current buffer. - bufferSizeAfterLimit = bufferEnd - currentLimit; - bufferSize -= bufferSizeAfterLimit; - } else { - bufferSizeAfterLimit = 0; - } - } - - /** - * Discards the current limit, returning to the previous limit. - * - * @param oldLimit The old limit, as returned by {@code pushLimit}. - */ - public void popLimit(final int oldLimit) { - currentLimit = oldLimit; - recomputeBufferSizeAfterLimit(); - } - - /** - * Returns the number of bytes to be read before the current limit. - * If no limit is set, returns -1. - */ - public int getBytesUntilLimit() { - if (currentLimit == Integer.MAX_VALUE) { - return -1; - } - - final int currentAbsolutePosition = bufferPos; - return currentLimit - currentAbsolutePosition; - } - - /** - * Returns true if the stream has reached the end of the input. This is the - * case if either the end of the underlying input source has been reached or - * if the stream has reached a limit created using {@link #pushLimit(int)}. - */ - public boolean isAtEnd() { - return bufferPos == bufferSize; - } - - /** - * Get current position in buffer relative to beginning offset. - */ - public int getPosition() { - return bufferPos - bufferStart; - } - - /** - * Retrieves a subset of data in the buffer. The returned array is not backed by the original - * buffer array. - * - * @param offset the position (relative to the buffer start position) to start at. - * @param length the number of bytes to retrieve. - */ - public byte[] getData(int offset, int length) { - if (length == 0) { - return WireFormatNano.EMPTY_BYTES; - } - byte[] copy = new byte[length]; - int start = bufferStart + offset; - System.arraycopy(buffer, start, copy, 0, length); - return copy; - } - - /** - * Rewind to previous position. Cannot go forward. - */ - public void rewindToPosition(int position) { - if (position > bufferPos - bufferStart) { - throw new IllegalArgumentException( - "Position " + position + " is beyond current " + (bufferPos - bufferStart)); - } - if (position < 0) { - throw new IllegalArgumentException("Bad position " + position); - } - bufferPos = bufferStart + position; - } - - /** - * Read one byte from the input. - * - * @throws InvalidProtocolBufferNanoException The end of the stream or the current - * limit was reached. - */ - public byte readRawByte() throws IOException { - if (bufferPos == bufferSize) { - throw InvalidProtocolBufferNanoException.truncatedMessage(); - } - return buffer[bufferPos++]; - } - - /** - * Read a fixed size of bytes from the input. - * - * @throws InvalidProtocolBufferNanoException The end of the stream or the current - * limit was reached. - */ - public byte[] readRawBytes(final int size) throws IOException { - if (size < 0) { - throw InvalidProtocolBufferNanoException.negativeSize(); - } - - if (bufferPos + size > currentLimit) { - // Read to the end of the stream anyway. - skipRawBytes(currentLimit - bufferPos); - // Then fail. - throw InvalidProtocolBufferNanoException.truncatedMessage(); - } - - if (size <= bufferSize - bufferPos) { - // We have all the bytes we need already. - final byte[] bytes = new byte[size]; - System.arraycopy(buffer, bufferPos, bytes, 0, size); - bufferPos += size; - return bytes; - } else { - throw InvalidProtocolBufferNanoException.truncatedMessage(); - } - } - - /** - * Reads and discards {@code size} bytes. - * - * @throws InvalidProtocolBufferNanoException The end of the stream or the current - * limit was reached. - */ - public void skipRawBytes(final int size) throws IOException { - if (size < 0) { - throw InvalidProtocolBufferNanoException.negativeSize(); - } - - if (bufferPos + size > currentLimit) { - // Read to the end of the stream anyway. - skipRawBytes(currentLimit - bufferPos); - // Then fail. - throw InvalidProtocolBufferNanoException.truncatedMessage(); - } - - if (size <= bufferSize - bufferPos) { - // We have all the bytes we need already. - bufferPos += size; - } else { - throw InvalidProtocolBufferNanoException.truncatedMessage(); - } - } - - // Read a primitive type. - Object readPrimitiveField(int type) throws IOException { - switch (type) { - case InternalNano.TYPE_DOUBLE: - return readDouble(); - case InternalNano.TYPE_FLOAT: - return readFloat(); - case InternalNano.TYPE_INT64: - return readInt64(); - case InternalNano.TYPE_UINT64: - return readUInt64(); - case InternalNano.TYPE_INT32: - return readInt32(); - case InternalNano.TYPE_FIXED64: - return readFixed64(); - case InternalNano.TYPE_FIXED32: - return readFixed32(); - case InternalNano.TYPE_BOOL: - return readBool(); - case InternalNano.TYPE_STRING: - return readString(); - case InternalNano.TYPE_BYTES: - return readBytes(); - case InternalNano.TYPE_UINT32: - return readUInt32(); - case InternalNano.TYPE_ENUM: - return readEnum(); - case InternalNano.TYPE_SFIXED32: - return readSFixed32(); - case InternalNano.TYPE_SFIXED64: - return readSFixed64(); - case InternalNano.TYPE_SINT32: - return readSInt32(); - case InternalNano.TYPE_SINT64: - return readSInt64(); - default: - throw new IllegalArgumentException("Unknown type " + type); - } - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java b/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java deleted file mode 100644 index 322ada8e..00000000 --- a/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java +++ /dev/null @@ -1,1214 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf.nano; - -import java.io.IOException; -import java.nio.BufferOverflowException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ReadOnlyBufferException; - -/** - * Encodes and writes protocol message fields. - * - * <p>This class contains two kinds of methods: methods that write specific - * protocol message constructs and field types (e.g. {@link #writeTag} and - * {@link #writeInt32}) and methods that write low-level values (e.g. - * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are - * writing encoded protocol messages, you should use the former methods, but if - * you are writing some other format of your own design, use the latter. - * - * <p>This class is totally unsynchronized. - * - * @author kneton@google.com Kenton Varda - */ -public final class CodedOutputByteBufferNano { - /* max bytes per java UTF-16 char in UTF-8 */ - private static final int MAX_UTF8_EXPANSION = 3; - private final ByteBuffer buffer; - - private CodedOutputByteBufferNano(final byte[] buffer, final int offset, - final int length) { - this(ByteBuffer.wrap(buffer, offset, length)); - } - - private CodedOutputByteBufferNano(final ByteBuffer buffer) { - this.buffer = buffer; - this.buffer.order(ByteOrder.LITTLE_ENDIAN); - } - - /** - * Create a new {@code CodedOutputStream} that writes directly to the given - * byte array. If more bytes are written than fit in the array, - * {@link OutOfSpaceException} will be thrown. Writing directly to a flat - * array is faster than writing to an {@code OutputStream}. - */ - public static CodedOutputByteBufferNano newInstance(final byte[] flatArray) { - return newInstance(flatArray, 0, flatArray.length); - } - - /** - * Create a new {@code CodedOutputStream} that writes directly to the given - * byte array slice. If more bytes are written than fit in the slice, - * {@link OutOfSpaceException} will be thrown. Writing directly to a flat - * array is faster than writing to an {@code OutputStream}. - */ - public static CodedOutputByteBufferNano newInstance(final byte[] flatArray, - final int offset, - final int length) { - return new CodedOutputByteBufferNano(flatArray, offset, length); - } - - // ----------------------------------------------------------------- - - /** Write a {@code double} field, including tag, to the stream. */ - public void writeDouble(final int fieldNumber, final double value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); - writeDoubleNoTag(value); - } - - /** Write a {@code float} field, including tag, to the stream. */ - public void writeFloat(final int fieldNumber, final float value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); - writeFloatNoTag(value); - } - - /** Write a {@code uint64} field, including tag, to the stream. */ - public void writeUInt64(final int fieldNumber, final long value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeUInt64NoTag(value); - } - - /** Write an {@code int64} field, including tag, to the stream. */ - public void writeInt64(final int fieldNumber, final long value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeInt64NoTag(value); - } - - /** Write an {@code int32} field, including tag, to the stream. */ - public void writeInt32(final int fieldNumber, final int value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeInt32NoTag(value); - } - - /** Write a {@code fixed64} field, including tag, to the stream. */ - public void writeFixed64(final int fieldNumber, final long value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); - writeFixed64NoTag(value); - } - - /** Write a {@code fixed32} field, including tag, to the stream. */ - public void writeFixed32(final int fieldNumber, final int value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); - writeFixed32NoTag(value); - } - - /** Write a {@code bool} field, including tag, to the stream. */ - public void writeBool(final int fieldNumber, final boolean value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeBoolNoTag(value); - } - - /** Write a {@code string} field, including tag, to the stream. */ - public void writeString(final int fieldNumber, final String value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); - writeStringNoTag(value); - } - - /** Write a {@code group} field, including tag, to the stream. */ - public void writeGroup(final int fieldNumber, final MessageNano value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_START_GROUP); - writeGroupNoTag(value); - writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP); - } - - /** Write an embedded message field, including tag, to the stream. */ - public void writeMessage(final int fieldNumber, final MessageNano value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); - writeMessageNoTag(value); - } - - /** Write a {@code bytes} field, including tag, to the stream. */ - public void writeBytes(final int fieldNumber, final byte[] value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); - writeBytesNoTag(value); - } - - /** Write a {@code uint32} field, including tag, to the stream. */ - public void writeUInt32(final int fieldNumber, final int value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeUInt32NoTag(value); - } - - /** - * Write an enum field, including tag, to the stream. Caller is responsible - * for converting the enum value to its numeric value. - */ - public void writeEnum(final int fieldNumber, final int value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeEnumNoTag(value); - } - - /** Write an {@code sfixed32} field, including tag, to the stream. */ - public void writeSFixed32(final int fieldNumber, final int value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED32); - writeSFixed32NoTag(value); - } - - /** Write an {@code sfixed64} field, including tag, to the stream. */ - public void writeSFixed64(final int fieldNumber, final long value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_FIXED64); - writeSFixed64NoTag(value); - } - - /** Write an {@code sint32} field, including tag, to the stream. */ - public void writeSInt32(final int fieldNumber, final int value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeSInt32NoTag(value); - } - - /** Write an {@code sint64} field, including tag, to the stream. */ - public void writeSInt64(final int fieldNumber, final long value) - throws IOException { - writeTag(fieldNumber, WireFormatNano.WIRETYPE_VARINT); - writeSInt64NoTag(value); - } - - /** - * Write a MessageSet extension field to the stream. For historical reasons, - * the wire format differs from normal fields. - */ -// public void writeMessageSetExtension(final int fieldNumber, -// final MessageMicro value) -// throws IOException { -// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP); -// writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber); -// writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value); -// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP); -// } - - /** - * Write an unparsed MessageSet extension field to the stream. For - * historical reasons, the wire format differs from normal fields. - */ -// public void writeRawMessageSetExtension(final int fieldNumber, -// final ByteStringMicro value) -// throws IOException { -// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP); -// writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber); -// writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value); -// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP); -// } - - // ----------------------------------------------------------------- - - /** Write a {@code double} field to the stream. */ - public void writeDoubleNoTag(final double value) throws IOException { - writeRawLittleEndian64(Double.doubleToLongBits(value)); - } - - /** Write a {@code float} field to the stream. */ - public void writeFloatNoTag(final float value) throws IOException { - writeRawLittleEndian32(Float.floatToIntBits(value)); - } - - /** Write a {@code uint64} field to the stream. */ - public void writeUInt64NoTag(final long value) throws IOException { - writeRawVarint64(value); - } - - /** Write an {@code int64} field to the stream. */ - public void writeInt64NoTag(final long value) throws IOException { - writeRawVarint64(value); - } - - /** Write an {@code int32} field to the stream. */ - public void writeInt32NoTag(final int value) throws IOException { - if (value >= 0) { - writeRawVarint32(value); - } else { - // Must sign-extend. - writeRawVarint64(value); - } - } - - /** Write a {@code fixed64} field to the stream. */ - public void writeFixed64NoTag(final long value) throws IOException { - writeRawLittleEndian64(value); - } - - /** Write a {@code fixed32} field to the stream. */ - public void writeFixed32NoTag(final int value) throws IOException { - writeRawLittleEndian32(value); - } - - /** Write a {@code bool} field to the stream. */ - public void writeBoolNoTag(final boolean value) throws IOException { - writeRawByte(value ? 1 : 0); - } - - /** Write a {@code string} field to the stream. */ - public void writeStringNoTag(final String value) throws IOException { - // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()), - // and at most 3 times of it. Optimize for the case where we know this length results in a - // constant varint length - saves measuring length of the string. - try { - final int minLengthVarIntSize = computeRawVarint32Size(value.length()); - final int maxLengthVarIntSize = computeRawVarint32Size(value.length() * MAX_UTF8_EXPANSION); - if (minLengthVarIntSize == maxLengthVarIntSize) { - int oldPosition = buffer.position(); - // Buffer.position, when passed a position that is past its limit, throws - // IllegalArgumentException, and this class is documented to throw - // OutOfSpaceException instead. - if (buffer.remaining() < minLengthVarIntSize) { - throw new OutOfSpaceException(oldPosition + minLengthVarIntSize, buffer.limit()); - } - buffer.position(oldPosition + minLengthVarIntSize); - encode(value, buffer); - int newPosition = buffer.position(); - buffer.position(oldPosition); - writeRawVarint32(newPosition - oldPosition - minLengthVarIntSize); - buffer.position(newPosition); - } else { - writeRawVarint32(encodedLength(value)); - encode(value, buffer); - } - } catch (BufferOverflowException e) { - final OutOfSpaceException outOfSpaceException = new OutOfSpaceException(buffer.position(), - buffer.limit()); - outOfSpaceException.initCause(e); - throw outOfSpaceException; - } - } - - // These UTF-8 handling methods are copied from Guava's Utf8 class. - /** - * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string, - * this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in - * both time and space. - * - * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired - * surrogates) - */ - private static int encodedLength(CharSequence sequence) { - // Warning to maintainers: this implementation is highly optimized. - int utf16Length = sequence.length(); - int utf8Length = utf16Length; - int i = 0; - - // This loop optimizes for pure ASCII. - while (i < utf16Length && sequence.charAt(i) < 0x80) { - i++; - } - - // This loop optimizes for chars less than 0x800. - for (; i < utf16Length; i++) { - char c = sequence.charAt(i); - if (c < 0x800) { - utf8Length += ((0x7f - c) >>> 31); // branch free! - } else { - utf8Length += encodedLengthGeneral(sequence, i); - break; - } - } - - if (utf8Length < utf16Length) { - // Necessary and sufficient condition for overflow because of maximum 3x expansion - throw new IllegalArgumentException("UTF-8 length does not fit in int: " - + (utf8Length + (1L << 32))); - } - return utf8Length; - } - - private static int encodedLengthGeneral(CharSequence sequence, int start) { - int utf16Length = sequence.length(); - int utf8Length = 0; - for (int i = start; i < utf16Length; i++) { - char c = sequence.charAt(i); - if (c < 0x800) { - utf8Length += (0x7f - c) >>> 31; // branch free! - } else { - utf8Length += 2; - // jdk7+: if (Character.isSurrogate(c)) { - if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) { - // Check that we have a well-formed surrogate pair. - int cp = Character.codePointAt(sequence, i); - if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) { - throw new IllegalArgumentException("Unpaired surrogate at index " + i); - } - i++; - } - } - } - return utf8Length; - } - - /** - * Encodes {@code sequence} into UTF-8, in {@code byteBuffer}. For a string, this method is - * equivalent to {@code buffer.put(string.getBytes(UTF_8))}, but is more efficient in both time - * and space. Bytes are written starting at the current position. This method requires paired - * surrogates, and therefore does not support chunking. - * - * <p>To ensure sufficient space in the output buffer, either call {@link #encodedLength} to - * compute the exact amount needed, or leave room for {@code 3 * sequence.length()}, which is the - * largest possible number of bytes that any input can be encoded to. - * - * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired - * surrogates) - * @throws BufferOverflowException if {@code sequence} encoded in UTF-8 does not fit in - * {@code byteBuffer}'s remaining space. - * @throws ReadOnlyBufferException if {@code byteBuffer} is a read-only buffer. - */ - private static void encode(CharSequence sequence, ByteBuffer byteBuffer) { - if (byteBuffer.isReadOnly()) { - throw new ReadOnlyBufferException(); - } else if (byteBuffer.hasArray()) { - try { - int encoded = encode(sequence, - byteBuffer.array(), - byteBuffer.arrayOffset() + byteBuffer.position(), - byteBuffer.remaining()); - byteBuffer.position(encoded - byteBuffer.arrayOffset()); - } catch (ArrayIndexOutOfBoundsException e) { - BufferOverflowException boe = new BufferOverflowException(); - boe.initCause(e); - throw boe; - } - } else { - encodeDirect(sequence, byteBuffer); - } - } - - private static void encodeDirect(CharSequence sequence, ByteBuffer byteBuffer) { - int utf16Length = sequence.length(); - for (int i = 0; i < utf16Length; i++) { - final char c = sequence.charAt(i); - if (c < 0x80) { // ASCII - byteBuffer.put((byte) c); - } else if (c < 0x800) { // 11 bits, two UTF-8 bytes - byteBuffer.put((byte) ((0xF << 6) | (c >>> 6))); - byteBuffer.put((byte) (0x80 | (0x3F & c))); - } else if (c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) { - // Maximium single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes - byteBuffer.put((byte) ((0xF << 5) | (c >>> 12))); - byteBuffer.put((byte) (0x80 | (0x3F & (c >>> 6)))); - byteBuffer.put((byte) (0x80 | (0x3F & c))); - } else { - final char low; - if (i + 1 == sequence.length() - || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) { - throw new IllegalArgumentException("Unpaired surrogate at index " + (i - 1)); - } - int codePoint = Character.toCodePoint(c, low); - byteBuffer.put((byte) ((0xF << 4) | (codePoint >>> 18))); - byteBuffer.put((byte) (0x80 | (0x3F & (codePoint >>> 12)))); - byteBuffer.put((byte) (0x80 | (0x3F & (codePoint >>> 6)))); - byteBuffer.put((byte) (0x80 | (0x3F & codePoint))); - } - } - } - - private static int encode(CharSequence sequence, byte[] bytes, int offset, int length) { - int utf16Length = sequence.length(); - int j = offset; - int i = 0; - int limit = offset + length; - // Designed to take advantage of - // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination - for (char c; i < utf16Length && i + j < limit && (c = sequence.charAt(i)) < 0x80; i++) { - bytes[j + i] = (byte) c; - } - if (i == utf16Length) { - return j + utf16Length; - } - j += i; - for (char c; i < utf16Length; i++) { - c = sequence.charAt(i); - if (c < 0x80 && j < limit) { - bytes[j++] = (byte) c; - } else if (c < 0x800 && j <= limit - 2) { // 11 bits, two UTF-8 bytes - bytes[j++] = (byte) ((0xF << 6) | (c >>> 6)); - bytes[j++] = (byte) (0x80 | (0x3F & c)); - } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && j <= limit - 3) { - // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes - bytes[j++] = (byte) ((0xF << 5) | (c >>> 12)); - bytes[j++] = (byte) (0x80 | (0x3F & (c >>> 6))); - bytes[j++] = (byte) (0x80 | (0x3F & c)); - } else if (j <= limit - 4) { - // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8 bytes - final char low; - if (i + 1 == sequence.length() - || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) { - throw new IllegalArgumentException("Unpaired surrogate at index " + (i - 1)); - } - int codePoint = Character.toCodePoint(c, low); - bytes[j++] = (byte) ((0xF << 4) | (codePoint >>> 18)); - bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 12))); - bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 6))); - bytes[j++] = (byte) (0x80 | (0x3F & codePoint)); - } else { - throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j); - } - } - return j; - } - - // End guava UTF-8 methods - - - /** Write a {@code group} field to the stream. */ - public void writeGroupNoTag(final MessageNano value) throws IOException { - value.writeTo(this); - } - - /** Write an embedded message field to the stream. */ - public void writeMessageNoTag(final MessageNano value) throws IOException { - writeRawVarint32(value.getCachedSize()); - value.writeTo(this); - } - - /** Write a {@code bytes} field to the stream. */ - public void writeBytesNoTag(final byte[] value) throws IOException { - writeRawVarint32(value.length); - writeRawBytes(value); - } - - /** Write a {@code uint32} field to the stream. */ - public void writeUInt32NoTag(final int value) throws IOException { - writeRawVarint32(value); - } - - /** - * Write an enum field to the stream. Caller is responsible - * for converting the enum value to its numeric value. - */ - public void writeEnumNoTag(final int value) throws IOException { - writeRawVarint32(value); - } - - /** Write an {@code sfixed32} field to the stream. */ - public void writeSFixed32NoTag(final int value) throws IOException { - writeRawLittleEndian32(value); - } - - /** Write an {@code sfixed64} field to the stream. */ - public void writeSFixed64NoTag(final long value) throws IOException { - writeRawLittleEndian64(value); - } - - /** Write an {@code sint32} field to the stream. */ - public void writeSInt32NoTag(final int value) throws IOException { - writeRawVarint32(encodeZigZag32(value)); - } - - /** Write an {@code sint64} field to the stream. */ - public void writeSInt64NoTag(final long value) throws IOException { - writeRawVarint64(encodeZigZag64(value)); - } - - // ================================================================= - - /** - * Compute the number of bytes that would be needed to encode a - * {@code double} field, including tag. - */ - public static int computeDoubleSize(final int fieldNumber, - final double value) { - return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code float} field, including tag. - */ - public static int computeFloatSize(final int fieldNumber, final float value) { - return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code uint64} field, including tag. - */ - public static int computeUInt64Size(final int fieldNumber, final long value) { - return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code int64} field, including tag. - */ - public static int computeInt64Size(final int fieldNumber, final long value) { - return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code int32} field, including tag. - */ - public static int computeInt32Size(final int fieldNumber, final int value) { - return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code fixed64} field, including tag. - */ - public static int computeFixed64Size(final int fieldNumber, - final long value) { - return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code fixed32} field, including tag. - */ - public static int computeFixed32Size(final int fieldNumber, - final int value) { - return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code bool} field, including tag. - */ - public static int computeBoolSize(final int fieldNumber, - final boolean value) { - return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code string} field, including tag. - */ - public static int computeStringSize(final int fieldNumber, - final String value) { - return computeTagSize(fieldNumber) + computeStringSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code group} field, including tag. - */ - public static int computeGroupSize(final int fieldNumber, - final MessageNano value) { - return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * embedded message field, including tag. - */ - public static int computeMessageSize(final int fieldNumber, - final MessageNano value) { - return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code bytes} field, including tag. - */ - public static int computeBytesSize(final int fieldNumber, - final byte[] value) { - return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code uint32} field, including tag. - */ - public static int computeUInt32Size(final int fieldNumber, final int value) { - return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * enum field, including tag. Caller is responsible for converting the - * enum value to its numeric value. - */ - public static int computeEnumSize(final int fieldNumber, final int value) { - return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sfixed32} field, including tag. - */ - public static int computeSFixed32Size(final int fieldNumber, - final int value) { - return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sfixed64} field, including tag. - */ - public static int computeSFixed64Size(final int fieldNumber, - final long value) { - return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sint32} field, including tag. - */ - public static int computeSInt32Size(final int fieldNumber, final int value) { - return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sint64} field, including tag. - */ - public static int computeSInt64Size(final int fieldNumber, final long value) { - return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value); - } - - /** - * Compute the number of bytes that would be needed to encode a - * MessageSet extension to the stream. For historical reasons, - * the wire format differs from normal fields. - */ -// public static int computeMessageSetExtensionSize( -// final int fieldNumber, final MessageMicro value) { -// return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 + -// computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) + -// computeMessageSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value); -// } - - /** - * Compute the number of bytes that would be needed to encode an - * unparsed MessageSet extension field to the stream. For - * historical reasons, the wire format differs from normal fields. - */ -// public static int computeRawMessageSetExtensionSize( -// final int fieldNumber, final ByteStringMicro value) { -// return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 + -// computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) + -// computeBytesSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value); -// } - - // ----------------------------------------------------------------- - - /** - * Compute the number of bytes that would be needed to encode a - * {@code double} field, including tag. - */ - public static int computeDoubleSizeNoTag(final double value) { - return LITTLE_ENDIAN_64_SIZE; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code float} field, including tag. - */ - public static int computeFloatSizeNoTag(final float value) { - return LITTLE_ENDIAN_32_SIZE; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code uint64} field, including tag. - */ - public static int computeUInt64SizeNoTag(final long value) { - return computeRawVarint64Size(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code int64} field, including tag. - */ - public static int computeInt64SizeNoTag(final long value) { - return computeRawVarint64Size(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code int32} field, including tag. - */ - public static int computeInt32SizeNoTag(final int value) { - if (value >= 0) { - return computeRawVarint32Size(value); - } else { - // Must sign-extend. - return 10; - } - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code fixed64} field. - */ - public static int computeFixed64SizeNoTag(final long value) { - return LITTLE_ENDIAN_64_SIZE; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code fixed32} field. - */ - public static int computeFixed32SizeNoTag(final int value) { - return LITTLE_ENDIAN_32_SIZE; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code bool} field. - */ - public static int computeBoolSizeNoTag(final boolean value) { - return 1; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code string} field. - */ - public static int computeStringSizeNoTag(final String value) { - final int length = encodedLength(value); - return computeRawVarint32Size(length) + length; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code group} field. - */ - public static int computeGroupSizeNoTag(final MessageNano value) { - return value.getSerializedSize(); - } - - /** - * Compute the number of bytes that would be needed to encode an embedded - * message field. - */ - public static int computeMessageSizeNoTag(final MessageNano value) { - final int size = value.getSerializedSize(); - return computeRawVarint32Size(size) + size; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code bytes} field. - */ - public static int computeBytesSizeNoTag(final byte[] value) { - return computeRawVarint32Size(value.length) + value.length; - } - - /** - * Compute the number of bytes that would be needed to encode a - * {@code uint32} field. - */ - public static int computeUInt32SizeNoTag(final int value) { - return computeRawVarint32Size(value); - } - - /** - * Compute the number of bytes that would be needed to encode an enum field. - * Caller is responsible for converting the enum value to its numeric value. - */ - public static int computeEnumSizeNoTag(final int value) { - return computeRawVarint32Size(value); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sfixed32} field. - */ - public static int computeSFixed32SizeNoTag(final int value) { - return LITTLE_ENDIAN_32_SIZE; - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sfixed64} field. - */ - public static int computeSFixed64SizeNoTag(final long value) { - return LITTLE_ENDIAN_64_SIZE; - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sint32} field. - */ - public static int computeSInt32SizeNoTag(final int value) { - return computeRawVarint32Size(encodeZigZag32(value)); - } - - /** - * Compute the number of bytes that would be needed to encode an - * {@code sint64} field. - */ - public static int computeSInt64SizeNoTag(final long value) { - return computeRawVarint64Size(encodeZigZag64(value)); - } - - // ================================================================= - - /** - * If writing to a flat array, return the space left in the array. - * Otherwise, throws {@code UnsupportedOperationException}. - */ - public int spaceLeft() { - return buffer.remaining(); - } - - /** - * Verifies that {@link #spaceLeft()} returns zero. It's common to create - * a byte array that is exactly big enough to hold a message, then write to - * it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()} - * after writing verifies that the message was actually as big as expected, - * which can help catch bugs. - */ - public void checkNoSpaceLeft() { - if (spaceLeft() != 0) { - throw new IllegalStateException( - "Did not write as much data as expected."); - } - } - - /** - * Returns the position within the internal buffer. - */ - public int position() { - return buffer.position(); - } - - /** - * Resets the position within the internal buffer to zero. - * - * @see #position - * @see #spaceLeft - */ - public void reset() { - buffer.clear(); - } - - /** - * If you create a CodedOutputStream around a simple flat array, you must - * not attempt to write more bytes than the array has space. Otherwise, - * this exception will be thrown. - */ - public static class OutOfSpaceException extends IOException { - private static final long serialVersionUID = -6947486886997889499L; - - OutOfSpaceException(int position, int limit) { - super("CodedOutputStream was writing to a flat byte array and ran " + - "out of space (pos " + position + " limit " + limit + ")."); - } - } - - /** Write a single byte. */ - public void writeRawByte(final byte value) throws IOException { - if (!buffer.hasRemaining()) { - // We're writing to a single buffer. - throw new OutOfSpaceException(buffer.position(), buffer.limit()); - } - - buffer.put(value); - } - - /** Write a single byte, represented by an integer value. */ - public void writeRawByte(final int value) throws IOException { - writeRawByte((byte) value); - } - - /** Write an array of bytes. */ - public void writeRawBytes(final byte[] value) throws IOException { - writeRawBytes(value, 0, value.length); - } - - /** Write part of an array of bytes. */ - public void writeRawBytes(final byte[] value, int offset, int length) - throws IOException { - if (buffer.remaining() >= length) { - buffer.put(value, offset, length); - } else { - // We're writing to a single buffer. - throw new OutOfSpaceException(buffer.position(), buffer.limit()); - } - } - - /** Encode and write a tag. */ - public void writeTag(final int fieldNumber, final int wireType) - throws IOException { - writeRawVarint32(WireFormatNano.makeTag(fieldNumber, wireType)); - } - - /** Compute the number of bytes that would be needed to encode a tag. */ - public static int computeTagSize(final int fieldNumber) { - return computeRawVarint32Size(WireFormatNano.makeTag(fieldNumber, 0)); - } - - /** - * Encode and write a varint. {@code value} is treated as - * unsigned, so it won't be sign-extended if negative. - */ - public void writeRawVarint32(int value) throws IOException { - while (true) { - if ((value & ~0x7F) == 0) { - writeRawByte(value); - return; - } else { - writeRawByte((value & 0x7F) | 0x80); - value >>>= 7; - } - } - } - - /** - * Compute the number of bytes that would be needed to encode a varint. - * {@code value} is treated as unsigned, so it won't be sign-extended if - * negative. - */ - public static int computeRawVarint32Size(final int value) { - if ((value & (0xffffffff << 7)) == 0) return 1; - if ((value & (0xffffffff << 14)) == 0) return 2; - if ((value & (0xffffffff << 21)) == 0) return 3; - if ((value & (0xffffffff << 28)) == 0) return 4; - return 5; - } - - /** Encode and write a varint. */ - public void writeRawVarint64(long value) throws IOException { - while (true) { - if ((value & ~0x7FL) == 0) { - writeRawByte((int)value); - return; - } else { - writeRawByte(((int)value & 0x7F) | 0x80); - value >>>= 7; - } - } - } - - /** Compute the number of bytes that would be needed to encode a varint. */ - public static int computeRawVarint64Size(final long value) { - if ((value & (0xffffffffffffffffL << 7)) == 0) return 1; - if ((value & (0xffffffffffffffffL << 14)) == 0) return 2; - if ((value & (0xffffffffffffffffL << 21)) == 0) return 3; - if ((value & (0xffffffffffffffffL << 28)) == 0) return 4; - if ((value & (0xffffffffffffffffL << 35)) == 0) return 5; - if ((value & (0xffffffffffffffffL << 42)) == 0) return 6; - if ((value & (0xffffffffffffffffL << 49)) == 0) return 7; - if ((value & (0xffffffffffffffffL << 56)) == 0) return 8; - if ((value & (0xffffffffffffffffL << 63)) == 0) return 9; - return 10; - } - - /** Write a little-endian 32-bit integer. */ - public void writeRawLittleEndian32(final int value) throws IOException { - if (buffer.remaining() < 4) { - throw new OutOfSpaceException(buffer.position(), buffer.limit()); - } - buffer.putInt(value); - } - - public static final int LITTLE_ENDIAN_32_SIZE = 4; - - /** Write a little-endian 64-bit integer. */ - public void writeRawLittleEndian64(final long value) throws IOException { - if (buffer.remaining() < 8) { - throw new OutOfSpaceException(buffer.position(), buffer.limit()); - } - buffer.putLong(value); - } - - public static final int LITTLE_ENDIAN_64_SIZE = 8; - - /** - * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers - * into values that can be efficiently encoded with varint. (Otherwise, - * negative values must be sign-extended to 64 bits to be varint encoded, - * thus always taking 10 bytes on the wire.) - * - * @param n A signed 32-bit integer. - * @return An unsigned 32-bit integer, stored in a signed int because - * Java has no explicit unsigned support. - */ - public static int encodeZigZag32(final int n) { - // Note: the right-shift must be arithmetic - return (n << 1) ^ (n >> 31); - } - - /** - * Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers - * into values that can be efficiently encoded with varint. (Otherwise, - * negative values must be sign-extended to 64 bits to be varint encoded, - * thus always taking 10 bytes on the wire.) - * - * @param n A signed 64-bit integer. - * @return An unsigned 64-bit integer, stored in a signed int because - * Java has no explicit unsigned support. - */ - public static long encodeZigZag64(final long n) { - // Note: the right-shift must be arithmetic - return (n << 1) ^ (n >> 63); - } - - static int computeFieldSize(int number, int type, Object object) { - switch (type) { - case InternalNano.TYPE_BOOL: - return computeBoolSize(number, (Boolean) object); - case InternalNano.TYPE_BYTES: - return computeBytesSize(number, (byte[]) object); - case InternalNano.TYPE_STRING: - return computeStringSize(number, (String) object); - case InternalNano.TYPE_FLOAT: - return computeFloatSize(number, (Float) object); - case InternalNano.TYPE_DOUBLE: - return computeDoubleSize(number, (Double) object); - case InternalNano.TYPE_ENUM: - return computeEnumSize(number, (Integer) object); - case InternalNano.TYPE_FIXED32: - return computeFixed32Size(number, (Integer) object); - case InternalNano.TYPE_INT32: - return computeInt32Size(number, (Integer) object); - case InternalNano.TYPE_UINT32: - return computeUInt32Size(number, (Integer) object); - case InternalNano.TYPE_SINT32: - return computeSInt32Size(number, (Integer) object); - case InternalNano.TYPE_SFIXED32: - return computeSFixed32Size(number, (Integer) object); - case InternalNano.TYPE_INT64: - return computeInt64Size(number, (Long) object); - case InternalNano.TYPE_UINT64: - return computeUInt64Size(number, (Long) object); - case InternalNano.TYPE_SINT64: - return computeSInt64Size(number, (Long) object); - case InternalNano.TYPE_FIXED64: - return computeFixed64Size(number, (Long) object); - case InternalNano.TYPE_SFIXED64: - return computeSFixed64Size(number, (Long) object); - case InternalNano.TYPE_MESSAGE: - return computeMessageSize(number, (MessageNano) object); - case InternalNano.TYPE_GROUP: - return computeGroupSize(number, (MessageNano) object); - default: - throw new IllegalArgumentException("Unknown type: " + type); - } - } - - void writeField(int number, int type, Object value) - throws IOException { - switch (type) { - case InternalNano.TYPE_DOUBLE: - Double doubleValue = (Double) value; - writeDouble(number, doubleValue); - break; - case InternalNano.TYPE_FLOAT: - Float floatValue = (Float) value; - writeFloat(number, floatValue); - break; - case InternalNano.TYPE_INT64: - Long int64Value = (Long) value; - writeInt64(number, int64Value); - break; - case InternalNano.TYPE_UINT64: - Long uint64Value = (Long) value; - writeUInt64(number, uint64Value); - break; - case InternalNano.TYPE_INT32: - Integer int32Value = (Integer) value; - writeInt32(number, int32Value); - break; - case InternalNano.TYPE_FIXED64: - Long fixed64Value = (Long) value; - writeFixed64(number, fixed64Value); - break; - case InternalNano.TYPE_FIXED32: - Integer fixed32Value = (Integer) value; - writeFixed32(number, fixed32Value); - break; - case InternalNano.TYPE_BOOL: - Boolean boolValue = (Boolean) value; - writeBool(number, boolValue); - break; - case InternalNano.TYPE_STRING: - String stringValue = (String) value; - writeString(number, stringValue); - break; - case InternalNano.TYPE_BYTES: - byte[] bytesValue = (byte[]) value; - writeBytes(number, bytesValue); - break; - case InternalNano.TYPE_UINT32: - Integer uint32Value = (Integer) value; - writeUInt32(number, uint32Value); - break; - case InternalNano.TYPE_ENUM: - Integer enumValue = (Integer) value; - writeEnum(number, enumValue); - break; - case InternalNano.TYPE_SFIXED32: - Integer sfixed32Value = (Integer) value; - writeSFixed32(number, sfixed32Value); - break; - case InternalNano.TYPE_SFIXED64: - Long sfixed64Value = (Long) value; - writeSFixed64(number, sfixed64Value); - break; - case InternalNano.TYPE_SINT32: - Integer sint32Value = (Integer) value; - writeSInt32(number, sint32Value); - break; - case InternalNano.TYPE_SINT64: - Long sint64Value = (Long) value; - writeSInt64(number, sint64Value); - break; - case InternalNano.TYPE_MESSAGE: - MessageNano messageValue = (MessageNano) value; - writeMessage(number, messageValue); - break; - case InternalNano.TYPE_GROUP: - MessageNano groupValue = (MessageNano) value; - writeGroup(number, groupValue); - break; - default: - throw new IOException("Unknown type: " + type); - } - } - -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java b/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java deleted file mode 100644 index 87973d76..00000000 --- a/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java +++ /dev/null @@ -1,169 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -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; - } - - @Override - public M clone() throws CloneNotSupportedException { - M cloned = (M) super.clone(); - InternalNano.cloneUnknownFieldData(this, cloned); - return cloned; - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/Extension.java b/javanano/src/main/java/com/google/protobuf/nano/Extension.java deleted file mode 100644 index c458f9b1..00000000 --- a/javanano/src/main/java/com/google/protobuf/nano/Extension.java +++ /dev/null @@ -1,706 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf.nano; - -import java.io.IOException; -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.List; - -/** - * Represents an extension. - * - * @author bduff@google.com (Brian Duff) - * @author maxtroy@google.com (Max Cai) - * @param <M> the type of the extendable message this extension is for. - * @param <T> the Java type of the extension; see {@link #clazz}. - */ -public class Extension<M extends ExtendableMessageNano<M>, T> { - - /* - * Because we typically only define message-typed extensions, the Extension class hierarchy is - * designed as follows, to allow a big amount of code in this file to be removed by ProGuard: - * - * Extension // ready to use for message/group typed extensions - * Δ - * | - * PrimitiveExtension // for primitive/enum typed extensions - */ - - public static final int TYPE_DOUBLE = InternalNano.TYPE_DOUBLE; - public static final int TYPE_FLOAT = InternalNano.TYPE_FLOAT; - public static final int TYPE_INT64 = InternalNano.TYPE_INT64; - public static final int TYPE_UINT64 = InternalNano.TYPE_UINT64; - public static final int TYPE_INT32 = InternalNano.TYPE_INT32; - public static final int TYPE_FIXED64 = InternalNano.TYPE_FIXED64; - public static final int TYPE_FIXED32 = InternalNano.TYPE_FIXED32; - public static final int TYPE_BOOL = InternalNano.TYPE_BOOL; - public static final int TYPE_STRING = InternalNano.TYPE_STRING; - public static final int TYPE_GROUP = InternalNano.TYPE_GROUP; - public static final int TYPE_MESSAGE = InternalNano.TYPE_MESSAGE; - public static final int TYPE_BYTES = InternalNano.TYPE_BYTES; - public static final int TYPE_UINT32 = InternalNano.TYPE_UINT32; - public static final int TYPE_ENUM = InternalNano.TYPE_ENUM; - public static final int TYPE_SFIXED32 = InternalNano.TYPE_SFIXED32; - public static final int TYPE_SFIXED64 = InternalNano.TYPE_SFIXED64; - public static final int TYPE_SINT32 = InternalNano.TYPE_SINT32; - public static final int TYPE_SINT64 = InternalNano.TYPE_SINT64; - - /** - * Creates an {@code Extension} of the given message type and tag number. - * Should be used by the generated code only. - * - * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP} - * @deprecated use {@link #createMessageTyped(int, Class, long)} instead. - */ - @Deprecated - public static <M extends ExtendableMessageNano<M>, T extends MessageNano> - Extension<M, T> createMessageTyped(int type, Class<T> clazz, int tag) { - return new Extension<M, T>(type, clazz, tag, false); - } - - // Note: these create...() methods take a long for the tag parameter, - // because tags are represented as unsigned ints, and these values exist - // in generated code as long values. However, they can fit in 32-bits, so - // it's safe to cast them to int without loss of precision. - - /** - * Creates an {@code Extension} of the given message type and tag number. - * Should be used by the generated code only. - * - * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP} - */ - public static <M extends ExtendableMessageNano<M>, T extends MessageNano> - Extension<M, T> createMessageTyped(int type, Class<T> clazz, long tag) { - return new Extension<M, T>(type, clazz, (int) tag, false); - } - - /** - * Creates a repeated {@code Extension} of the given message type and tag number. - * Should be used by the generated code only. - * - * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP} - */ - public static <M extends ExtendableMessageNano<M>, T extends MessageNano> - Extension<M, T[]> createRepeatedMessageTyped(int type, Class<T[]> clazz, long tag) { - return new Extension<M, T[]>(type, clazz, (int) tag, true); - } - - /** - * Creates an {@code Extension} of the given primitive type and tag number. - * Should be used by the generated code only. - * - * @param type one of {@code TYPE_*}, except {@link #TYPE_MESSAGE} and {@link #TYPE_GROUP} - * @param clazz the boxed Java type of this extension - */ - public static <M extends ExtendableMessageNano<M>, T> - Extension<M, T> createPrimitiveTyped(int type, Class<T> clazz, long tag) { - return new PrimitiveExtension<M, T>(type, clazz, (int) tag, false, 0, 0); - } - - /** - * Creates a repeated {@code Extension} of the given primitive type and tag number. - * Should be used by the generated code only. - * - * @param type one of {@code TYPE_*}, except {@link #TYPE_MESSAGE} and {@link #TYPE_GROUP} - * @param clazz the Java array type of this extension, with an unboxed component type - */ - public static <M extends ExtendableMessageNano<M>, T> - Extension<M, T> createRepeatedPrimitiveTyped( - int type, Class<T> clazz, long tag, long nonPackedTag, long packedTag) { - return new PrimitiveExtension<M, T>(type, clazz, (int) tag, true, - (int) nonPackedTag, (int) packedTag); - } - - /** - * Protocol Buffer type of this extension; one of the {@code TYPE_} constants. - */ - protected final int type; - - /** - * Java type of this extension. For a singular extension, this is the boxed Java type for the - * Protocol Buffer {@link #type}; for a repeated extension, this is an array type whose - * component type is the unboxed Java type for {@link #type}. For example, for a singular - * {@code int32}/{@link #TYPE_INT32} extension, this equals {@code Integer.class}; for a - * repeated {@code int32} extension, this equals {@code int[].class}. - */ - protected final Class<T> clazz; - - /** - * Tag number of this extension. The data should be viewed as an unsigned 32-bit value. - */ - public final int tag; - - /** - * Whether this extension is repeated. - */ - protected final boolean repeated; - - private Extension(int type, Class<T> clazz, int tag, boolean repeated) { - this.type = type; - this.clazz = clazz; - this.tag = tag; - this.repeated = repeated; - } - - /** - * Returns the value of this extension stored in the given list of unknown fields, or - * {@code null} if no unknown fields matches this extension. - * - * @param unknownFields a list of {@link UnknownFieldData}. All of the elements must have a tag - * that matches this Extension's tag. - * - */ - final T getValueFrom(List<UnknownFieldData> unknownFields) { - if (unknownFields == null) { - return null; - } - return repeated ? getRepeatedValueFrom(unknownFields) : getSingularValueFrom(unknownFields); - } - - private T getRepeatedValueFrom(List<UnknownFieldData> unknownFields) { - // For repeated extensions, read all matching unknown fields in their original order. - List<Object> resultList = new ArrayList<Object>(); - for (int i = 0; i < unknownFields.size(); i++) { - UnknownFieldData data = unknownFields.get(i); - if (data.bytes.length != 0) { - readDataInto(data, resultList); - } - } - - int resultSize = resultList.size(); - if (resultSize == 0) { - return null; - } else { - T result = clazz.cast(Array.newInstance(clazz.getComponentType(), resultSize)); - for (int i = 0; i < resultSize; i++) { - Array.set(result, i, resultList.get(i)); - } - return result; - } - } - - private T getSingularValueFrom(List<UnknownFieldData> unknownFields) { - // For singular extensions, get the last piece of data stored under this extension. - if (unknownFields.isEmpty()) { - return null; - } - UnknownFieldData lastData = unknownFields.get(unknownFields.size() - 1); - return clazz.cast(readData(CodedInputByteBufferNano.newInstance(lastData.bytes))); - } - - protected Object readData(CodedInputByteBufferNano input) { - // This implementation is for message/group extensions. - Class<?> messageType = repeated ? clazz.getComponentType() : clazz; - try { - switch (type) { - case TYPE_GROUP: - MessageNano group = (MessageNano) messageType.newInstance(); - input.readGroup(group, WireFormatNano.getTagFieldNumber(tag)); - return group; - case TYPE_MESSAGE: - MessageNano message = (MessageNano) messageType.newInstance(); - input.readMessage(message); - return message; - default: - throw new IllegalArgumentException("Unknown type " + type); - } - } catch (InstantiationException e) { - throw new IllegalArgumentException( - "Error creating instance of class " + messageType, e); - } catch (IllegalAccessException e) { - throw new IllegalArgumentException( - "Error creating instance of class " + messageType, e); - } catch (IOException e) { - throw new IllegalArgumentException("Error reading extension field", e); - } - } - - protected void readDataInto(UnknownFieldData data, List<Object> resultList) { - // This implementation is for message/group extensions. - resultList.add(readData(CodedInputByteBufferNano.newInstance(data.bytes))); - } - - void writeTo(Object value, CodedOutputByteBufferNano output) throws IOException { - if (repeated) { - writeRepeatedData(value, output); - } else { - writeSingularData(value, output); - } - } - - protected void writeSingularData(Object value, CodedOutputByteBufferNano out) { - // This implementation is for message/group extensions. - try { - out.writeRawVarint32(tag); - switch (type) { - case TYPE_GROUP: - MessageNano groupValue = (MessageNano) value; - int fieldNumber = WireFormatNano.getTagFieldNumber(tag); - out.writeGroupNoTag(groupValue); - // The endgroup tag must be included in the data payload. - out.writeTag(fieldNumber, WireFormatNano.WIRETYPE_END_GROUP); - break; - case TYPE_MESSAGE: - MessageNano messageValue = (MessageNano) value; - out.writeMessageNoTag(messageValue); - break; - default: - throw new IllegalArgumentException("Unknown type " + type); - } - } catch (IOException e) { - // Should not happen - throw new IllegalStateException(e); - } - } - - protected void writeRepeatedData(Object array, CodedOutputByteBufferNano output) { - // This implementation is for non-packed extensions. - int arrayLength = Array.getLength(array); - for (int i = 0; i < arrayLength; i++) { - Object element = Array.get(array, i); - if (element != null) { - writeSingularData(element, output); - } - } - } - - int computeSerializedSize(Object value) { - if (repeated) { - return computeRepeatedSerializedSize(value); - } else { - return computeSingularSerializedSize(value); - } - } - - protected int computeRepeatedSerializedSize(Object array) { - // This implementation is for non-packed extensions. - int size = 0; - int arrayLength = Array.getLength(array); - for (int i = 0; i < arrayLength; i++) { - Object element = Array.get(array, i); - if (element != null) { - size += computeSingularSerializedSize(Array.get(array, i)); - } - } - return size; - } - - protected int computeSingularSerializedSize(Object value) { - // This implementation is for message/group extensions. - int fieldNumber = WireFormatNano.getTagFieldNumber(tag); - switch (type) { - case TYPE_GROUP: - MessageNano groupValue = (MessageNano) value; - return CodedOutputByteBufferNano.computeGroupSize(fieldNumber, groupValue); - case TYPE_MESSAGE: - MessageNano messageValue = (MessageNano) value; - return CodedOutputByteBufferNano.computeMessageSize(fieldNumber, messageValue); - default: - throw new IllegalArgumentException("Unknown type " + type); - } - } - - /** - * Represents an extension of a primitive (including enum) type. If there is no primitive - * extensions, this subclass will be removable by ProGuard. - */ - private static class PrimitiveExtension<M extends ExtendableMessageNano<M>, T> - extends Extension<M, T> { - - /** - * Tag of a piece of non-packed data from the wire compatible with this extension. - */ - private final int nonPackedTag; - - /** - * Tag of a piece of packed data from the wire compatible with this extension. - * 0 if the type of this extension is not packable. - */ - private final int packedTag; - - public PrimitiveExtension(int type, Class<T> clazz, int tag, boolean repeated, - int nonPackedTag, int packedTag) { - super(type, clazz, tag, repeated); - this.nonPackedTag = nonPackedTag; - this.packedTag = packedTag; - } - - @Override - protected Object readData(CodedInputByteBufferNano input) { - try { - return input.readPrimitiveField(type); - } catch (IOException e) { - throw new IllegalArgumentException("Error reading extension field", e); - } - } - - @Override - protected void readDataInto(UnknownFieldData data, List<Object> resultList) { - // This implementation is for primitive typed extensions, - // which can read both packed and non-packed data. - if (data.tag == nonPackedTag) { - resultList.add(readData(CodedInputByteBufferNano.newInstance(data.bytes))); - } else { - CodedInputByteBufferNano buffer = - CodedInputByteBufferNano.newInstance(data.bytes); - try { - buffer.pushLimit(buffer.readRawVarint32()); // length limit - } catch (IOException e) { - throw new IllegalArgumentException("Error reading extension field", e); - } - while (!buffer.isAtEnd()) { - resultList.add(readData(buffer)); - } - } - } - - @Override - protected final void writeSingularData(Object value, CodedOutputByteBufferNano output) { - try { - output.writeRawVarint32(tag); - switch (type) { - case TYPE_DOUBLE: - Double doubleValue = (Double) value; - output.writeDoubleNoTag(doubleValue); - break; - case TYPE_FLOAT: - Float floatValue = (Float) value; - output.writeFloatNoTag(floatValue); - break; - case TYPE_INT64: - Long int64Value = (Long) value; - output.writeInt64NoTag(int64Value); - break; - case TYPE_UINT64: - Long uint64Value = (Long) value; - output.writeUInt64NoTag(uint64Value); - break; - case TYPE_INT32: - Integer int32Value = (Integer) value; - output.writeInt32NoTag(int32Value); - break; - case TYPE_FIXED64: - Long fixed64Value = (Long) value; - output.writeFixed64NoTag(fixed64Value); - break; - case TYPE_FIXED32: - Integer fixed32Value = (Integer) value; - output.writeFixed32NoTag(fixed32Value); - break; - case TYPE_BOOL: - Boolean boolValue = (Boolean) value; - output.writeBoolNoTag(boolValue); - break; - case TYPE_STRING: - String stringValue = (String) value; - output.writeStringNoTag(stringValue); - break; - case TYPE_BYTES: - byte[] bytesValue = (byte[]) value; - output.writeBytesNoTag(bytesValue); - break; - case TYPE_UINT32: - Integer uint32Value = (Integer) value; - output.writeUInt32NoTag(uint32Value); - break; - case TYPE_ENUM: - Integer enumValue = (Integer) value; - output.writeEnumNoTag(enumValue); - break; - case TYPE_SFIXED32: - Integer sfixed32Value = (Integer) value; - output.writeSFixed32NoTag(sfixed32Value); - break; - case TYPE_SFIXED64: - Long sfixed64Value = (Long) value; - output.writeSFixed64NoTag(sfixed64Value); - break; - case TYPE_SINT32: - Integer sint32Value = (Integer) value; - output.writeSInt32NoTag(sint32Value); - break; - case TYPE_SINT64: - Long sint64Value = (Long) value; - output.writeSInt64NoTag(sint64Value); - break; - default: - throw new IllegalArgumentException("Unknown type " + type); - } - } catch (IOException e) { - // Should not happen - throw new IllegalStateException(e); - } - } - - @Override - protected void writeRepeatedData(Object array, CodedOutputByteBufferNano output) { - if (tag == nonPackedTag) { - // Use base implementation for non-packed data - super.writeRepeatedData(array, output); - } else if (tag == packedTag) { - // Packed. Note that the array element type is guaranteed to be primitive, so there - // won't be any null elements, so no null check in this block. - int arrayLength = Array.getLength(array); - int dataSize = computePackedDataSize(array); - - try { - output.writeRawVarint32(tag); - output.writeRawVarint32(dataSize); - switch (type) { - case TYPE_BOOL: - for (int i = 0; i < arrayLength; i++) { - output.writeBoolNoTag(Array.getBoolean(array, i)); - } - break; - case TYPE_FIXED32: - for (int i = 0; i < arrayLength; i++) { - output.writeFixed32NoTag(Array.getInt(array, i)); - } - break; - case TYPE_SFIXED32: - for (int i = 0; i < arrayLength; i++) { - output.writeSFixed32NoTag(Array.getInt(array, i)); - } - break; - case TYPE_FLOAT: - for (int i = 0; i < arrayLength; i++) { - output.writeFloatNoTag(Array.getFloat(array, i)); - } - break; - case TYPE_FIXED64: - for (int i = 0; i < arrayLength; i++) { - output.writeFixed64NoTag(Array.getLong(array, i)); - } - break; - case TYPE_SFIXED64: - for (int i = 0; i < arrayLength; i++) { - output.writeSFixed64NoTag(Array.getLong(array, i)); - } - break; - case TYPE_DOUBLE: - for (int i = 0; i < arrayLength; i++) { - output.writeDoubleNoTag(Array.getDouble(array, i)); - } - break; - case TYPE_INT32: - for (int i = 0; i < arrayLength; i++) { - output.writeInt32NoTag(Array.getInt(array, i)); - } - break; - case TYPE_SINT32: - for (int i = 0; i < arrayLength; i++) { - output.writeSInt32NoTag(Array.getInt(array, i)); - } - break; - case TYPE_UINT32: - for (int i = 0; i < arrayLength; i++) { - output.writeUInt32NoTag(Array.getInt(array, i)); - } - break; - case TYPE_INT64: - for (int i = 0; i < arrayLength; i++) { - output.writeInt64NoTag(Array.getLong(array, i)); - } - break; - case TYPE_SINT64: - for (int i = 0; i < arrayLength; i++) { - output.writeSInt64NoTag(Array.getLong(array, i)); - } - break; - case TYPE_UINT64: - for (int i = 0; i < arrayLength; i++) { - output.writeUInt64NoTag(Array.getLong(array, i)); - } - break; - case TYPE_ENUM: - for (int i = 0; i < arrayLength; i++) { - output.writeEnumNoTag(Array.getInt(array, i)); - } - break; - default: - throw new IllegalArgumentException("Unpackable type " + type); - } - } catch (IOException e) { - // Should not happen. - throw new IllegalStateException(e); - } - } else { - throw new IllegalArgumentException("Unexpected repeated extension tag " + tag - + ", unequal to both non-packed variant " + nonPackedTag - + " and packed variant " + packedTag); - } - } - - private int computePackedDataSize(Object array) { - int dataSize = 0; - int arrayLength = Array.getLength(array); - switch (type) { - case TYPE_BOOL: - // Bools are stored as int32 but just as 0 or 1, so 1 byte each. - dataSize = arrayLength; - break; - case TYPE_FIXED32: - case TYPE_SFIXED32: - case TYPE_FLOAT: - dataSize = arrayLength * CodedOutputByteBufferNano.LITTLE_ENDIAN_32_SIZE; - break; - case TYPE_FIXED64: - case TYPE_SFIXED64: - case TYPE_DOUBLE: - dataSize = arrayLength * CodedOutputByteBufferNano.LITTLE_ENDIAN_64_SIZE; - break; - case TYPE_INT32: - for (int i = 0; i < arrayLength; i++) { - dataSize += CodedOutputByteBufferNano.computeInt32SizeNoTag( - Array.getInt(array, i)); - } - break; - case TYPE_SINT32: - for (int i = 0; i < arrayLength; i++) { - dataSize += CodedOutputByteBufferNano.computeSInt32SizeNoTag( - Array.getInt(array, i)); - } - break; - case TYPE_UINT32: - for (int i = 0; i < arrayLength; i++) { - dataSize += CodedOutputByteBufferNano.computeUInt32SizeNoTag( - Array.getInt(array, i)); - } - break; - case TYPE_INT64: - for (int i = 0; i < arrayLength; i++) { - dataSize += CodedOutputByteBufferNano.computeInt64SizeNoTag( - Array.getLong(array, i)); - } - break; - case TYPE_SINT64: - for (int i = 0; i < arrayLength; i++) { - dataSize += CodedOutputByteBufferNano.computeSInt64SizeNoTag( - Array.getLong(array, i)); - } - break; - case TYPE_UINT64: - for (int i = 0; i < arrayLength; i++) { - dataSize += CodedOutputByteBufferNano.computeUInt64SizeNoTag( - Array.getLong(array, i)); - } - break; - case TYPE_ENUM: - for (int i = 0; i < arrayLength; i++) { - dataSize += CodedOutputByteBufferNano.computeEnumSizeNoTag( - Array.getInt(array, i)); - } - break; - default: - throw new IllegalArgumentException("Unexpected non-packable type " + type); - } - return dataSize; - } - - @Override - protected int computeRepeatedSerializedSize(Object array) { - if (tag == nonPackedTag) { - // Use base implementation for non-packed data - return super.computeRepeatedSerializedSize(array); - } else if (tag == packedTag) { - // Packed. - int dataSize = computePackedDataSize(array); - int payloadSize = - dataSize + CodedOutputByteBufferNano.computeRawVarint32Size(dataSize); - return payloadSize + CodedOutputByteBufferNano.computeRawVarint32Size(tag); - } else { - throw new IllegalArgumentException("Unexpected repeated extension tag " + tag - + ", unequal to both non-packed variant " + nonPackedTag - + " and packed variant " + packedTag); - } - } - - @Override - protected final int computeSingularSerializedSize(Object value) { - int fieldNumber = WireFormatNano.getTagFieldNumber(tag); - switch (type) { - case TYPE_DOUBLE: - Double doubleValue = (Double) value; - return CodedOutputByteBufferNano.computeDoubleSize(fieldNumber, doubleValue); - case TYPE_FLOAT: - Float floatValue = (Float) value; - return CodedOutputByteBufferNano.computeFloatSize(fieldNumber, floatValue); - case TYPE_INT64: - Long int64Value = (Long) value; - return CodedOutputByteBufferNano.computeInt64Size(fieldNumber, int64Value); - case TYPE_UINT64: - Long uint64Value = (Long) value; - return CodedOutputByteBufferNano.computeUInt64Size(fieldNumber, uint64Value); - case TYPE_INT32: - Integer int32Value = (Integer) value; - return CodedOutputByteBufferNano.computeInt32Size(fieldNumber, int32Value); - case TYPE_FIXED64: - Long fixed64Value = (Long) value; - return CodedOutputByteBufferNano.computeFixed64Size(fieldNumber, fixed64Value); - case TYPE_FIXED32: - Integer fixed32Value = (Integer) value; - return CodedOutputByteBufferNano.computeFixed32Size(fieldNumber, fixed32Value); - case TYPE_BOOL: - Boolean boolValue = (Boolean) value; - return CodedOutputByteBufferNano.computeBoolSize(fieldNumber, boolValue); - case TYPE_STRING: - String stringValue = (String) value; - return CodedOutputByteBufferNano.computeStringSize(fieldNumber, stringValue); - case TYPE_BYTES: - byte[] bytesValue = (byte[]) value; - return CodedOutputByteBufferNano.computeBytesSize(fieldNumber, bytesValue); - case TYPE_UINT32: - Integer uint32Value = (Integer) value; - return CodedOutputByteBufferNano.computeUInt32Size(fieldNumber, uint32Value); - case TYPE_ENUM: - Integer enumValue = (Integer) value; - return CodedOutputByteBufferNano.computeEnumSize(fieldNumber, enumValue); - case TYPE_SFIXED32: - Integer sfixed32Value = (Integer) value; - return CodedOutputByteBufferNano.computeSFixed32Size(fieldNumber, - sfixed32Value); - case TYPE_SFIXED64: - Long sfixed64Value = (Long) value; - return CodedOutputByteBufferNano.computeSFixed64Size(fieldNumber, - sfixed64Value); - case TYPE_SINT32: - Integer sint32Value = (Integer) value; - return CodedOutputByteBufferNano.computeSInt32Size(fieldNumber, sint32Value); - case TYPE_SINT64: - Long sint64Value = (Long) value; - return CodedOutputByteBufferNano.computeSInt64Size(fieldNumber, sint64Value); - default: - throw new IllegalArgumentException("Unknown type " + type); - } - } - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java b/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java deleted file mode 100644 index b49a97fa..00000000 --- a/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java +++ /dev/null @@ -1,291 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2014 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf.nano; - - -/** - * A custom version of {@code android.util.SparseArray} with the minimal API - * for storing {@link FieldData} objects. - * - * <p>This class is an internal implementation detail of nano and should not - * be called directly by clients. - * - * Based on {@code android.support.v4.util.SpareArrayCompat}. - */ -public final class FieldArray implements Cloneable { - 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. - */ - 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. - */ - 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. - */ - 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. - */ - 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. - */ - 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. - */ - 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. - */ - 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; - } - - @Override - public final FieldArray clone() { - // Trigger GC so we compact and don't copy DELETED elements. - int size = size(); - FieldArray clone = new FieldArray(size); - System.arraycopy(mFieldNumbers, 0, clone.mFieldNumbers, 0, size); - for (int i = 0; i < size; i++) { - if (mData[i] != null) { - clone.mData[i] = mData[i].clone(); - } - } - clone.mSize = size; - return clone; - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/FieldData.java b/javanano/src/main/java/com/google/protobuf/nano/FieldData.java deleted file mode 100644 index ebebabc8..00000000 --- a/javanano/src/main/java/com/google/protobuf/nano/FieldData.java +++ /dev/null @@ -1,240 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2014 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -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 implements Cloneable { - 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; - } - - @Override - public final FieldData clone() { - FieldData clone = new FieldData(); - try { - clone.cachedExtension = cachedExtension; - if (unknownFieldData == null) { - clone.unknownFieldData = null; - } else { - clone.unknownFieldData.addAll(unknownFieldData); - } - - // Whether we need to deep clone value depends on its type. Primitive reference types - // (e.g. Integer, Long etc.) are ok, since they're immutable. We need to clone arrays - // and messages. - if (value == null) { - // No cloning required. - } else if (value instanceof MessageNano) { - clone.value = ((MessageNano) value).clone(); - } else if (value instanceof byte[]) { - clone.value = ((byte[]) value).clone(); - } else if (value instanceof byte[][]) { - byte[][] valueArray = (byte[][]) value; - byte[][] cloneArray = new byte[valueArray.length][]; - clone.value = cloneArray; - for (int i = 0; i < valueArray.length; i++) { - cloneArray[i] = valueArray[i].clone(); - } - } else if (value instanceof boolean[]) { - clone.value = ((boolean[]) value).clone(); - } else if (value instanceof int[]) { - clone.value = ((int[]) value).clone(); - } else if (value instanceof long[]) { - clone.value = ((long[]) value).clone(); - } else if (value instanceof float[]) { - clone.value = ((float[]) value).clone(); - } else if (value instanceof double[]) { - clone.value = ((double[]) value).clone(); - } else if (value instanceof MessageNano[]) { - MessageNano[] valueArray = (MessageNano[]) value; - MessageNano[] cloneArray = new MessageNano[valueArray.length]; - clone.value = cloneArray; - for (int i = 0; i < valueArray.length; i++) { - cloneArray[i] = valueArray[i].clone(); - } - } - return clone; - } catch (CloneNotSupportedException e) { - throw new AssertionError(e); - } - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java deleted file mode 100644 index 278368a0..00000000 --- a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java +++ /dev/null @@ -1,547 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf.nano; - -import com.google.protobuf.nano.MapFactories.MapFactory; - -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.Arrays; -import java.util.Map; -import java.util.Map.Entry; - -/** - * 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 kenton@google.com (Kenton Varda) - */ -public final class InternalNano { - - public static final int TYPE_DOUBLE = 1; - public static final int TYPE_FLOAT = 2; - public static final int TYPE_INT64 = 3; - public static final int TYPE_UINT64 = 4; - public static final int TYPE_INT32 = 5; - public static final int TYPE_FIXED64 = 6; - public static final int TYPE_FIXED32 = 7; - public static final int TYPE_BOOL = 8; - public static final int TYPE_STRING = 9; - public static final int TYPE_GROUP = 10; - public static final int TYPE_MESSAGE = 11; - public static final int TYPE_BYTES = 12; - public static final int TYPE_UINT32 = 13; - public static final int TYPE_ENUM = 14; - public static final int TYPE_SFIXED32 = 15; - public static final int TYPE_SFIXED64 = 16; - public static final int TYPE_SINT32 = 17; - public static final int TYPE_SINT64 = 18; - - static final Charset UTF_8 = Charset.forName("UTF-8"); - static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); - - private InternalNano() {} - - /** - * An object to provide synchronization when lazily initializing static fields - * of {@link MessageNano} subclasses. - * <p> - * To enable earlier versions of ProGuard to inline short methods from a - * generated MessageNano subclass to the call sites, that class must not have - * a class initializer, which will be created if there is any static variable - * initializers. To lazily initialize the static variables in a thread-safe - * manner, the initialization code will synchronize on this object. - */ - public static final Object LAZY_INIT_LOCK = new Object(); - - /** - * 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) { - return new String(bytes.getBytes(ISO_8859_1), InternalNano.UTF_8); - } - - /** - * 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 byte[] bytesDefaultValue(String bytes) { - return bytes.getBytes(ISO_8859_1); - } - - /** - * Helper function to convert a string into UTF-8 while turning the - * UnsupportedEncodingException to a RuntimeException. - */ - public static byte[] copyFromUtf8(final String text) { - return text.getBytes(InternalNano.UTF_8); - } - - /** - * Checks repeated int field equality; null-value and 0-length fields are - * considered equal. - */ - public static boolean equals(int[] field1, int[] field2) { - if (field1 == null || field1.length == 0) { - return field2 == null || field2.length == 0; - } else { - return Arrays.equals(field1, field2); - } - } - - /** - * Checks repeated long field equality; null-value and 0-length fields are - * considered equal. - */ - public static boolean equals(long[] field1, long[] field2) { - if (field1 == null || field1.length == 0) { - return field2 == null || field2.length == 0; - } else { - return Arrays.equals(field1, field2); - } - } - - /** - * Checks repeated float field equality; null-value and 0-length fields are - * considered equal. - */ - public static boolean equals(float[] field1, float[] field2) { - if (field1 == null || field1.length == 0) { - return field2 == null || field2.length == 0; - } else { - return Arrays.equals(field1, field2); - } - } - - /** - * Checks repeated double field equality; null-value and 0-length fields are - * considered equal. - */ - public static boolean equals(double[] field1, double[] field2) { - if (field1 == null || field1.length == 0) { - return field2 == null || field2.length == 0; - } else { - return Arrays.equals(field1, field2); - } - } - - /** - * Checks repeated boolean field equality; null-value and 0-length fields are - * considered equal. - */ - public static boolean equals(boolean[] field1, boolean[] field2) { - if (field1 == null || field1.length == 0) { - return field2 == null || field2.length == 0; - } else { - return Arrays.equals(field1, field2); - } - } - - /** - * Checks repeated bytes field equality. Only non-null elements are tested. - * Returns true if the two fields have the same sequence of non-null - * elements. Null-value fields and fields of any length with only null - * elements are considered equal. - */ - public static boolean equals(byte[][] field1, byte[][] field2) { - int index1 = 0; - int length1 = field1 == null ? 0 : field1.length; - int index2 = 0; - int length2 = field2 == null ? 0 : field2.length; - while (true) { - while (index1 < length1 && field1[index1] == null) { - index1++; - } - while (index2 < length2 && field2[index2] == null) { - index2++; - } - boolean atEndOf1 = index1 >= length1; - boolean atEndOf2 = index2 >= length2; - if (atEndOf1 && atEndOf2) { - // no more non-null elements to test in both arrays - return true; - } else if (atEndOf1 != atEndOf2) { - // one of the arrays have extra non-null elements - return false; - } else if (!Arrays.equals(field1[index1], field2[index2])) { - // element mismatch - return false; - } - index1++; - index2++; - } - } - - /** - * Checks repeated string/message field equality. Only non-null elements are - * tested. Returns true if the two fields have the same sequence of non-null - * elements. Null-value fields and fields of any length with only null - * elements are considered equal. - */ - public static boolean equals(Object[] field1, Object[] field2) { - int index1 = 0; - int length1 = field1 == null ? 0 : field1.length; - int index2 = 0; - int length2 = field2 == null ? 0 : field2.length; - while (true) { - while (index1 < length1 && field1[index1] == null) { - index1++; - } - while (index2 < length2 && field2[index2] == null) { - index2++; - } - boolean atEndOf1 = index1 >= length1; - boolean atEndOf2 = index2 >= length2; - if (atEndOf1 && atEndOf2) { - // no more non-null elements to test in both arrays - return true; - } else if (atEndOf1 != atEndOf2) { - // one of the arrays have extra non-null elements - return false; - } else if (!field1[index1].equals(field2[index2])) { - // element mismatch - return false; - } - index1++; - index2++; - } - } - - /** - * Computes the hash code of a repeated int field. Null-value and 0-length - * fields have the same hash code. - */ - public static int hashCode(int[] field) { - return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); - } - - /** - * Computes the hash code of a repeated long field. Null-value and 0-length - * fields have the same hash code. - */ - public static int hashCode(long[] field) { - return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); - } - - /** - * Computes the hash code of a repeated float field. Null-value and 0-length - * fields have the same hash code. - */ - public static int hashCode(float[] field) { - return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); - } - - /** - * Computes the hash code of a repeated double field. Null-value and 0-length - * fields have the same hash code. - */ - public static int hashCode(double[] field) { - return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); - } - - /** - * Computes the hash code of a repeated boolean field. Null-value and 0-length - * fields have the same hash code. - */ - public static int hashCode(boolean[] field) { - return field == null || field.length == 0 ? 0 : Arrays.hashCode(field); - } - - /** - * Computes the hash code of a repeated bytes field. Only the sequence of all - * non-null elements are used in the computation. Null-value fields and fields - * of any length with only null elements have the same hash code. - */ - public static int hashCode(byte[][] field) { - int result = 0; - for (int i = 0, size = field == null ? 0 : field.length; i < size; i++) { - byte[] element = field[i]; - if (element != null) { - result = 31 * result + Arrays.hashCode(element); - } - } - return result; - } - - /** - * Computes the hash code of a repeated string/message field. Only the - * sequence of all non-null elements are used in the computation. Null-value - * fields and fields of any length with only null elements have the same hash - * code. - */ - public static int hashCode(Object[] field) { - int result = 0; - for (int i = 0, size = field == null ? 0 : field.length; i < size; i++) { - Object element = field[i]; - if (element != null) { - result = 31 * result + element.hashCode(); - } - } - return result; - } - private static Object primitiveDefaultValue(int type) { - switch (type) { - case TYPE_BOOL: - return Boolean.FALSE; - case TYPE_BYTES: - return WireFormatNano.EMPTY_BYTES; - case TYPE_STRING: - return ""; - case TYPE_FLOAT: - return Float.valueOf(0); - case TYPE_DOUBLE: - return Double.valueOf(0); - case TYPE_ENUM: - case TYPE_FIXED32: - case TYPE_INT32: - case TYPE_UINT32: - case TYPE_SINT32: - case TYPE_SFIXED32: - return Integer.valueOf(0); - case TYPE_INT64: - case TYPE_UINT64: - case TYPE_SINT64: - case TYPE_FIXED64: - case TYPE_SFIXED64: - return Long.valueOf(0L); - case TYPE_MESSAGE: - case TYPE_GROUP: - default: - throw new IllegalArgumentException( - "Type: " + type + " is not a primitive type."); - } - } - - /** - * Merges the map entry into the map field. Note this is only supposed to - * be called by generated messages. - * - * @param map the map field; may be null, in which case a map will be - * instantiated using the {@link MapFactories.MapFactory} - * @param input the input byte buffer - * @param keyType key type, as defined in InternalNano.TYPE_* - * @param valueType value type, as defined in InternalNano.TYPE_* - * @param value an new instance of the value, if the value is a TYPE_MESSAGE; - * otherwise this parameter can be null and will be ignored. - * @param keyTag wire tag for the key - * @param valueTag wire tag for the value - * @return the map field - * @throws IOException - */ - @SuppressWarnings("unchecked") - public static final <K, V> Map<K, V> mergeMapEntry( - CodedInputByteBufferNano input, - Map<K, V> map, - MapFactory mapFactory, - int keyType, - int valueType, - V value, - int keyTag, - int valueTag) throws IOException { - map = mapFactory.forMap(map); - final int length = input.readRawVarint32(); - final int oldLimit = input.pushLimit(length); - K key = null; - while (true) { - int tag = input.readTag(); - if (tag == 0) { - break; - } - if (tag == keyTag) { - key = (K) input.readPrimitiveField(keyType); - } else if (tag == valueTag) { - if (valueType == TYPE_MESSAGE) { - input.readMessage((MessageNano) value); - } else { - value = (V) input.readPrimitiveField(valueType); - } - } else { - if (!input.skipField(tag)) { - break; - } - } - } - input.checkLastTagWas(0); - input.popLimit(oldLimit); - - if (key == null) { - // key can only be primitive types. - key = (K) primitiveDefaultValue(keyType); - } - - if (value == null) { - // message type value will be initialized by code-gen. - value = (V) primitiveDefaultValue(valueType); - } - - map.put(key, value); - return map; - } - - public static <K, V> void serializeMapField( - CodedOutputByteBufferNano output, - Map<K, V> map, int number, int keyType, int valueType) - throws IOException { - for (Entry<K, V> entry: map.entrySet()) { - K key = entry.getKey(); - V value = entry.getValue(); - if (key == null || value == null) { - throw new IllegalStateException( - "keys and values in maps cannot be null"); - } - int entrySize = - CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) + - CodedOutputByteBufferNano.computeFieldSize(2, valueType, value); - output.writeTag(number, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); - output.writeRawVarint32(entrySize); - output.writeField(1, keyType, key); - output.writeField(2, valueType, value); - } - } - - public static <K, V> int computeMapFieldSize( - Map<K, V> map, int number, int keyType, int valueType) { - int size = 0; - int tagSize = CodedOutputByteBufferNano.computeTagSize(number); - for (Entry<K, V> entry: map.entrySet()) { - K key = entry.getKey(); - V value = entry.getValue(); - if (key == null || value == null) { - throw new IllegalStateException( - "keys and values in maps cannot be null"); - } - int entrySize = - CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) + - CodedOutputByteBufferNano.computeFieldSize(2, valueType, value); - size += tagSize + entrySize - + CodedOutputByteBufferNano.computeRawVarint32Size(entrySize); - } - return size; - } - - /** - * Checks whether two {@link Map} are equal. We don't use the default equals - * method of {@link Map} because it compares by identity not by content for - * byte arrays. - */ - public static <K, V> boolean equals(Map<K, V> a, Map<K, V> b) { - if (a == b) { - return true; - } - if (a == null) { - return b.size() == 0; - } - if (b == null) { - return a.size() == 0; - } - if (a.size() != b.size()) { - return false; - } - for (Entry<K, V> entry : a.entrySet()) { - if (!b.containsKey(entry.getKey())) { - return false; - } - if (!equalsMapValue(entry.getValue(), b.get(entry.getKey()))) { - return false; - } - } - return true; - } - - private static boolean equalsMapValue(Object a, Object b) { - if (a == null || b == null) { - throw new IllegalStateException( - "keys and values in maps cannot be null"); - } - if (a instanceof byte[] && b instanceof byte[]) { - return Arrays.equals((byte[]) a, (byte[]) b); - } - return a.equals(b); - } - - public static <K, V> int hashCode(Map<K, V> map) { - if (map == null) { - return 0; - } - int result = 0; - for (Entry<K, V> entry : map.entrySet()) { - result += hashCodeForMap(entry.getKey()) - ^ hashCodeForMap(entry.getValue()); - } - return result; - } - - private static int hashCodeForMap(Object o) { - if (o instanceof byte[]) { - return Arrays.hashCode((byte[]) o); - } - return o.hashCode(); - } - - // This avoids having to make FieldArray public. - public static void cloneUnknownFieldData(ExtendableMessageNano original, - ExtendableMessageNano cloned) { - if (original.unknownFieldData != null) { - cloned.unknownFieldData = (FieldArray) original.unknownFieldData.clone(); - } - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java b/javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java deleted file mode 100644 index 9a83d6d3..00000000 --- a/javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java +++ /dev/null @@ -1,93 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -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 that 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."); - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java b/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java deleted file mode 100644 index 98fa4877..00000000 --- a/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java +++ /dev/null @@ -1,67 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf.nano; - -import java.util.HashMap; -import java.util.Map; - -/** - * Utility class for maps support. - */ -public final class MapFactories { - public static interface MapFactory { - <K, V> Map<K, V> forMap(Map<K, V> oldMap); - } - - // NOTE(liujisi): The factory setter is temporarily marked as package private. - // The way to provide customized implementations of maps for different - // platforms are still under discussion. Mark it as private to avoid exposing - // the API in proto3 alpha release. - /* public */ static void setMapFactory(MapFactory newMapFactory) { - mapFactory = newMapFactory; - } - - public static MapFactory getMapFactory() { - return mapFactory; - } - - private static class DefaultMapFactory implements MapFactory { - public <K, V> Map<K, V> forMap(Map<K, V> oldMap) { - if (oldMap == null) { - return new HashMap<K, V>(); - } - return oldMap; - } - } - private static volatile MapFactory mapFactory = new DefaultMapFactory(); - - private MapFactories() {} -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java b/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java deleted file mode 100644 index 23475027..00000000 --- a/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java +++ /dev/null @@ -1,198 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -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); - } - - /** - * Provides support for cloning. This only works if you specify the generate_clone method. - */ - @Override - public MessageNano clone() throws CloneNotSupportedException { - return (MessageNano) super.clone(); - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java b/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java deleted file mode 100644 index 5f329f02..00000000 --- a/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java +++ /dev/null @@ -1,275 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf.nano; - -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Map; - -/** - * Static helper methods for printing nano protos. - * - * @author flynn@google.com Andrew Flynn - */ -public final class MessageNanoPrinter { - // Do not allow instantiation - private MessageNanoPrinter() {} - - private static final String INDENT = " "; - private static final int MAX_STRING_LEN = 200; - - /** - * Returns an text representation of a MessageNano suitable for debugging. The returned string - * is mostly compatible with Protocol Buffer's TextFormat (as provided by non-nano protocol - * buffers) -- groups (which are deprecated) are output with an underscore name (e.g. foo_bar - * instead of FooBar) and will thus not parse. - * - * <p>Employs Java reflection on the given object and recursively prints primitive fields, - * groups, and messages.</p> - */ - public static <T extends MessageNano> String print(T message) { - if (message == null) { - return ""; - } - - StringBuffer buf = new StringBuffer(); - try { - print(null, message, new StringBuffer(), buf); - } catch (IllegalAccessException e) { - return "Error printing proto: " + e.getMessage(); - } catch (InvocationTargetException e) { - return "Error printing proto: " + e.getMessage(); - } - return buf.toString(); - } - - /** - * Function that will print the given message/field into the StringBuffer. - * Meant to be called recursively. - * - * @param identifier the identifier to use, or {@code null} if this is the root message to - * print. - * @param object the value to print. May in fact be a primitive value or byte array and not a - * message. - * @param indentBuf the indentation each line should begin with. - * @param buf the output buffer. - */ - private static void print(String identifier, Object object, - StringBuffer indentBuf, StringBuffer buf) throws IllegalAccessException, - InvocationTargetException { - if (object == null) { - // This can happen if... - // - we're about to print a message, String, or byte[], but it not present; - // - we're about to print a primitive, but "reftype" optional style is enabled, and - // the field is unset. - // In both cases the appropriate behavior is to output nothing. - } else if (object instanceof MessageNano) { // Nano proto message - int origIndentBufLength = indentBuf.length(); - if (identifier != null) { - buf.append(indentBuf).append(deCamelCaseify(identifier)).append(" <\n"); - indentBuf.append(INDENT); - } - Class<?> clazz = object.getClass(); - - // Proto fields follow one of two formats: - // - // 1) Public, non-static variables that do not begin or end with '_' - // Find and print these using declared public fields - for (Field field : clazz.getFields()) { - int modifiers = field.getModifiers(); - String fieldName = field.getName(); - if ("cachedSize".equals(fieldName)) { - // TODO(bduff): perhaps cachedSize should have a more obscure name. - continue; - } - - if ((modifiers & Modifier.PUBLIC) == Modifier.PUBLIC - && (modifiers & Modifier.STATIC) != Modifier.STATIC - && !fieldName.startsWith("_") - && !fieldName.endsWith("_")) { - Class<?> fieldType = field.getType(); - Object value = field.get(object); - - if (fieldType.isArray()) { - Class<?> arrayType = fieldType.getComponentType(); - - // bytes is special since it's not repeated, but is represented by an array - if (arrayType == byte.class) { - print(fieldName, value, indentBuf, buf); - } else { - int len = value == null ? 0 : Array.getLength(value); - for (int i = 0; i < len; i++) { - Object elem = Array.get(value, i); - print(fieldName, elem, indentBuf, buf); - } - } - } else { - print(fieldName, value, indentBuf, buf); - } - } - } - - // 2) Fields that are accessed via getter methods (when accessors - // mode is turned on) - // Find and print these using getter methods. - for (Method method : clazz.getMethods()) { - String name = method.getName(); - // Check for the setter accessor method since getters and hazzers both have - // non-proto-field name collisions (hashCode() and getSerializedSize()) - if (name.startsWith("set")) { - String subfieldName = name.substring(3); - - Method hazzer = null; - try { - hazzer = clazz.getMethod("has" + subfieldName); - } catch (NoSuchMethodException e) { - continue; - } - // If hazzer doesn't exist or returns false, no need to continue - if (!(Boolean) hazzer.invoke(object)) { - continue; - } - - Method getter = null; - try { - getter = clazz.getMethod("get" + subfieldName); - } catch (NoSuchMethodException e) { - continue; - } - - print(subfieldName, getter.invoke(object), indentBuf, buf); - } - } - if (identifier != null) { - indentBuf.setLength(origIndentBufLength); - buf.append(indentBuf).append(">\n"); - } - } else if (object instanceof Map) { - Map<?,?> map = (Map<?,?>) object; - identifier = deCamelCaseify(identifier); - - for (Map.Entry<?,?> entry : map.entrySet()) { - buf.append(indentBuf).append(identifier).append(" <\n"); - int origIndentBufLength = indentBuf.length(); - indentBuf.append(INDENT); - print("key", entry.getKey(), indentBuf, buf); - print("value", entry.getValue(), indentBuf, buf); - indentBuf.setLength(origIndentBufLength); - buf.append(indentBuf).append(">\n"); - } - } else { - // Non-null primitive value - identifier = deCamelCaseify(identifier); - buf.append(indentBuf).append(identifier).append(": "); - if (object instanceof String) { - String stringMessage = sanitizeString((String) object); - buf.append("\"").append(stringMessage).append("\""); - } else if (object instanceof byte[]) { - appendQuotedBytes((byte[]) object, buf); - } else { - buf.append(object); - } - buf.append("\n"); - } - } - - /** - * Converts an identifier of the format "FieldName" into "field_name". - */ - private static String deCamelCaseify(String identifier) { - StringBuffer out = new StringBuffer(); - for (int i = 0; i < identifier.length(); i++) { - char currentChar = identifier.charAt(i); - if (i == 0) { - out.append(Character.toLowerCase(currentChar)); - } else if (Character.isUpperCase(currentChar)) { - out.append('_').append(Character.toLowerCase(currentChar)); - } else { - out.append(currentChar); - } - } - return out.toString(); - } - - /** - * Shortens and escapes the given string. - */ - private static String sanitizeString(String str) { - if (!str.startsWith("http") && str.length() > MAX_STRING_LEN) { - // Trim non-URL strings. - str = str.substring(0, MAX_STRING_LEN) + "[...]"; - } - return escapeString(str); - } - - /** - * Escape everything except for low ASCII code points. - */ - private static String escapeString(String str) { - int strLen = str.length(); - StringBuilder b = new StringBuilder(strLen); - for (int i = 0; i < strLen; i++) { - char original = str.charAt(i); - if (original >= ' ' && original <= '~' && original != '"' && original != '\'') { - b.append(original); - } else { - b.append(String.format("\\u%04x", (int) original)); - } - } - return b.toString(); - } - - /** - * Appends a quoted byte array to the provided {@code StringBuffer}. - */ - private static void appendQuotedBytes(byte[] bytes, StringBuffer builder) { - if (bytes == null) { - builder.append("\"\""); - return; - } - - builder.append('"'); - for (int i = 0; i < bytes.length; ++i) { - int ch = bytes[i] & 0xff; - if (ch == '\\' || ch == '"') { - builder.append('\\').append((char) ch); - } else if (ch >= 32 && ch < 127) { - builder.append((char) ch); - } else { - builder.append(String.format("\\%03o", ch)); - } - } - builder.append('"'); - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java b/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java deleted file mode 100644 index b1678d1b..00000000 --- a/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java +++ /dev/null @@ -1,88 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -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; - /** - * Important: this should be treated as immutable, even though it's possible - * to change the array values. - */ - 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; - } -} diff --git a/javanano/src/main/java/com/google/protobuf/nano/WireFormatNano.java b/javanano/src/main/java/com/google/protobuf/nano/WireFormatNano.java deleted file mode 100644 index bbb6370a..00000000 --- a/javanano/src/main/java/com/google/protobuf/nano/WireFormatNano.java +++ /dev/null @@ -1,124 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -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; - } - -} |