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 
EncodedValueReader(ByteInput in)52     public EncodedValueReader(ByteInput in) {
53         this.in = in;
54     }
55 
EncodedValueReader(EncodedValue in)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      */
EncodedValueReader(ByteInput in, int knownType)66     public EncodedValueReader(ByteInput in, int knownType) {
67         this.in = in;
68         this.type = knownType;
69     }
70 
EncodedValueReader(EncodedValue in, int knownType)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      */
peek()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      */
readArray()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      */
readAnnotation()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      */
getAnnotationType()128     public int getAnnotationType() {
129         return annotationType;
130     }
131 
readAnnotationName()132     public int readAnnotationName() {
133         return Leb128.readUnsignedLeb128(in);
134     }
135 
readByte()136     public byte readByte() {
137         checkType(ENCODED_BYTE);
138         type = MUST_READ;
139         return (byte) EncodedValueCodec.readSignedInt(in, arg);
140     }
141 
readShort()142     public short readShort() {
143         checkType(ENCODED_SHORT);
144         type = MUST_READ;
145         return (short) EncodedValueCodec.readSignedInt(in, arg);
146     }
147 
readChar()148     public char readChar() {
149         checkType(ENCODED_CHAR);
150         type = MUST_READ;
151         return (char) EncodedValueCodec.readUnsignedInt(in, arg, false);
152     }
153 
readInt()154     public int readInt() {
155         checkType(ENCODED_INT);
156         type = MUST_READ;
157         return EncodedValueCodec.readSignedInt(in, arg);
158     }
159 
readLong()160     public long readLong() {
161         checkType(ENCODED_LONG);
162         type = MUST_READ;
163         return EncodedValueCodec.readSignedLong(in, arg);
164     }
165 
readFloat()166     public float readFloat() {
167         checkType(ENCODED_FLOAT);
168         type = MUST_READ;
169         return Float.intBitsToFloat(EncodedValueCodec.readUnsignedInt(in, arg, true));
170     }
171 
readDouble()172     public double readDouble() {
173         checkType(ENCODED_DOUBLE);
174         type = MUST_READ;
175         return Double.longBitsToDouble(EncodedValueCodec.readUnsignedLong(in, arg, true));
176     }
177 
readMethodType()178     public int readMethodType() {
179         checkType(ENCODED_METHOD_TYPE);
180         type = MUST_READ;
181         return EncodedValueCodec.readUnsignedInt(in, arg, false);
182     }
183 
readMethodHandle()184     public int readMethodHandle() {
185         checkType(ENCODED_METHOD_HANDLE);
186         type = MUST_READ;
187         return EncodedValueCodec.readUnsignedInt(in, arg, false);
188     }
189 
readString()190     public int readString() {
191         checkType(ENCODED_STRING);
192         type = MUST_READ;
193         return EncodedValueCodec.readUnsignedInt(in, arg, false);
194     }
195 
readType()196     public int readType() {
197         checkType(ENCODED_TYPE);
198         type = MUST_READ;
199         return EncodedValueCodec.readUnsignedInt(in, arg, false);
200     }
201 
readField()202     public int readField() {
203         checkType(ENCODED_FIELD);
204         type = MUST_READ;
205         return EncodedValueCodec.readUnsignedInt(in, arg, false);
206     }
207 
readEnum()208     public int readEnum() {
209         checkType(ENCODED_ENUM);
210         type = MUST_READ;
211         return EncodedValueCodec.readUnsignedInt(in, arg, false);
212     }
213 
readMethod()214     public int readMethod() {
215         checkType(ENCODED_METHOD);
216         type = MUST_READ;
217         return EncodedValueCodec.readUnsignedInt(in, arg, false);
218     }
219 
readNull()220     public void readNull() {
221         checkType(ENCODED_NULL);
222         type = MUST_READ;
223     }
224 
readBoolean()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      */
skipValue()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 
checkType(int expected)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