Home | History | Annotate | Download | only in Util
      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 
     25 package 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  */
     34 public class ByteArrayInput
     35     implements Input {
     36 
     37     /** non-null; the data itself */
     38     private byte[] data;
     39 
     40     /** &gt;= 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