1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/*
2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2008 The Android Open Source Project
3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License");
5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License.
6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at
7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *      http://www.apache.org/licenses/LICENSE-2.0
9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software
11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS,
12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and
14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License.
15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.dex.file;
18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.annotation.Annotation;
20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.annotation.NameValuePair;
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.Constant;
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstAnnotation;
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstArray;
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstBoolean;
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstByte;
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstChar;
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstDouble;
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstEnumRef;
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstFieldRef;
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstFloat;
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstInteger;
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstKnownNull;
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstLiteralBits;
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstLong;
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstMethodRef;
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstShort;
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstString;
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstType;
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstUtf8;
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.AnnotatedOutput;
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.Hex;
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.Collection;
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Handler for writing out {@code encoded_values} and parts
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * thereof.
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class ValueEncoder {
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code byte} */
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_BYTE = 0x00;
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code short} */
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_SHORT = 0x02;
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code char} */
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_CHAR = 0x03;
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code int} */
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_INT = 0x04;
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code long} */
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_LONG = 0x06;
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code float} */
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_FLOAT = 0x10;
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code double} */
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_DOUBLE = 0x11;
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code string} */
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_STRING = 0x17;
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code type} */
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_TYPE = 0x18;
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code field} */
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_FIELD = 0x19;
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code method} */
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_METHOD = 0x1a;
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code enum} */
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_ENUM = 0x1b;
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code array} */
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_ARRAY = 0x1c;
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code annotation} */
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_ANNOTATION = 0x1d;
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code null} */
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_NULL = 0x1e;
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** annotation value type constant: {@code boolean} */
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final int VALUE_BOOLEAN = 0x1f;
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} file being written */
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final DexFile file;
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} output stream to write to */
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final AnnotatedOutput out;
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Construct an instance.
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param file {@code non-null;} file being written
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param out {@code non-null;} output stream to write to
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public ValueEncoder(DexFile file, AnnotatedOutput out) {
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (file == null) {
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("file == null");
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (out == null) {
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("out == null");
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.file = file;
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.out = out;
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Writes out the encoded form of the given constant.
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param cst {@code non-null;} the constant to write
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void writeConstant(Constant cst) {
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int type = constantToValueType(cst);
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int arg;
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        switch (type) {
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_BYTE:
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_SHORT:
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_INT:
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_LONG: {
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                long value = ((CstLiteralBits) cst).getLongBits();
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                writeSignedIntegralValue(type, value);
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                break;
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_CHAR: {
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                long value = ((CstLiteralBits) cst).getLongBits();
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                writeUnsignedIntegralValue(type, value);
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                break;
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_FLOAT: {
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                // Shift value left 32 so that right-zero-extension works.
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                long value = ((CstFloat) cst).getLongBits() << 32;
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                writeRightZeroExtendedValue(type, value);
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                break;
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_DOUBLE: {
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                long value = ((CstDouble) cst).getLongBits();
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                writeRightZeroExtendedValue(type, value);
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                break;
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_STRING: {
158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                int index = file.getStringIds().indexOf((CstString) cst);
159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                writeUnsignedIntegralValue(type, (long) index);
160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                break;
161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_TYPE: {
163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                int index = file.getTypeIds().indexOf((CstType) cst);
164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                writeUnsignedIntegralValue(type, (long) index);
165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                break;
166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_FIELD: {
168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                int index = file.getFieldIds().indexOf((CstFieldRef) cst);
169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                writeUnsignedIntegralValue(type, (long) index);
170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                break;
171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_METHOD: {
173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                int index = file.getMethodIds().indexOf((CstMethodRef) cst);
174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                writeUnsignedIntegralValue(type, (long) index);
175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                break;
176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_ENUM: {
178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                CstFieldRef fieldRef = ((CstEnumRef) cst).getFieldRef();
179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                int index = file.getFieldIds().indexOf(fieldRef);
180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                writeUnsignedIntegralValue(type, (long) index);
181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                break;
182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_ARRAY: {
184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.writeByte(type);
185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                writeArray((CstArray) cst, false);
186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                break;
187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_ANNOTATION: {
189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.writeByte(type);
190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                writeAnnotation(((CstAnnotation) cst).getAnnotation(),
191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                        false);
192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                break;
193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_NULL: {
195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.writeByte(type);
196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                break;
197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            case VALUE_BOOLEAN: {
199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                int value = ((CstBoolean) cst).getIntBits();
200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.writeByte(type | (value << 5));
201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                break;
202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            default: {
204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                throw new RuntimeException("Shouldn't happen");
205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the value type for the given constant.
211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param cst {@code non-null;} the constant
213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return the value type; one of the {@code VALUE_*} constants
214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * defined by this class
215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static int constantToValueType(Constant cst) {
217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /*
218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * TODO: Constant should probable have an associated enum, so this
219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * can be a switch().
220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (cst instanceof CstByte) {
222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_BYTE;
223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstShort) {
224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_SHORT;
225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstChar) {
226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_CHAR;
227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstInteger) {
228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_INT;
229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstLong) {
230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_LONG;
231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstFloat) {
232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_FLOAT;
233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstDouble) {
234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_DOUBLE;
235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstString) {
236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_STRING;
237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstType) {
238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_TYPE;
239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstFieldRef) {
240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_FIELD;
241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstMethodRef) {
242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_METHOD;
243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstEnumRef) {
244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_ENUM;
245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstArray) {
246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_ARRAY;
247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstAnnotation) {
248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_ANNOTATION;
249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstKnownNull) {
250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_NULL;
251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstBoolean) {
252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return VALUE_BOOLEAN;
253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else {
254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new RuntimeException("Shouldn't happen");
255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Writes out the encoded form of the given array, that is, as
260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * an {@code encoded_array} and not including a
261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code value_type} prefix. If the output stream keeps
262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * (debugging) annotations and {@code topLevel} is
263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code true}, then this method will write (debugging)
264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * annotations.
265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param array {@code non-null;} array instance to write
267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param topLevel {@code true} iff the given annotation is the
268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * top-level annotation or {@code false} if it is a sub-annotation
269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * of some other annotation
270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void writeArray(CstArray array, boolean topLevel) {
272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        boolean annotates = topLevel && out.annotates();
273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        CstArray.List list = ((CstArray) array).getList();
274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int size = list.size();
275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (annotates) {
277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate("  size: " + Hex.u4(size));
278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeUnsignedLeb128(size);
281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < size; i++) {
283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            Constant cst = list.get(i);
284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (annotates) {
285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.annotate("  [" + Integer.toHexString(i) + "] " +
286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                        constantToHuman(cst));
287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            writeConstant(cst);
289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (annotates) {
292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.endAnnotation();
293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Writes out the encoded form of the given annotation, that is,
298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * as an {@code encoded_annotation} and not including a
299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code value_type} prefix. If the output stream keeps
300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * (debugging) annotations and {@code topLevel} is
301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code true}, then this method will write (debugging)
302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * annotations.
303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param annotation {@code non-null;} annotation instance to write
305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param topLevel {@code true} iff the given annotation is the
306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * top-level annotation or {@code false} if it is a sub-annotation
307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * of some other annotation
308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void writeAnnotation(Annotation annotation, boolean topLevel) {
310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        boolean annotates = topLevel && out.annotates();
311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        StringIdsSection stringIds = file.getStringIds();
312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        TypeIdsSection typeIds = file.getTypeIds();
313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        CstType type = annotation.getType();
315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int typeIdx = typeIds.indexOf(type);
316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (annotates) {
318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate("  type_idx: " + Hex.u4(typeIdx) + " // " +
319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    type.toHuman());
320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeUnsignedLeb128(typeIds.indexOf(annotation.getType()));
323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        Collection<NameValuePair> pairs = annotation.getNameValuePairs();
325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int size = pairs.size();
326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (annotates) {
328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.annotate("  size: " + Hex.u4(size));
329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeUnsignedLeb128(size);
332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int at = 0;
334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (NameValuePair pair : pairs) {
335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            CstUtf8 name = pair.getName();
336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            int nameIdx = stringIds.indexOf(name);
337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            Constant value = pair.getValue();
338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (annotates) {
340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.annotate(0, "  elements[" + at + "]:");
341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                at++;
342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.annotate("    name_idx: " + Hex.u4(nameIdx) + " // " +
343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                        name.toHuman());
344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.writeUnsignedLeb128(nameIdx);
347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (annotates) {
349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                out.annotate("    value: " + constantToHuman(value));
350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            writeConstant(value);
353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (annotates) {
356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.endAnnotation();
357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the colloquial type name and human form of the type of the
362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * given constant, when used as an encoded value.
363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param cst {@code non-null;} the constant
365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} its type name and human form
366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String constantToHuman(Constant cst) {
368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int type = constantToValueType(cst);
369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (type == VALUE_NULL) {
371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return "null";
372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        StringBuilder sb = new StringBuilder();
375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(cst.typeName());
377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(' ');
378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(cst.toHuman());
379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return sb.toString();
381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Helper for {@link #writeConstant}, which writes out the value
385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * for any signed integral type.
386917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
387917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param type the type constant
388917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param value {@code long} bits of the value
389917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
390917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private void writeSignedIntegralValue(int type, long value) {
391917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /*
392917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Figure out how many bits are needed to represent the value,
393917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * including a sign bit: The bit count is subtracted from 65
394917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * and not 64 to account for the sign bit. The xor operation
395917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * has the effect of leaving non-negative values alone and
396917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * unary complementing negative values (so that a leading zero
397917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * count always returns a useful number for our present
398917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * purpose).
399917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
400917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int requiredBits =
401917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            65 - Long.numberOfLeadingZeros(value ^ (value >> 63));
402917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
403917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // Round up the requiredBits to a number of bytes.
404917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int requiredBytes = (requiredBits + 0x07) >> 3;
405917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
406917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /*
407917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Write the header byte, which includes the type and
408917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * requiredBytes - 1.
409917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
410917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeByte(type | ((requiredBytes - 1) << 5));
411917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
412917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // Write the value, per se.
413917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        while (requiredBytes > 0) {
414917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.writeByte((byte) value);
415917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            value >>= 8;
416917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            requiredBytes--;
417917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
418917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
419917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
420917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
421917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Helper for {@link #writeConstant}, which writes out the value
422917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * for any unsigned integral type.
423917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
424917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param type the type constant
425917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param value {@code long} bits of the value
426917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
427917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private void writeUnsignedIntegralValue(int type, long value) {
428917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // Figure out how many bits are needed to represent the value.
429917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int requiredBits = 64 - Long.numberOfLeadingZeros(value);
430917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (requiredBits == 0) {
431917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            requiredBits = 1;
432917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
433917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
434917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // Round up the requiredBits to a number of bytes.
435917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int requiredBytes = (requiredBits + 0x07) >> 3;
436917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
437917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /*
438917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Write the header byte, which includes the type and
439917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * requiredBytes - 1.
440917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
441917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeByte(type | ((requiredBytes - 1) << 5));
442917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
443917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // Write the value, per se.
444917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        while (requiredBytes > 0) {
445917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.writeByte((byte) value);
446917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            value >>= 8;
447917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            requiredBytes--;
448917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
449917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
450917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
451917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
452917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Helper for {@link #writeConstant}, which writes out a
453917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * right-zero-extended value.
454917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
455917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param type the type constant
456917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param value {@code long} bits of the value
457917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
458917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private void writeRightZeroExtendedValue(int type, long value) {
459917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // Figure out how many bits are needed to represent the value.
460917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int requiredBits = 64 - Long.numberOfTrailingZeros(value);
461917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (requiredBits == 0) {
462917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            requiredBits = 1;
463917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
464917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
465917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // Round up the requiredBits to a number of bytes.
466917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int requiredBytes = (requiredBits + 0x07) >> 3;
467917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
468917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // Scootch the first bits to be written down to the low-order bits.
469917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        value >>= 64 - (requiredBytes * 8);
470917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
471917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /*
472917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Write the header byte, which includes the type and
473917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * requiredBytes - 1.
474917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
475917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        out.writeByte(type | ((requiredBytes - 1) << 5));
476917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
477917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // Write the value, per se.
478917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        while (requiredBytes > 0) {
479917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            out.writeByte((byte) value);
480917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            value >>= 8;
481917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            requiredBytes--;
482917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
483917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
484917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
485917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
486917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
487917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Helper for {@code addContents()} methods, which adds
488917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * contents for a particular {@link Annotation}, calling itself
489917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * recursively should it encounter a nested annotation.
490917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
491917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param file {@code non-null;} the file to add to
492917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param annotation {@code non-null;} the annotation to add contents for
493917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
494917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static void addContents(DexFile file, Annotation annotation) {
495917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        TypeIdsSection typeIds = file.getTypeIds();
496917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        StringIdsSection stringIds = file.getStringIds();
497917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
498917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        typeIds.intern(annotation.getType());
499917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
500917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (NameValuePair pair : annotation.getNameValuePairs()) {
501917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            stringIds.intern(pair.getName());
502917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            addContents(file, pair.getValue());
503917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
504917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
505917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
506917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
507917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Helper for {@code addContents()} methods, which adds
508917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * contents for a particular constant, calling itself recursively
509917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * should it encounter a {@link CstArray} and calling {@link
510917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * #addContents(DexFile,Annotation)} recursively should it
511917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * encounter a {@link CstAnnotation}.
512917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
513917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param file {@code non-null;} the file to add to
514917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param cst {@code non-null;} the constant to add contents for
515917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
516917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static void addContents(DexFile file, Constant cst) {
517917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (cst instanceof CstAnnotation) {
518917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            addContents(file, ((CstAnnotation) cst).getAnnotation());
519917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (cst instanceof CstArray) {
520917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            CstArray.List list = ((CstArray) cst).getList();
521917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            int size = list.size();
522917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            for (int i = 0; i < size; i++) {
523917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                addContents(file, list.get(i));
524917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
525917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else {
526917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            file.internIfAppropriate(cst);
527917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
528917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
529917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
530