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