Home | History | Annotate | Download | only in dex
      1 /*
      2  * Copyright (C) 2011 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 package com.android.dex;
     18 
     19 import com.android.dex.util.ByteInput;
     20 
     21 /**
     22  * Pull parser for encoded values.
     23  */
     24 public final class EncodedValueReader {
     25     public static final int ENCODED_BYTE = 0x00;
     26     public static final int ENCODED_SHORT = 0x02;
     27     public static final int ENCODED_CHAR = 0x03;
     28     public static final int ENCODED_INT = 0x04;
     29     public static final int ENCODED_LONG = 0x06;
     30     public static final int ENCODED_FLOAT = 0x10;
     31     public static final int ENCODED_DOUBLE = 0x11;
     32     public static final int ENCODED_METHOD_TYPE = 0x15;
     33     public static final int ENCODED_METHOD_HANDLE = 0x16;
     34     public static final int ENCODED_STRING = 0x17;
     35     public static final int ENCODED_TYPE = 0x18;
     36     public static final int ENCODED_FIELD = 0x19;
     37     public static final int ENCODED_ENUM = 0x1b;
     38     public static final int ENCODED_METHOD = 0x1a;
     39     public static final int ENCODED_ARRAY = 0x1c;
     40     public static final int ENCODED_ANNOTATION = 0x1d;
     41     public static final int ENCODED_NULL = 0x1e;
     42     public static final int ENCODED_BOOLEAN = 0x1f;
     43 
     44     /** placeholder type if the type is not yet known */
     45     private static final int MUST_READ = -1;
     46 
     47     protected final ByteInput in;
     48     private int type = MUST_READ;
     49     private int annotationType;
     50     private int arg;
     51 
     52     public EncodedValueReader(ByteInput in) {
     53         this.in = in;
     54     }
     55 
     56     public EncodedValueReader(EncodedValue in) {
     57         this(in.asByteInput());
     58     }
     59 
     60     /**
     61      * Creates a new encoded value reader whose only value is the specified
     62      * known type. This is useful for encoded values without a type prefix,
     63      * such as class_def_item's encoded_array or annotation_item's
     64      * encoded_annotation.
     65      */
     66     public EncodedValueReader(ByteInput in, int knownType) {
     67         this.in = in;
     68         this.type = knownType;
     69     }
     70 
     71     public EncodedValueReader(EncodedValue in, int knownType) {
     72         this(in.asByteInput(), knownType);
     73     }
     74 
     75     /**
     76      * Returns the type of the next value to read.
     77      */
     78     public int peek() {
     79         if (type == MUST_READ) {
     80             int argAndType = in.readByte() & 0xff;
     81             type = argAndType & 0x1f;
     82             arg = (argAndType & 0xe0) >> 5;
     83         }
     84         return type;
     85     }
     86 
     87     /**
     88      * Begins reading the elements of an array, returning the array's size. The
     89      * caller must follow up by calling a read method for each element in the
     90      * array. For example, this reads a byte array: <pre>   {@code
     91      *   int arraySize = readArray();
     92      *   for (int i = 0, i < arraySize; i++) {
     93      *     readByte();
     94      *   }
     95      * }</pre>
     96      */
     97     public int readArray() {
     98         checkType(ENCODED_ARRAY);
     99         type = MUST_READ;
    100         return Leb128.readUnsignedLeb128(in);
    101     }
    102 
    103     /**
    104      * Begins reading the fields of an annotation, returning the number of
    105      * fields. The caller must follow up by making alternating calls to {@link
    106      * #readAnnotationName()} and another read method. For example, this reads
    107      * an annotation whose fields are all bytes: <pre>   {@code
    108      *   int fieldCount = readAnnotation();
    109      *   int annotationType = getAnnotationType();
    110      *   for (int i = 0; i < fieldCount; i++) {
    111      *       readAnnotationName();
    112      *       readByte();
    113      *   }
    114      * }</pre>
    115      */
    116     public int readAnnotation() {
    117         checkType(ENCODED_ANNOTATION);
    118         type = MUST_READ;
    119         annotationType = Leb128.readUnsignedLeb128(in);
    120         return Leb128.readUnsignedLeb128(in);
    121     }
    122 
    123     /**
    124      * Returns the type of the annotation just returned by {@link
    125      * #readAnnotation()}. This method's value is undefined unless the most
    126      * recent call was to {@link #readAnnotation()}.
    127      */
    128     public int getAnnotationType() {
    129         return annotationType;
    130     }
    131 
    132     public int readAnnotationName() {
    133         return Leb128.readUnsignedLeb128(in);
    134     }
    135 
    136     public byte readByte() {
    137         checkType(ENCODED_BYTE);
    138         type = MUST_READ;
    139         return (byte) EncodedValueCodec.readSignedInt(in, arg);
    140     }
    141 
    142     public short readShort() {
    143         checkType(ENCODED_SHORT);
    144         type = MUST_READ;
    145         return (short) EncodedValueCodec.readSignedInt(in, arg);
    146     }
    147 
    148     public char readChar() {
    149         checkType(ENCODED_CHAR);
    150         type = MUST_READ;
    151         return (char) EncodedValueCodec.readUnsignedInt(in, arg, false);
    152     }
    153 
    154     public int readInt() {
    155         checkType(ENCODED_INT);
    156         type = MUST_READ;
    157         return EncodedValueCodec.readSignedInt(in, arg);
    158     }
    159 
    160     public long readLong() {
    161         checkType(ENCODED_LONG);
    162         type = MUST_READ;
    163         return EncodedValueCodec.readSignedLong(in, arg);
    164     }
    165 
    166     public float readFloat() {
    167         checkType(ENCODED_FLOAT);
    168         type = MUST_READ;
    169         return Float.intBitsToFloat(EncodedValueCodec.readUnsignedInt(in, arg, true));
    170     }
    171 
    172     public double readDouble() {
    173         checkType(ENCODED_DOUBLE);
    174         type = MUST_READ;
    175         return Double.longBitsToDouble(EncodedValueCodec.readUnsignedLong(in, arg, true));
    176     }
    177 
    178     public int readMethodType() {
    179         checkType(ENCODED_METHOD_TYPE);
    180         type = MUST_READ;
    181         return EncodedValueCodec.readUnsignedInt(in, arg, false);
    182     }
    183 
    184     public int readMethodHandle() {
    185         checkType(ENCODED_METHOD_HANDLE);
    186         type = MUST_READ;
    187         return EncodedValueCodec.readUnsignedInt(in, arg, false);
    188     }
    189 
    190     public int readString() {
    191         checkType(ENCODED_STRING);
    192         type = MUST_READ;
    193         return EncodedValueCodec.readUnsignedInt(in, arg, false);
    194     }
    195 
    196     public int readType() {
    197         checkType(ENCODED_TYPE);
    198         type = MUST_READ;
    199         return EncodedValueCodec.readUnsignedInt(in, arg, false);
    200     }
    201 
    202     public int readField() {
    203         checkType(ENCODED_FIELD);
    204         type = MUST_READ;
    205         return EncodedValueCodec.readUnsignedInt(in, arg, false);
    206     }
    207 
    208     public int readEnum() {
    209         checkType(ENCODED_ENUM);
    210         type = MUST_READ;
    211         return EncodedValueCodec.readUnsignedInt(in, arg, false);
    212     }
    213 
    214     public int readMethod() {
    215         checkType(ENCODED_METHOD);
    216         type = MUST_READ;
    217         return EncodedValueCodec.readUnsignedInt(in, arg, false);
    218     }
    219 
    220     public void readNull() {
    221         checkType(ENCODED_NULL);
    222         type = MUST_READ;
    223     }
    224 
    225     public boolean readBoolean() {
    226         checkType(ENCODED_BOOLEAN);
    227         type = MUST_READ;
    228         return arg != 0;
    229     }
    230 
    231     /**
    232      * Skips a single value, including its nested values if it is an array or
    233      * annotation.
    234      */
    235     public void skipValue() {
    236         switch (peek()) {
    237         case ENCODED_BYTE:
    238             readByte();
    239             break;
    240         case ENCODED_SHORT:
    241             readShort();
    242             break;
    243         case ENCODED_CHAR:
    244             readChar();
    245             break;
    246         case ENCODED_INT:
    247             readInt();
    248             break;
    249         case ENCODED_LONG:
    250             readLong();
    251             break;
    252         case ENCODED_FLOAT:
    253             readFloat();
    254             break;
    255         case ENCODED_DOUBLE:
    256             readDouble();
    257             break;
    258         case ENCODED_METHOD_TYPE:
    259             readMethodType();
    260             break;
    261         case ENCODED_METHOD_HANDLE:
    262             readMethodHandle();
    263             break;
    264         case ENCODED_STRING:
    265             readString();
    266             break;
    267         case ENCODED_TYPE:
    268             readType();
    269             break;
    270         case ENCODED_FIELD:
    271             readField();
    272             break;
    273         case ENCODED_ENUM:
    274             readEnum();
    275             break;
    276         case ENCODED_METHOD:
    277             readMethod();
    278             break;
    279         case ENCODED_ARRAY:
    280             for (int i = 0, size = readArray(); i < size; i++) {
    281                 skipValue();
    282             }
    283             break;
    284         case ENCODED_ANNOTATION:
    285             for (int i = 0, size = readAnnotation(); i < size; i++) {
    286                 readAnnotationName();
    287                 skipValue();
    288             }
    289             break;
    290         case ENCODED_NULL:
    291             readNull();
    292             break;
    293         case ENCODED_BOOLEAN:
    294             readBoolean();
    295             break;
    296         default:
    297             throw new DexException("Unexpected type: " + Integer.toHexString(type));
    298         }
    299     }
    300 
    301     private void checkType(int expected) {
    302         if (peek() != expected) {
    303             throw new IllegalStateException(
    304                     String.format("Expected %x but was %x", expected, peek()));
    305         }
    306     }
    307 }
    308