1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/* 2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project 3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License"); 5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License. 6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at 7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * http://www.apache.org/licenses/LICENSE-2.0 9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software 11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS, 12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and 14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License. 15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.util; 18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.DataInputStream; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.IOException; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.io.InputStream; 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Wrapper for a {@code byte[]}, which provides read-only access and 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * can "reveal" a partial slice of the underlying array. 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <b>Note:</b> Multibyte accessors all use big-endian order. 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class ByteArray { 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} underlying array */ 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final byte[] bytes; 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= 0}; start index of the slice (inclusive) */ 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final int start; 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= 0, <= bytes.length}; size computed as 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code end - start} (in the constructor) */ 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final int size; 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param bytes {@code non-null;} the underlying array 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param start {@code >= 0;} start index of the slice (inclusive) 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param end {@code >= start, <= bytes.length;} end index of 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the slice (exclusive) 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public ByteArray(byte[] bytes, int start, int end) { 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (bytes == null) { 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("bytes == null"); 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (start < 0) { 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("start < 0"); 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (end < start) { 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("end < start"); 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (end > bytes.length) { 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("end > bytes.length"); 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.bytes = bytes; 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.start = start; 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.size = end - start; 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance from an entire {@code byte[]}. 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param bytes {@code non-null;} the underlying array 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public ByteArray(byte[] bytes) { 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this(bytes, 0, bytes.length); 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the size of the array, in bytes. 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the size 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int size() { 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return size; 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns a slice (that is, a sub-array) of this instance. 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param start {@code >= 0;} start index of the slice (inclusive) 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param end {@code >= start, <= size();} end index of 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the slice (exclusive) 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the slice 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public ByteArray slice(int start, int end) { 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul checkOffsets(start, end); 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return new ByteArray(bytes, start + this.start, end + this.start); 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns the offset into the given array represented by the given 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * offset into this instance. 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param offset offset into this instance 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param bytes {@code non-null;} (alleged) underlying array 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return corresponding offset into {@code bytes} 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IllegalArgumentException thrown if {@code bytes} is 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * not the underlying array of this instance 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int underlyingOffset(int offset, byte[] bytes) { 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (bytes != this.bytes) { 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("wrong bytes"); 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return start + offset; 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the {@code signed byte} value at a particular offset. 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param off {@code >= 0, < size();} offset to fetch 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code signed byte} at that offset 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getByte(int off) { 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul checkOffsets(off, off + 1); 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return getByte0(off); 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the {@code signed short} value at a particular offset. 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param off {@code >= 0, < (size() - 1);} offset to fetch 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code signed short} at that offset 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getShort(int off) { 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul checkOffsets(off, off + 2); 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (getByte0(off) << 8) | getUnsignedByte0(off + 1); 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the {@code signed int} value at a particular offset. 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param off {@code >= 0, < (size() - 3);} offset to fetch 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code signed int} at that offset 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getInt(int off) { 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul checkOffsets(off, off + 4); 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (getByte0(off) << 24) | 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul (getUnsignedByte0(off + 1) << 16) | 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul (getUnsignedByte0(off + 2) << 8) | 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul getUnsignedByte0(off + 3); 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the {@code signed long} value at a particular offset. 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param off {@code >= 0, < (size() - 7);} offset to fetch 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code signed int} at that offset 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public long getLong(int off) { 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul checkOffsets(off, off + 8); 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int part1 = (getByte0(off) << 24) | 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul (getUnsignedByte0(off + 1) << 16) | 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul (getUnsignedByte0(off + 2) << 8) | 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul getUnsignedByte0(off + 3); 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int part2 = (getByte0(off + 4) << 24) | 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul (getUnsignedByte0(off + 5) << 16) | 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul (getUnsignedByte0(off + 6) << 8) | 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul getUnsignedByte0(off + 7); 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (part2 & 0xffffffffL) | ((long) part1) << 32; 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the {@code unsigned byte} value at a particular offset. 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param off {@code >= 0, < size();} offset to fetch 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code unsigned byte} at that offset 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getUnsignedByte(int off) { 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul checkOffsets(off, off + 1); 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return getUnsignedByte0(off); 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the {@code unsigned short} value at a particular offset. 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param off {@code >= 0, < (size() - 1);} offset to fetch 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code unsigned short} at that offset 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getUnsignedShort(int off) { 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul checkOffsets(off, off + 2); 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (getUnsignedByte0(off) << 8) | getUnsignedByte0(off + 1); 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copies the contents of this instance into the given raw 199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code byte[]} at the given offset. The given array must be 200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * large enough. 201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} array to hold the output 203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param offset {@code non-null;} index into {@code out} for the first 204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * byte of output 205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void getBytes(byte[] out, int offset) { 207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((out.length - offset) < size) { 208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IndexOutOfBoundsException("(out.length - offset) < " + 209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul "size()"); 210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul System.arraycopy(bytes, start, out, offset, size); 213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Checks a range of offsets for validity, throwing if invalid. 217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param s start offset (inclusive) 219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param e end offset (exclusive) 220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private void checkOffsets(int s, int e) { 222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((s < 0) || (e < s) || (e > size)) { 223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("bad range: " + s + ".." + e + 224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul "; actual size " + size); 225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the {@code signed byte} value at the given offset, 230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * without doing any argument checking. 231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param off offset to fetch 233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return byte at that offset 234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int getByte0(int off) { 236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return bytes[start + off]; 237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the {@code unsigned byte} value at the given offset, 241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * without doing any argument checking. 242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param off offset to fetch 244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return byte at that offset 245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int getUnsignedByte0(int off) { 247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return bytes[start + off] & 0xff; 248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets a {@code DataInputStream} that reads from this instance, 252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * with the cursor starting at the beginning of this instance's data. 253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <b>Note:</b> The returned instance may be cast to {@link #GetCursor} 254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * if needed. 255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed 257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code DataInputStream} instance 258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public MyDataInputStream makeDataInputStream() { 260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return new MyDataInputStream(makeInputStream()); 261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets a {@code InputStream} that reads from this instance, 265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * with the cursor starting at the beginning of this instance's data. 266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <b>Note:</b> The returned instance may be cast to {@link #GetCursor} 267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * if needed. 268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed 270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code InputStream} instancex 271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public MyInputStream makeInputStream() { 273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return new MyInputStream(); 274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper interface that allows one to get the cursor (of a stream). 278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public interface GetCursor { 280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the current cursor. 282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code 0..size();} the cursor 284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getCursor(); 286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper class for {@link #makeInputStream}, which implements the 290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * stream functionality. 291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public class MyInputStream extends InputStream { 293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 0..size; the cursor */ 294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int cursor; 295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 0..size; the mark */ 297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int mark; 298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public MyInputStream() { 300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul cursor = 0; 301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul mark = 0; 302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int read() throws IOException { 305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (cursor >= size) { 306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return -1; 307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int result = getUnsignedByte0(cursor); 310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul cursor++; 311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int read(byte[] arr, int offset, int length) { 315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((offset + length) > arr.length) { 316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul length = arr.length - offset; 317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int maxLength = size - cursor; 320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (length > maxLength) { 321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul length = maxLength; 322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul System.arraycopy(bytes, cursor + start, arr, offset, length); 325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul cursor += length; 326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return length; 327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int available() { 330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return size - cursor; 331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void mark(int reserve) { 334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul mark = cursor; 335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void reset() { 338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul cursor = mark; 339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean markSupported() { 342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return true; 343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper class for {@link #makeDataInputStream}. This is used 348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * simply so that the cursor of a wrapped {@link #MyInputStream} 349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance may be easily determined. 350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static class MyDataInputStream extends DataInputStream { 352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} the underlying {@link #MyInputStream} */ 353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final MyInputStream wrapped; 354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public MyDataInputStream(MyInputStream wrapped) { 356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super(wrapped); 357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.wrapped = wrapped; 359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 362