diff --git b/OsmAnd-java/src/com/google/protobuf/CodedInputStream.java a/OsmAnd-java/src/com/google/protobuf/CodedInputStream.java index ad43f96..45004e2 100644 --- b/OsmAnd-java/src/com/google/protobuf/CodedInputStream.java +++ a/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; @@ -71,6 +72,12 @@ public final class CodedInputStream { } // ----------------------------------------------------------------- + // begin osmand change + public static CodedInputStream newInstance(RandomAccessFile raf) { + return new CodedInputStream(raf); + } + // end osmand change + /** * Attempt to read a field tag, returning zero if we have reached EOF. @@ -477,6 +484,7 @@ public final class CodedInputStream { // ----------------------------------------------------------------- private final byte[] buffer; + private RandomAccessFile raf; private int bufferSize; private int bufferSizeAfterLimit; private int bufferPos; @@ -504,7 +512,8 @@ 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; @@ -521,6 +530,15 @@ public final class CodedInputStream { totalBytesRetired = 0; this.input = input; } + + private CodedInputStream(final RandomAccessFile raf) { + buffer = new byte[BUFFER_SIZE]; + this.bufferSize = 0; + bufferPos = 0; + totalBytesRetired = 0; + this.raf = raf; + input = null; + } /** * Set the maximum message recursion depth. In order to prevent malicious @@ -679,7 +697,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 + @@ -793,8 +822,16 @@ 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(); } @@ -817,7 +854,6 @@ public final class CodedInputStream { System.arraycopy(chunk, 0, bytes, pos, chunk.length); pos += chunk.length; } - // Done. return bytes; } @@ -847,13 +883,19 @@ 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; // ? pos incorrect 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 ; + if(raf != null) { + n = raf.skipBytes(size - pos); + } else { + n = (input == null) ? -1 : (int) input.skip(size - pos); + } if (n <= 0) { throw InvalidProtocolBufferException.truncatedMessage(); } @@ -862,4 +904,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/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 +++ a/OsmAnd-java/src/com/google/protobuf/CodedOutputStream.java @@ -30,8 +30,8 @@ package com.google.protobuf; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; import java.io.UnsupportedEncodingException; /** @@ -52,6 +52,8 @@ public final class CodedOutputStream { private final byte[] buffer; private final int limit; private int position; + // + Change + private long writtenBytes = 0; private final OutputStream output; @@ -801,6 +803,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; } @@ -813,6 +816,13 @@ public final class CodedOutputStream { refreshBuffer(); } } + + /** + * @return current offset in the output file + */ + public long getWrittenBytes() { + return writtenBytes + position; + } /** * If writing to a flat array, return the space left in the array. @@ -902,6 +912,7 @@ public final class CodedOutputStream { } else { // Write is very big. Let's do it all at once. output.write(value, offset, length); + writtenBytes += length; } } } diff --git b/OsmAnd-java/src/com/google/protobuf/WireFormat.java a/OsmAnd-java/src/com/google/protobuf/WireFormat.java index c46f7b0..cca0b8e 100644 --- b/OsmAnd-java/src/com/google/protobuf/WireFormat.java +++ a/OsmAnd-java/src/com/google/protobuf/WireFormat.java @@ -51,11 +51,13 @@ public final class WireFormat { static final int WIRETYPE_START_GROUP = 3; static final int WIRETYPE_END_GROUP = 4; 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; }