1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* 18 * As per the Apache license requirements, this file has been modified 19 * from its original state. 20 * 21 * Such modifications are Copyright (C) 2010 Ben Gruver, and are released 22 * under the original license 23 */ 24 25package org.jf.dexlib.Util; 26 27/** 28 * Implementation of {@link Input} which reads the data from a 29 * <code>byte[]</code> instance. 30 * 31 * <p><b>Note:</b> As per the {@link Input } interface, multi-byte 32 * reads all use little-endian order.</p> 33 */ 34public class ByteArrayInput 35 implements Input { 36 37 /** non-null; the data itself */ 38 private byte[] data; 39 40 /** >= 0; current read cursor */ 41 private int cursor; 42 43 /** 44 * Constructs an instance with the given data 45 * 46 * @param data non-null; data array to use for input 47 */ 48 public ByteArrayInput(byte[] data) { 49 if (data == null) { 50 throw new NullPointerException("data == null"); 51 } 52 53 this.data = data; 54 this.cursor = 0; 55 } 56 57 /** 58 * Gets the underlying <code>byte[]</code> of this instance 59 * 60 * @return non-null; the <code>byte[]</code> 61 */ 62 public byte[] getArray() { 63 return data; 64 } 65 66 /** {@inheritDoc} */ 67 public int getCursor() { 68 return cursor; 69 } 70 71 /** {@inheritDoc} */ 72 public void setCursor(int cursor) { 73 if (cursor < 0 || cursor >= data.length) 74 throw new IndexOutOfBoundsException("The provided cursor value " + 75 "is not within the bounds of this instance's data array"); 76 this.cursor = cursor; 77 } 78 79 /** {@inheritDoc} */ 80 public void assertCursor(int expectedCursor) { 81 if (cursor != expectedCursor) { 82 throw new ExceptionWithContext("expected cursor " + 83 expectedCursor + "; actual value: " + cursor); 84 } 85 } 86 87 /** {@inheritDoc} */ 88 public byte readByte() { 89 return data[cursor++]; 90 } 91 92 /** {@inheritDoc} */ 93 public int readShort() { 94 int readAt = cursor; 95 int result = ((data[readAt++] & 0xff) + 96 ((data[readAt++] & 0xff) << 8)); 97 cursor = readAt; 98 return result; 99 } 100 101 /** {@inheritDoc} */ 102 public int readInt() { 103 int readAt = cursor; 104 int result = (data[readAt++] & 0xff) + 105 ((data[readAt++] & 0xff) << 8) + 106 ((data[readAt++] & 0xff) << 16) + 107 ((data[readAt++] & 0xff) << 24); 108 cursor = readAt; 109 return result; 110 } 111 112 /** {@inheritDoc} */ 113 public long readLong() { 114 int readAt = cursor; 115 116 long result = (data[readAt++] & 0xffL) | 117 ((data[readAt++] & 0xffL) << 8) | 118 ((data[readAt++] & 0xffL) << 16) | 119 ((data[readAt++] & 0xffL) << 24) | 120 ((data[readAt++] & 0xffL) << 32) | 121 ((data[readAt++] & 0xffL) << 40) | 122 ((data[readAt++] & 0xffL) << 48) | 123 ((data[readAt++] & 0xffL) << 56); 124 cursor = readAt; 125 return result; 126 } 127 128 129 /** {@inheritDoc} */ 130 public int readUnsignedOrSignedLeb128() { 131 int end = cursor; 132 int currentByteValue; 133 int result; 134 135 result = data[end++] & 0xff; 136 if (result > 0x7f) { 137 currentByteValue = data[end++] & 0xff; 138 result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7); 139 if (currentByteValue > 0x7f) { 140 currentByteValue = data[end++] & 0xff; 141 result |= (currentByteValue & 0x7f) << 14; 142 if (currentByteValue > 0x7f) { 143 currentByteValue = data[end++] & 0xff; 144 result |= (currentByteValue & 0x7f) << 21; 145 if (currentByteValue > 0x7f) { 146 currentByteValue = data[end++] & 0xff; 147 if (currentByteValue > 0x0f) { 148 throwInvalidLeb(); 149 } 150 result |= currentByteValue << 28; 151 } 152 } 153 } 154 } else { 155 cursor = end; 156 return result; 157 } 158 159 cursor = end; 160 161 //If the last byte is 0, then this was an unsigned value (incorrectly) written in a signed format 162 //The caller wants to know if this is the case, so we'll return the negated value instead 163 //If there was only a single byte that had a value of 0, then we would have returned in the above 164 //"else" 165 if (data[end-1] == 0) { 166 return ~result; 167 } 168 return result; 169 } 170 171 172 173 174 /** {@inheritDoc} */ 175 public int readUnsignedLeb128() { 176 int end = cursor; 177 int currentByteValue; 178 int result; 179 180 result = data[end++] & 0xff; 181 if (result > 0x7f) { 182 currentByteValue = data[end++] & 0xff; 183 result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7); 184 if (currentByteValue > 0x7f) { 185 currentByteValue = data[end++] & 0xff; 186 result |= (currentByteValue & 0x7f) << 14; 187 if (currentByteValue > 0x7f) { 188 currentByteValue = data[end++] & 0xff; 189 result |= (currentByteValue & 0x7f) << 21; 190 if (currentByteValue > 0x7f) { 191 currentByteValue = data[end++] & 0xff; 192 if (currentByteValue > 0x0f) { 193 throwInvalidLeb(); 194 } 195 result |= currentByteValue << 28; 196 } 197 } 198 } 199 } 200 201 cursor = end; 202 return result; 203 } 204 205 /** {@inheritDoc} */ 206 public int readSignedLeb128() { 207 int end = cursor; 208 int currentByteValue; 209 int result; 210 211 result = data[end++] & 0xff; 212 if (result <= 0x7f) { 213 result = (result << 25) >> 25; 214 } else { 215 currentByteValue = data[end++] & 0xff; 216 result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7); 217 if (currentByteValue <= 0x7f) { 218 result = (result << 18) >> 18; 219 } else { 220 currentByteValue = data[end++] & 0xff; 221 result |= (currentByteValue & 0x7f) << 14; 222 if (currentByteValue <= 0x7f) { 223 result = (result << 11) >> 11; 224 } else { 225 currentByteValue = data[end++] & 0xff; 226 result |= (currentByteValue & 0x7f) << 21; 227 if (currentByteValue <= 0x7f) { 228 result = (result << 4) >> 4; 229 } else { 230 currentByteValue = data[end++] & 0xff; 231 if (currentByteValue > 0x0f) { 232 throwInvalidLeb(); 233 } 234 result |= currentByteValue << 28; 235 } 236 } 237 } 238 } 239 240 cursor = end; 241 return result; 242 } 243 244 /** {@inheritDoc} */ 245 public void read(byte[] bytes, int offset, int length) { 246 int end = cursor + length; 247 248 if (end > data.length) { 249 throwBounds(); 250 } 251 252 System.arraycopy(data, cursor, bytes, offset, length); 253 cursor = end; 254 } 255 256 /** {@inheritDoc} */ 257 public void read(byte[] bytes) { 258 int length = bytes.length; 259 int end = cursor + length; 260 261 if (end > data.length) { 262 throwBounds(); 263 } 264 265 System.arraycopy(data, cursor, bytes, 0, length); 266 cursor = end; 267 } 268 269 /** {@inheritDoc} */ 270 public byte[] readBytes(int length) { 271 int end = cursor + length; 272 273 if (end > data.length) { 274 throwBounds(); 275 } 276 277 byte[] result = new byte[length]; 278 System.arraycopy(data, cursor, result, 0, length); 279 cursor = end; 280 return result; 281 } 282 283 /** {@inheritDoc} */ 284 public String realNullTerminatedUtf8String() { 285 int startPosition = cursor; 286 while (data[cursor] != 0) { 287 cursor++; 288 } 289 int byteCount = cursor - startPosition; 290 291 //skip the terminating null 292 cursor++; 293 294 return Utf8Utils.utf8BytesToString(data, startPosition, byteCount); 295 } 296 297 /** {@inheritDoc} */ 298 public void skipBytes(int count) { 299 cursor += count; 300 } 301 302 /** {@inheritDoc} */ 303 public void alignTo(int alignment) { 304 cursor = AlignmentUtils.alignOffset(cursor, alignment); 305 } 306 307 /** 308 * Throws the excpetion for when an attempt is made to read past the 309 * end of the instance. 310 */ 311 private static void throwBounds() { 312 throw new IndexOutOfBoundsException("attempt to read past the end"); 313 } 314 315 /** 316 * Throws the exception for when an invalid LEB128 value is encountered 317 */ 318 private static void throwInvalidLeb() { 319 throw new RuntimeException("invalid LEB128 integer encountered"); 320 } 321} 322