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
17package com.android.dx.io;
18
19import com.android.dx.util.ByteInput;
20import com.android.dx.util.Leb128Utils;
21
22/**
23 * SAX-style reader for encoded values.
24 * TODO: convert this to a pull-style reader
25 */
26public class EncodedValueReader {
27    public static final int ENCODED_BYTE = 0x00;
28    public static final int ENCODED_SHORT = 0x02;
29    public static final int ENCODED_CHAR = 0x03;
30    public static final int ENCODED_INT = 0x04;
31    public static final int ENCODED_LONG = 0x06;
32    public static final int ENCODED_FLOAT = 0x10;
33    public static final int ENCODED_DOUBLE = 0x11;
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    protected final ByteInput in;
45
46    public EncodedValueReader(ByteInput in) {
47        this.in = in;
48    }
49
50    public EncodedValueReader(EncodedValue in) {
51        this(in.asByteInput());
52    }
53
54    public final void readArray() {
55        int size = Leb128Utils.readUnsignedLeb128(in);
56        visitArray(size);
57
58        for (int i = 0; i < size; i++) {
59            readValue();
60        }
61    }
62
63    public final void readAnnotation() {
64        int typeIndex = Leb128Utils.readUnsignedLeb128(in);
65        int size = Leb128Utils.readUnsignedLeb128(in);
66        visitAnnotation(typeIndex, size);
67
68        for (int i = 0; i < size; i++) {
69            visitAnnotationName(Leb128Utils.readUnsignedLeb128(in));
70            readValue();
71        }
72    }
73
74    public final void readValue() {
75        int argAndType = in.readByte() & 0xff;
76        int type = argAndType & 0x1f;
77        int arg = (argAndType & 0xe0) >> 5;
78        int size = arg + 1;
79
80        switch (type) {
81        case ENCODED_BYTE:
82        case ENCODED_SHORT:
83        case ENCODED_CHAR:
84        case ENCODED_INT:
85        case ENCODED_LONG:
86        case ENCODED_FLOAT:
87        case ENCODED_DOUBLE:
88            visitPrimitive(argAndType, type, arg, size);
89            break;
90        case ENCODED_STRING:
91            visitString(type, readIndex(in, size));
92            break;
93        case ENCODED_TYPE:
94            visitType(type, readIndex(in, size));
95            break;
96        case ENCODED_FIELD:
97        case ENCODED_ENUM:
98            visitField(type, readIndex(in, size));
99            break;
100        case ENCODED_METHOD:
101            visitMethod(type, readIndex(in, size));
102            break;
103        case ENCODED_ARRAY:
104            visitArrayValue(argAndType);
105            readArray();
106            break;
107        case ENCODED_ANNOTATION:
108            visitAnnotationValue(argAndType);
109            readAnnotation();
110            break;
111        case ENCODED_NULL:
112            visitEncodedNull(argAndType);
113            break;
114        case ENCODED_BOOLEAN:
115            visitEncodedBoolean(argAndType);
116            break;
117        }
118    }
119
120    protected void visitArray(int size) {}
121    protected void visitAnnotation(int typeIndex, int size) {}
122    protected void visitAnnotationName(int nameIndex) {}
123    protected void visitPrimitive(int argAndType, int type, int arg, int size) {
124        for (int i = 0; i < size; i++) {
125            in.readByte();
126        }
127    }
128    protected void visitString(int type, int index) {}
129    protected void visitType(int type, int index) {}
130    protected void visitField(int type, int index) {}
131    protected void visitMethod(int type, int index) {}
132    protected void visitArrayValue(int argAndType) {}
133    protected void visitAnnotationValue(int argAndType) {}
134    protected void visitEncodedBoolean(int argAndType) {}
135    protected void visitEncodedNull(int argAndType) {}
136
137    private int readIndex(ByteInput in, int byteCount) {
138        int result = 0;
139        int shift = 0;
140        for (int i = 0; i < byteCount; i++) {
141            result += (in.readByte() & 0xff) << shift;
142            shift += 8;
143        }
144        return result;
145    }
146}
147