diff --git a/OsmAnd-java/protobuf-src/protobuf-2.3.patch b/OsmAnd-java/protobuf-src/protobuf-2.3.patch index d5b4bcde95..59dd00fb51 100644 --- a/OsmAnd-java/protobuf-src/protobuf-2.3.patch +++ b/OsmAnd-java/protobuf-src/protobuf-2.3.patch @@ -148,213 +148,6 @@ index ad43f96..45004e2 100644 + } + } } -diff --git b/OsmAnd-java/src/com/google/protobuf/CodedInputStreamRAF.java a/OsmAnd-java/src/com/google/protobuf/CodedInputStreamRAF.java -index ad43f96..02c1ee5 100644 ---- b/OsmAnd-java/src/com/google/protobuf/CodedInputStreamRAF.java -+++ a/OsmAnd-java/src/com/google/protobuf/CodedInputStreamRAF.java -@@ -30,8 +30,10 @@ - - package com.google.protobuf; - -+import java.io.EOFException; - import java.io.IOException; - import java.io.InputStream; -+import java.io.RandomAccessFile; - import java.util.ArrayList; - import java.util.List; - -@@ -46,29 +48,20 @@ import java.util.List; - * reading some other format of your own design, use the latter. - * - * @author kenton@google.com Kenton Varda -+ * OSMAND change - */ --public final class CodedInputStream { -+public final class CodedInputStreamRAF { - /** - * Create a new CodedInputStream wrapping the given InputStream. - */ -- public static CodedInputStream newInstance(final InputStream input) { -- return new CodedInputStream(input); -+ public static CodedInputStreamRAF newInstance(RandomAccessFile raf) { -+ return new CodedInputStreamRAF(raf, BUFFER_SIZE_DEF); - } -- -- /** -- * Create a new CodedInputStream wrapping the given byte array. -- */ -- public static CodedInputStream newInstance(final byte[] buf) { -- return newInstance(buf, 0, buf.length); -+ -+ public static CodedInputStreamRAF newInstance(RandomAccessFile raf, int bufferSize) { -+ return new CodedInputStreamRAF(raf, bufferSize); - } - -- /** -- * Create a new CodedInputStream wrapping the given byte array slice. -- */ -- public static CodedInputStream newInstance(final byte[] buf, final int off, -- final int len) { -- return new CodedInputStream(buf, off, len); -- } - - // ----------------------------------------------------------------- - -@@ -210,55 +203,8 @@ public final class CodedInputStream { - } - } - -- /** Read a {@code group} field value from the stream. */ -- public void readGroup(final int fieldNumber, -- final MessageLite.Builder builder, -- final ExtensionRegistryLite extensionRegistry) -- throws IOException { -- if (recursionDepth >= recursionLimit) { -- throw InvalidProtocolBufferException.recursionLimitExceeded(); -- } -- ++recursionDepth; -- builder.mergeFrom(this, extensionRegistry); -- checkLastTagWas( -- WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); -- --recursionDepth; -- } - -- /** -- * Reads a {@code group} field value from the stream and merges it into the -- * given {@link UnknownFieldSet}. -- * -- * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so -- * you can just call {@link #readGroup}. -- */ -- @Deprecated -- public void readUnknownGroup(final int fieldNumber, -- final MessageLite.Builder builder) -- throws IOException { -- // We know that UnknownFieldSet will ignore any ExtensionRegistry so it -- // is safe to pass null here. (We can't call -- // ExtensionRegistry.getEmptyRegistry() because that would make this -- // class depend on ExtensionRegistry, which is not part of the lite -- // library.) -- readGroup(fieldNumber, builder, null); -- } -- -- /** Read an embedded message field value from the stream. */ -- public void readMessage(final MessageLite.Builder builder, -- final ExtensionRegistryLite extensionRegistry) -- throws IOException { -- final int length = readRawVarint32(); -- if (recursionDepth >= recursionLimit) { -- throw InvalidProtocolBufferException.recursionLimitExceeded(); -- } -- final int oldLimit = pushLimit(length); -- ++recursionDepth; -- builder.mergeFrom(this, extensionRegistry); -- checkLastTagWas(0); -- --recursionDepth; -- popLimit(oldLimit); -- } -+ - - /** Read a {@code bytes} field value from the stream. */ - public ByteString readBytes() throws IOException { -@@ -480,7 +426,7 @@ public final class CodedInputStream { - private int bufferSize; - private int bufferSizeAfterLimit; - private int bufferPos; -- private final InputStream input; -+ private final RandomAccessFile raf; - private int lastTag; - - /** -@@ -504,22 +450,17 @@ public final class CodedInputStream { - - private static final int DEFAULT_RECURSION_LIMIT = 64; - private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB -- private static final int BUFFER_SIZE = 4096; -+ private static final int BUFFER_SIZE_DEF = 4096; -+ private int BUFFER_SIZE = BUFFER_SIZE_DEF; - -- private CodedInputStream(final byte[] buffer, final int off, final int len) { -- this.buffer = buffer; -- bufferSize = off + len; -- bufferPos = off; -- totalBytesRetired = -off; -- input = null; -- } - -- private CodedInputStream(final InputStream input) { -+ private CodedInputStreamRAF(final RandomAccessFile raf, int bufferSize) { -+ BUFFER_SIZE = bufferSize; - buffer = new byte[BUFFER_SIZE]; -- bufferSize = 0; -+ this.bufferSize = 0; - bufferPos = 0; - totalBytesRetired = 0; -- this.input = input; -+ this.raf = raf; - } - - /** -@@ -679,7 +620,8 @@ public final class CodedInputStream { - totalBytesRetired += bufferSize; - - bufferPos = 0; -- bufferSize = (input == null) ? -1 : input.read(buffer); -+ // osmand change -+ bufferSize = raf.read(buffer); - if (bufferSize == 0 || bufferSize < -1) { - throw new IllegalStateException( - "InputStream#read(byte[]) returned invalid result: " + bufferSize + -@@ -793,8 +735,8 @@ public final class CodedInputStream { - final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)]; - int pos = 0; - while (pos < chunk.length) { -- final int n = (input == null) ? -1 : -- input.read(chunk, pos, chunk.length - pos); -+ // osmand change -+ final int n = raf.read(chunk, pos, chunk.length - pos); - if (n == -1) { - throw InvalidProtocolBufferException.truncatedMessage(); - } -@@ -847,13 +789,14 @@ public final class CodedInputStream { - } else { - // Skipping more bytes than are in the buffer. First skip what we have. - int pos = bufferSize - bufferPos; -- totalBytesRetired += pos; -+ totalBytesRetired += bufferSize; - bufferPos = 0; - bufferSize = 0; - - // Then skip directly from the InputStream for the rest. - while (pos < size) { -- final int n = (input == null) ? -1 : (int) input.skip(size - pos); -+ // osmand change -+ final int n = raf.skipBytes(size - pos); - if (n <= 0) { - throw InvalidProtocolBufferException.truncatedMessage(); - } -@@ -862,4 +805,21 @@ public final class CodedInputStream { - } - } - } -+ -+ // osmand change -+ public void seek(long pointer) throws IOException{ -+ if(pointer - totalBytesRetired >= 0 && pointer - totalBytesRetired < bufferSize){ -+ if (pointer > currentLimit) { -+ // Then fail. -+ throw InvalidProtocolBufferException.truncatedMessage(); -+ } -+ bufferPos = (int) (pointer - totalBytesRetired); -+ } else { -+ totalBytesRetired = (int) pointer; -+ bufferSizeAfterLimit = 0; -+ raf.seek(pointer); -+ bufferPos = 0; -+ bufferSize = 0; -+ } -+ } - } diff --git b/OsmAnd-java/src/com/google/protobuf/CodedOutputStream.java a/OsmAnd-java/src/com/google/protobuf/CodedOutputStream.java index 58dd150..6e81b98 100644 --- b/OsmAnd-java/src/com/google/protobuf/CodedOutputStream.java diff --git a/OsmAnd-java/protobuf-src/protobuf-2.5.patch b/OsmAnd-java/protobuf-src/protobuf-2.5.patch new file mode 100644 index 0000000000..165bb18ebf --- /dev/null +++ b/OsmAnd-java/protobuf-src/protobuf-2.5.patch @@ -0,0 +1,207 @@ +diff --git a/OsmAnd-java/src/com/google/protobuf/CodedInputStream.java b/OsmAnd-java/src/com/google/protobuf/CodedInputStream.java +index 33417a7..5a9cb17 100644 +--- a/OsmAnd-java/src/com/google/protobuf/CodedInputStream.java ++++ b/OsmAnd-java/src/com/google/protobuf/CodedInputStream.java +@@ -32,6 +32,7 @@ package com.google.protobuf; + + import java.io.IOException; + import java.io.InputStream; ++import java.io.RandomAccessFile; + import java.util.ArrayList; + import java.util.List; + +@@ -61,6 +62,11 @@ public final class CodedInputStream { + public static CodedInputStream newInstance(final byte[] buf) { + return newInstance(buf, 0, buf.length); + } ++ ++ // begin osmand change ++ public static CodedInputStream newInstance(RandomAccessFile raf) { ++ return new CodedInputStream(raf); ++ } + + /** + * Create a new CodedInputStream wrapping the given byte array slice. +@@ -532,6 +538,7 @@ public final class CodedInputStream { + // ----------------------------------------------------------------- + + private final byte[] buffer; ++ private RandomAccessFile raf; + private int bufferSize; + private int bufferSizeAfterLimit; + private int bufferPos; +@@ -559,7 +566,7 @@ public final class CodedInputStream { + + private static final int DEFAULT_RECURSION_LIMIT = 64; + private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB +- private static final int BUFFER_SIZE = 4096; ++ private static final int BUFFER_SIZE = 5 * 1024; + + private CodedInputStream(final byte[] buffer, final int off, final int len) { + this.buffer = buffer; +@@ -569,6 +576,16 @@ public final class CodedInputStream { + input = null; + } + ++ // osmand change ++ private CodedInputStream(final RandomAccessFile raf) { ++ buffer = new byte[BUFFER_SIZE]; ++ this.bufferSize = 0; ++ bufferPos = 0; ++ totalBytesRetired = 0; ++ this.raf = raf; ++ input = null; ++ } ++ + private CodedInputStream(final InputStream input) { + buffer = new byte[BUFFER_SIZE]; + bufferSize = 0; +@@ -734,7 +751,18 @@ public final class CodedInputStream { + totalBytesRetired += bufferSize; + + bufferPos = 0; +- bufferSize = (input == null) ? -1 : input.read(buffer); ++ if (raf != null) { ++ // osmand change ++ long remain = raf.length() - raf.getFilePointer(); ++ bufferSize = (int) Math.min(remain, buffer.length); ++ if(bufferSize > 0) { ++ raf.readFully(buffer, 0, bufferSize); ++ } else { ++ bufferSize = -1; ++ } ++ } else { ++ bufferSize = (input == null) ? -1 : input.read(buffer); ++ } + if (bufferSize == 0 || bufferSize < -1) { + throw new IllegalStateException( + "InputStream#read(byte[]) returned invalid result: " + bufferSize + +@@ -848,8 +876,15 @@ public final class CodedInputStream { + final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)]; + int pos = 0; + while (pos < chunk.length) { +- final int n = (input == null) ? -1 : +- input.read(chunk, pos, chunk.length - pos); ++ final int n; ++ // osmand change ++ if(raf != null) { ++ raf.readFully(chunk, pos, chunk.length - pos); ++ n = chunk.length - pos; ++ } else { ++ n = (input == null) ? -1 : ++ input.read(chunk, pos, chunk.length - pos); ++ } + if (n == -1) { + throw InvalidProtocolBufferException.truncatedMessage(); + } +@@ -904,6 +939,16 @@ public final class CodedInputStream { + int pos = bufferSize - bufferPos; + bufferPos = bufferSize; + ++ // osmand change ++ if(raf != null) { ++ bufferPos = 0; ++ bufferSize = 0; ++ final int n = raf.skipBytes(size - pos); ++ totalBytesRetired += bufferSize + n; // ? pos incorrect ++ if (n <= 0) { ++ throw InvalidProtocolBufferException.truncatedMessage(); ++ } ++ } else { + // Keep refilling the buffer until we get to the point we wanted to skip + // to. This has the side effect of ensuring the limits are updated + // correctly. +@@ -915,6 +960,23 @@ public final class CodedInputStream { + } + + bufferPos = size - pos; ++ } + } + } ++ ++ public void seek(long pointer) throws IOException { ++ if (pointer - totalBytesRetired >= 0 && pointer - totalBytesRetired < bufferSize) { ++ if (pointer > currentLimit) { ++ // Then fail. ++ throw InvalidProtocolBufferException.truncatedMessage(); ++ } ++ bufferPos = (int) (pointer - totalBytesRetired); ++ } else { ++ totalBytesRetired = (int) pointer; ++ bufferSizeAfterLimit = 0; ++ raf.seek(pointer); ++ bufferPos = 0; ++ bufferSize = 0; ++ } ++ } + } +diff --git a/OsmAnd-java/src/com/google/protobuf/CodedOutputStream.java b/OsmAnd-java/src/com/google/protobuf/CodedOutputStream.java +index ca24638..c1001bc 100644 +--- a/OsmAnd-java/src/com/google/protobuf/CodedOutputStream.java ++++ b/OsmAnd-java/src/com/google/protobuf/CodedOutputStream.java +@@ -53,6 +53,7 @@ public final class CodedOutputStream { + private final byte[] buffer; + private final int limit; + private int position; ++ private long writtenBytes = 0; + + private final OutputStream output; + +@@ -831,6 +832,7 @@ public final class CodedOutputStream { + // Since we have an output stream, this is our buffer + // and buffer offset == 0 + output.write(buffer, 0, position); ++ writtenBytes += position; + position = 0; + } + +@@ -857,6 +859,13 @@ public final class CodedOutputStream { + "writing to a flat array."); + } + } ++ ++ /** ++ * @return current offset in the output file ++ */ ++ public long getWrittenBytes() { ++ return writtenBytes + position; ++ } + + /** + * Verifies that {@link #spaceLeft()} returns zero. It's common to create +@@ -937,6 +946,7 @@ public final class CodedOutputStream { + } else { + // Write is very big. Let's do it all at once. + output.write(value, offset, length); ++ writtenBytes += length; + } + } + } +@@ -982,6 +992,7 @@ public final class CodedOutputStream { + throw new IllegalStateException("Read failed? Should never happen"); + } + output.write(buffer, 0, bytesRead); ++ writtenBytes += bytesRead; + length -= bytesRead; + } + } +diff --git a/OsmAnd-java/src/com/google/protobuf/WireFormat.java b/OsmAnd-java/src/com/google/protobuf/WireFormat.java +index dd2d631..d6e07cf 100644 +--- a/OsmAnd-java/src/com/google/protobuf/WireFormat.java ++++ b/OsmAnd-java/src/com/google/protobuf/WireFormat.java +@@ -51,12 +51,14 @@ public final class WireFormat { + public static final int WIRETYPE_START_GROUP = 3; + public static final int WIRETYPE_END_GROUP = 4; + public static final int WIRETYPE_FIXED32 = 5; ++ // Osmand Delta change ++ public static final int WIRETYPE_FIXED32_LENGTH_DELIMITED = 6; + + 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) { ++ public static int getTagWireType(final int tag) { + return tag & TAG_TYPE_MASK; + } + diff --git a/OsmAnd-java/protobuf-src/protobuf-patch.sh b/OsmAnd-java/protobuf-src/protobuf-patch.sh index 0b55270c3a..cb163f12bd 100755 --- a/OsmAnd-java/protobuf-src/protobuf-patch.sh +++ b/OsmAnd-java/protobuf-src/protobuf-patch.sh @@ -1,5 +1,4 @@ #!/bin/bash mkdir -p ../src/com -cp com/google/protobuf/CodedInputStream.java com/google/protobuf/CodedInputStreamRAF.java cp -Rf com/* ../src/com/ (cd ../ && git apply -v protobuf-src/protobuf-2.3.patch) \ No newline at end of file diff --git a/OsmAnd-java/src/com/google/protobuf/CodedInputStreamRAF.java b/OsmAnd-java/src/com/google/protobuf/CodedInputStreamRAF.java deleted file mode 100644 index 02c1ee5d0f..0000000000 --- a/OsmAnd-java/src/com/google/protobuf/CodedInputStreamRAF.java +++ /dev/null @@ -1,825 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package com.google.protobuf; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.util.ArrayList; -import java.util.List; - -/** - * 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 - * OSMAND change - */ -public final class CodedInputStreamRAF { - /** - * Create a new CodedInputStream wrapping the given InputStream. - */ - public static CodedInputStreamRAF newInstance(RandomAccessFile raf) { - return new CodedInputStreamRAF(raf, BUFFER_SIZE_DEF); - } - - public static CodedInputStreamRAF newInstance(RandomAccessFile raf, int bufferSize) { - return new CodedInputStreamRAF(raf, bufferSize); - } - - - // ----------------------------------------------------------------- - - /** - * 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 (WireFormat.getTagFieldNumber(lastTag) == 0) { - // If we actually read zero (or any tag number corresponding to field - // number zero), that's not a valid tag. - throw InvalidProtocolBufferException.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 InvalidProtocolBufferException {@code value} does not match the - * last tag. - */ - public void checkLastTagWas(final int value) - throws InvalidProtocolBufferException { - if (lastTag != value) { - throw InvalidProtocolBufferException.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 (WireFormat.getTagWireType(tag)) { - case WireFormat.WIRETYPE_VARINT: - readInt32(); - return true; - case WireFormat.WIRETYPE_FIXED64: - readRawLittleEndian64(); - return true; - case WireFormat.WIRETYPE_LENGTH_DELIMITED: - skipRawBytes(readRawVarint32()); - return true; - case WireFormat.WIRETYPE_START_GROUP: - skipMessage(); - checkLastTagWas( - WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), - WireFormat.WIRETYPE_END_GROUP)); - return true; - case WireFormat.WIRETYPE_END_GROUP: - return false; - case WireFormat.WIRETYPE_FIXED32: - readRawLittleEndian32(); - return true; - default: - throw InvalidProtocolBufferException.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, "UTF-8"); - bufferPos += size; - return result; - } else { - // Slow path: Build a byte array first then copy it. - return new String(readRawBytes(size), "UTF-8"); - } - } - - - - - /** Read a {@code bytes} field value from the stream. */ - public ByteString 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 ByteString result = ByteString.copyFrom(buffer, bufferPos, size); - bufferPos += size; - return result; - } else { - // Slow path: Build a byte array first then copy it. - return ByteString.copyFrom(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 InvalidProtocolBufferException.malformedVarint(); - } - } - } - } - return result; - } - - /** - * Reads a varint from the input one byte at a time, so that it does not - * read any bytes after the end of the varint. If you simply wrapped the - * stream in a CodedInputStream and used {@link #readRawVarint32(InputStream)} - * then you would probably end up reading past the end of the varint since - * CodedInputStream buffers its input. - */ - static int readRawVarint32(final InputStream input) throws IOException { - final int firstByte = input.read(); - if (firstByte == -1) { - throw InvalidProtocolBufferException.truncatedMessage(); - } - return readRawVarint32(firstByte, input); - } - - /** - * Like {@link #readRawVarint32(InputStream)}, but expects that the caller - * has already read one byte. This allows the caller to determine if EOF - * has been reached before attempting to read. - */ - static int readRawVarint32(final int firstByte, - final InputStream input) throws IOException { - if ((firstByte & 0x80) == 0) { - return firstByte; - } - - int result = firstByte & 0x7f; - int offset = 7; - for (; offset < 32; offset += 7) { - final int b = input.read(); - if (b == -1) { - throw InvalidProtocolBufferException.truncatedMessage(); - } - result |= (b & 0x7f) << offset; - if ((b & 0x80) == 0) { - return result; - } - } - // Keep reading up to 64 bits. - for (; offset < 64; offset += 7) { - final int b = input.read(); - if (b == -1) { - throw InvalidProtocolBufferException.truncatedMessage(); - } - if ((b & 0x80) == 0) { - return result; - } - } - throw InvalidProtocolBufferException.malformedVarint(); - } - - /** 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 InvalidProtocolBufferException.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 (((int)b1 & 0xff) ) | - (((int)b2 & 0xff) << 8) | - (((int)b3 & 0xff) << 16) | - (((int)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 bufferSize; - private int bufferSizeAfterLimit; - private int bufferPos; - private final RandomAccessFile raf; - private int lastTag; - - /** - * The total number of bytes read before the current buffer. The total - * bytes read up to the current position can be computed as - * {@code totalBytesRetired + bufferPos}. This value may be negative if - * reading started in the middle of the current buffer (e.g. if the - * constructor that takes a byte array and an offset was used). - */ - private int totalBytesRetired; - - /** 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 static final int BUFFER_SIZE_DEF = 4096; - private int BUFFER_SIZE = BUFFER_SIZE_DEF; - - - private CodedInputStreamRAF(final RandomAccessFile raf, int bufferSize) { - BUFFER_SIZE = bufferSize; - buffer = new byte[BUFFER_SIZE]; - this.bufferSize = 0; - bufferPos = 0; - totalBytesRetired = 0; - this.raf = raf; - } - - /** - * 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 (nor with - * {@link ByteString#newCodedInput}). - *
- * 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() { - totalBytesRetired = -bufferPos; - } - - /** - * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This - * is called when descending into a length-delimited embedded message. - * - *
Note that {@code pushLimit()} does NOT affect how many bytes the
- * {@code CodedInputStream} reads from an underlying {@code InputStream} when
- * refreshing its buffer. If you need to prevent reading past a certain
- * point in the underlying {@code InputStream} (e.g. because you expect it to
- * contain more data after the end of the message which you need to handle
- * differently) then you must place a wrapper around you {@code InputStream}
- * which limits the amount of data that can be read from it.
- *
- * @return the old limit.
- */
- public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
- if (byteLimit < 0) {
- throw InvalidProtocolBufferException.negativeSize();
- }
- byteLimit += totalBytesRetired + bufferPos;
- final int oldLimit = currentLimit;
- if (byteLimit > oldLimit) {
- throw InvalidProtocolBufferException.truncatedMessage();
- }
- currentLimit = byteLimit;
-
- recomputeBufferSizeAfterLimit();
-
- return oldLimit;
- }
-
- private void recomputeBufferSizeAfterLimit() {
- bufferSize += bufferSizeAfterLimit;
- final int bufferEnd = totalBytesRetired + 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 = totalBytesRetired + 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() throws IOException {
- return bufferPos == bufferSize && !refillBuffer(false);
- }
-
- /**
- * The total bytes read up to the current position. Calling
- * {@link #resetSizeCounter()} resets this value to zero.
- */
- public int getTotalBytesRead() {
- return totalBytesRetired + bufferPos;
- }
-
- /**
- * Called with {@code this.buffer} is empty to read more bytes from the
- * input. If {@code mustSucceed} is true, refillBuffer() gurantees that
- * either there will be at least one byte in the buffer when it returns
- * or it will throw an exception. If {@code mustSucceed} is false,
- * refillBuffer() returns false if no more bytes were available.
- */
- private boolean refillBuffer(final boolean mustSucceed) throws IOException {
- if (bufferPos < bufferSize) {
- throw new IllegalStateException(
- "refillBuffer() called when buffer wasn't empty.");
- }
-
- if (totalBytesRetired + bufferSize == currentLimit) {
- // Oops, we hit a limit.
- if (mustSucceed) {
- throw InvalidProtocolBufferException.truncatedMessage();
- } else {
- return false;
- }
- }
-
- totalBytesRetired += bufferSize;
-
- bufferPos = 0;
- // osmand change
- bufferSize = raf.read(buffer);
- if (bufferSize == 0 || bufferSize < -1) {
- throw new IllegalStateException(
- "InputStream#read(byte[]) returned invalid result: " + bufferSize +
- "\nThe InputStream implementation is buggy.");
- }
- if (bufferSize == -1) {
- bufferSize = 0;
- if (mustSucceed) {
- throw InvalidProtocolBufferException.truncatedMessage();
- } else {
- return false;
- }
- } else {
- recomputeBufferSizeAfterLimit();
- final int totalBytesRead =
- totalBytesRetired + bufferSize + bufferSizeAfterLimit;
- if (totalBytesRead > sizeLimit || totalBytesRead < 0) {
- throw InvalidProtocolBufferException.sizeLimitExceeded();
- }
- return true;
- }
- }
-
- /**
- * Read one byte from the input.
- *
- * @throws InvalidProtocolBufferException The end of the stream or the current
- * limit was reached.
- */
- public byte readRawByte() throws IOException {
- if (bufferPos == bufferSize) {
- refillBuffer(true);
- }
- return buffer[bufferPos++];
- }
-
- /**
- * Read a fixed size of bytes from the input.
- *
- * @throws InvalidProtocolBufferException The end of the stream or the current
- * limit was reached.
- */
- public byte[] readRawBytes(final int size) throws IOException {
- if (size < 0) {
- throw InvalidProtocolBufferException.negativeSize();
- }
-
- if (totalBytesRetired + bufferPos + size > currentLimit) {
- // Read to the end of the stream anyway.
- skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
- // Then fail.
- throw InvalidProtocolBufferException.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 if (size < BUFFER_SIZE) {
- // Reading more bytes than are in the buffer, but not an excessive number
- // of bytes. We can safely allocate the resulting array ahead of time.
-
- // First copy what we have.
- final byte[] bytes = new byte[size];
- int pos = bufferSize - bufferPos;
- System.arraycopy(buffer, bufferPos, bytes, 0, pos);
- bufferPos = bufferSize;
-
- // We want to use refillBuffer() and then copy from the buffer into our
- // byte array rather than reading directly into our byte array because
- // the input may be unbuffered.
- refillBuffer(true);
-
- while (size - pos > bufferSize) {
- System.arraycopy(buffer, 0, bytes, pos, bufferSize);
- pos += bufferSize;
- bufferPos = bufferSize;
- refillBuffer(true);
- }
-
- System.arraycopy(buffer, 0, bytes, pos, size - pos);
- bufferPos = size - pos;
-
- return bytes;
- } else {
- // The size is very large. For security reasons, we can't allocate the
- // entire byte array yet. The size comes directly from the input, so a
- // maliciously-crafted message could provide a bogus very large size in
- // order to trick the app into allocating a lot of memory. We avoid this
- // by allocating and reading only a small chunk at a time, so that the
- // malicious message must actually *be* extremely large to cause
- // problems. Meanwhile, we limit the allowed size of a message elsewhere.
-
- // Remember the buffer markers since we'll have to copy the bytes out of
- // it later.
- final int originalBufferPos = bufferPos;
- final int originalBufferSize = bufferSize;
-
- // Mark the current buffer consumed.
- totalBytesRetired += bufferSize;
- bufferPos = 0;
- bufferSize = 0;
-
- // Read all the rest of the bytes we need.
- int sizeLeft = size - (originalBufferSize - originalBufferPos);
- final List