1ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson/*
2ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson * Copyright (C) 2011 The Android Open Source Project
3ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson *
4ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson * you may not use this file except in compliance with the License.
6ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson * You may obtain a copy of the License at
7ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson *
8ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
9ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson *
10ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson * Unless required by applicable law or agreed to in writing, software
11ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson * See the License for the specific language governing permissions and
14ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson * limitations under the License.
15ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson */
16ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson
17ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilsonpackage com.android.dx.io;
18ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson
19bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilsonimport com.android.dx.util.ByteInput;
20bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilsonimport com.android.dx.util.Leb128Utils;
21bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson
22ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson/**
23ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson * SAX-style reader for encoded values.
24ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson * TODO: convert this to a pull-style reader
25ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson */
26ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilsonpublic class EncodedValueReader {
27ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_BYTE = 0x00;
28ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_SHORT = 0x02;
29ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_CHAR = 0x03;
30ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_INT = 0x04;
31ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_LONG = 0x06;
32ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_FLOAT = 0x10;
33ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_DOUBLE = 0x11;
34ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_STRING = 0x17;
35ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_TYPE = 0x18;
36ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_FIELD = 0x19;
37ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_ENUM = 0x1b;
38ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_METHOD = 0x1a;
39ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_ARRAY = 0x1c;
40ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_ANNOTATION = 0x1d;
41ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_NULL = 0x1e;
42ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public static final int ENCODED_BOOLEAN = 0x1f;
43ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson
44bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson    protected final ByteInput in;
45ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson
46bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson    public EncodedValueReader(ByteInput in) {
47ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        this.in = in;
48ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    }
49ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson
50bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson    public EncodedValueReader(EncodedValue in) {
51bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson        this(in.asByteInput());
52bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson    }
53bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson
54ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public final void readArray() {
55bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson        int size = Leb128Utils.readUnsignedLeb128(in);
56ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        visitArray(size);
57ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson
58ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        for (int i = 0; i < size; i++) {
59ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            readValue();
60ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        }
61ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    }
62ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson
63ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public final void readAnnotation() {
64bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson        int typeIndex = Leb128Utils.readUnsignedLeb128(in);
65bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson        int size = Leb128Utils.readUnsignedLeb128(in);
66ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        visitAnnotation(typeIndex, size);
67ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson
68ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        for (int i = 0; i < size; i++) {
69bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson            visitAnnotationName(Leb128Utils.readUnsignedLeb128(in));
70ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            readValue();
71ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        }
72ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    }
73ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson
74ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    public final void readValue() {
75ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        int argAndType = in.readByte() & 0xff;
76ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        int type = argAndType & 0x1f;
77ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        int arg = (argAndType & 0xe0) >> 5;
78ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        int size = arg + 1;
79ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson
80ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        switch (type) {
81ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_BYTE:
82ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_SHORT:
83ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_CHAR:
84ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_INT:
85ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_LONG:
86ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_FLOAT:
87ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_DOUBLE:
88ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            visitPrimitive(argAndType, type, arg, size);
89ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            break;
90ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_STRING:
91ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            visitString(type, readIndex(in, size));
92ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            break;
93ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_TYPE:
94ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            visitType(type, readIndex(in, size));
95ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            break;
96ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_FIELD:
97ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_ENUM:
98ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            visitField(type, readIndex(in, size));
99ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            break;
100ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_METHOD:
101ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            visitMethod(type, readIndex(in, size));
102ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            break;
103ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_ARRAY:
104ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            visitArrayValue(argAndType);
105ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            readArray();
106ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            break;
107ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_ANNOTATION:
108ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            visitAnnotationValue(argAndType);
109ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            readAnnotation();
110ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            break;
111ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_NULL:
112ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            visitEncodedNull(argAndType);
113ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            break;
114ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        case ENCODED_BOOLEAN:
115ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            visitEncodedBoolean(argAndType);
116ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            break;
117ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        }
118ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    }
119ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson
120ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    protected void visitArray(int size) {}
121ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    protected void visitAnnotation(int typeIndex, int size) {}
122ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    protected void visitAnnotationName(int nameIndex) {}
123ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    protected void visitPrimitive(int argAndType, int type, int arg, int size) {
124ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        for (int i = 0; i < size; i++) {
125ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            in.readByte();
126ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        }
127ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    }
128ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    protected void visitString(int type, int index) {}
129ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    protected void visitType(int type, int index) {}
130ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    protected void visitField(int type, int index) {}
131ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    protected void visitMethod(int type, int index) {}
132ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    protected void visitArrayValue(int argAndType) {}
133ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    protected void visitAnnotationValue(int argAndType) {}
134ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    protected void visitEncodedBoolean(int argAndType) {}
135ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    protected void visitEncodedNull(int argAndType) {}
136ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson
137bd3dba4346223593ac6033a3d2a7d8ec6f20738bJesse Wilson    private int readIndex(ByteInput in, int byteCount) {
138ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        int result = 0;
139ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        int shift = 0;
140ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        for (int i = 0; i < byteCount; i++) {
141ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            result += (in.readByte() & 0xff) << shift;
142ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson            shift += 8;
143ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        }
144ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson        return result;
145ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson    }
146ae38a1e705253b53abf1beff7dc3467d52c58f32Jesse Wilson}
147