1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.dex.file;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.annotation.Annotation;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.annotation.NameValuePair;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.Constant;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstAnnotation;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstArray;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstBoolean;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstByte;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstChar;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstDouble;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstEnumRef;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstFieldRef;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstFloat;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstInteger;
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstKnownNull;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstLiteralBits;
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstLong;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstMethodRef;
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstShort;
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstString;
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstType;
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.AnnotatedOutput;
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Collection;
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
4499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Handler for writing out {@code encoded_values} and parts
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * thereof.
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class ValueEncoder {
4899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code byte} */
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_BYTE = 0x00;
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code short} */
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_SHORT = 0x02;
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code char} */
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_CHAR = 0x03;
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code int} */
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_INT = 0x04;
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code long} */
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_LONG = 0x06;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code float} */
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_FLOAT = 0x10;
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code double} */
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_DOUBLE = 0x11;
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code string} */
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_STRING = 0x17;
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code type} */
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_TYPE = 0x18;
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code field} */
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_FIELD = 0x19;
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code method} */
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_METHOD = 0x1a;
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
8199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code enum} */
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_ENUM = 0x1b;
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
8499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code array} */
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_ARRAY = 0x1c;
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
8799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code annotation} */
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_ANNOTATION = 0x1d;
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code null} */
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_NULL = 0x1e;
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** annotation value type constant: {@code boolean} */
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final int VALUE_BOOLEAN = 0x1f;
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} file being written */
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final DexFile file;
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} output stream to write to */
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final AnnotatedOutput out;
101de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Construct an instance.
104de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
10599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param file {@code non-null;} file being written
10699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param out {@code non-null;} output stream to write to
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ValueEncoder(DexFile file, AnnotatedOutput out) {
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (file == null) {
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("file == null");
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (out == null) {
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("out == null");
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.file = file;
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.out = out;
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes out the encoded form of the given constant.
123de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
12499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param cst {@code non-null;} the constant to write
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void writeConstant(Constant cst) {
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int type = constantToValueType(cst);
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int arg;
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (type) {
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_BYTE:
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_SHORT:
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_INT:
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_LONG: {
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                long value = ((CstLiteralBits) cst).getLongBits();
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                writeSignedIntegralValue(type, value);
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_CHAR: {
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                long value = ((CstLiteralBits) cst).getLongBits();
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                writeUnsignedIntegralValue(type, value);
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_FLOAT: {
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Shift value left 32 so that right-zero-extension works.
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                long value = ((CstFloat) cst).getLongBits() << 32;
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                writeRightZeroExtendedValue(type, value);
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_DOUBLE: {
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                long value = ((CstDouble) cst).getLongBits();
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                writeRightZeroExtendedValue(type, value);
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_STRING: {
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int index = file.getStringIds().indexOf((CstString) cst);
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                writeUnsignedIntegralValue(type, (long) index);
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_TYPE: {
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int index = file.getTypeIds().indexOf((CstType) cst);
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                writeUnsignedIntegralValue(type, (long) index);
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_FIELD: {
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int index = file.getFieldIds().indexOf((CstFieldRef) cst);
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                writeUnsignedIntegralValue(type, (long) index);
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_METHOD: {
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int index = file.getMethodIds().indexOf((CstMethodRef) cst);
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                writeUnsignedIntegralValue(type, (long) index);
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_ENUM: {
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                CstFieldRef fieldRef = ((CstEnumRef) cst).getFieldRef();
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int index = file.getFieldIds().indexOf(fieldRef);
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                writeUnsignedIntegralValue(type, (long) index);
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_ARRAY: {
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                out.writeByte(type);
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                writeArray((CstArray) cst, false);
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_ANNOTATION: {
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                out.writeByte(type);
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                writeAnnotation(((CstAnnotation) cst).getAnnotation(),
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        false);
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_NULL: {
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                out.writeByte(type);
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case VALUE_BOOLEAN: {
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int value = ((CstBoolean) cst).getIntBits();
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                out.writeByte(type | (value << 5));
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default: {
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new RuntimeException("Shouldn't happen");
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the value type for the given constant.
209de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
21099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param cst {@code non-null;} the constant
21199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return the value type; one of the {@code VALUE_*} constants
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * defined by this class
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static int constantToValueType(Constant cst) {
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * TODO: Constant should probable have an associated enum, so this
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * can be a switch().
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cst instanceof CstByte) {
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_BYTE;
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstShort) {
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_SHORT;
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstChar) {
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_CHAR;
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstInteger) {
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_INT;
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstLong) {
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_LONG;
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstFloat) {
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_FLOAT;
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstDouble) {
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_DOUBLE;
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstString) {
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_STRING;
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstType) {
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_TYPE;
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstFieldRef) {
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_FIELD;
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstMethodRef) {
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_METHOD;
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstEnumRef) {
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_ENUM;
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstArray) {
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_ARRAY;
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstAnnotation) {
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_ANNOTATION;
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstKnownNull) {
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_NULL;
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstBoolean) {
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return VALUE_BOOLEAN;
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new RuntimeException("Shouldn't happen");
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes out the encoded form of the given array, that is, as
25899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * an {@code encoded_array} and not including a
25999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code value_type} prefix. If the output stream keeps
26099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * (debugging) annotations and {@code topLevel} is
26199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code true}, then this method will write (debugging)
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * annotations.
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
26499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param array {@code non-null;} array instance to write
26599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param topLevel {@code true} iff the given annotation is the
26699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * top-level annotation or {@code false} if it is a sub-annotation
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of some other annotation
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void writeArray(CstArray array, boolean topLevel) {
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean annotates = topLevel && out.annotates();
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CstArray.List list = ((CstArray) array).getList();
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int size = list.size();
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotates) {
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.annotate("  size: " + Hex.u4(size));
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
277de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
278dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson        out.writeUleb128(size);
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < size; i++) {
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Constant cst = list.get(i);
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (annotates) {
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                out.annotate("  [" + Integer.toHexString(i) + "] " +
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        constantToHuman(cst));
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            writeConstant(cst);
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotates) {
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.endAnnotation();
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes out the encoded form of the given annotation, that is,
29699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * as an {@code encoded_annotation} and not including a
29799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code value_type} prefix. If the output stream keeps
29899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * (debugging) annotations and {@code topLevel} is
29999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code true}, then this method will write (debugging)
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * annotations.
301de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
30299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param annotation {@code non-null;} annotation instance to write
30399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param topLevel {@code true} iff the given annotation is the
30499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * top-level annotation or {@code false} if it is a sub-annotation
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of some other annotation
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void writeAnnotation(Annotation annotation, boolean topLevel) {
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean annotates = topLevel && out.annotates();
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringIdsSection stringIds = file.getStringIds();
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TypeIdsSection typeIds = file.getTypeIds();
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CstType type = annotation.getType();
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int typeIdx = typeIds.indexOf(type);
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotates) {
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.annotate("  type_idx: " + Hex.u4(typeIdx) + " // " +
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    type.toHuman());
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
319de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
320dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson        out.writeUleb128(typeIds.indexOf(annotation.getType()));
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Collection<NameValuePair> pairs = annotation.getNameValuePairs();
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int size = pairs.size();
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotates) {
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.annotate("  size: " + Hex.u4(size));
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
329dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson        out.writeUleb128(size);
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int at = 0;
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (NameValuePair pair : pairs) {
333333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson            CstString name = pair.getName();
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int nameIdx = stringIds.indexOf(name);
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Constant value = pair.getValue();
336de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (annotates) {
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                out.annotate(0, "  elements[" + at + "]:");
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                at++;
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                out.annotate("    name_idx: " + Hex.u4(nameIdx) + " // " +
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        name.toHuman());
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
344dfc5e8e159e7df3efa47d553b7725be22839665dJesse Wilson            out.writeUleb128(nameIdx);
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (annotates) {
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                out.annotate("    value: " + constantToHuman(value));
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            writeConstant(value);
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (annotates) {
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.endAnnotation();
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
357de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the colloquial type name and human form of the type of the
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * given constant, when used as an encoded value.
361de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
36299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param cst {@code non-null;} the constant
36399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} its type name and human form
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static String constantToHuman(Constant cst) {
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int type = constantToValueType(cst);
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (type == VALUE_NULL) {
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return "null";
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuilder sb = new StringBuilder();
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(cst.typeName());
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(' ');
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(cst.toHuman());
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sb.toString();
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper for {@link #writeConstant}, which writes out the value
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for any signed integral type.
384de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param type the type constant
38699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param value {@code long} bits of the value
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void writeSignedIntegralValue(int type, long value) {
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Figure out how many bits are needed to represent the value,
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * including a sign bit: The bit count is subtracted from 65
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and not 64 to account for the sign bit. The xor operation
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * has the effect of leaving non-negative values alone and
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * unary complementing negative values (so that a leading zero
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * count always returns a useful number for our present
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * purpose).
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int requiredBits =
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            65 - Long.numberOfLeadingZeros(value ^ (value >> 63));
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Round up the requiredBits to a number of bytes.
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int requiredBytes = (requiredBits + 0x07) >> 3;
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Write the header byte, which includes the type and
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * requiredBytes - 1.
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeByte(type | ((requiredBytes - 1) << 5));
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Write the value, per se.
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (requiredBytes > 0) {
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.writeByte((byte) value);
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            value >>= 8;
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            requiredBytes--;
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper for {@link #writeConstant}, which writes out the value
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for any unsigned integral type.
421de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param type the type constant
42399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param value {@code long} bits of the value
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void writeUnsignedIntegralValue(int type, long value) {
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Figure out how many bits are needed to represent the value.
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int requiredBits = 64 - Long.numberOfLeadingZeros(value);
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (requiredBits == 0) {
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            requiredBits = 1;
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
431de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Round up the requiredBits to a number of bytes.
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int requiredBytes = (requiredBits + 0x07) >> 3;
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Write the header byte, which includes the type and
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * requiredBytes - 1.
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeByte(type | ((requiredBytes - 1) << 5));
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Write the value, per se.
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (requiredBytes > 0) {
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.writeByte((byte) value);
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            value >>= 8;
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            requiredBytes--;
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper for {@link #writeConstant}, which writes out a
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * right-zero-extended value.
452de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param type the type constant
45499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param value {@code long} bits of the value
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void writeRightZeroExtendedValue(int type, long value) {
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Figure out how many bits are needed to represent the value.
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int requiredBits = 64 - Long.numberOfTrailingZeros(value);
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (requiredBits == 0) {
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            requiredBits = 1;
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
462de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Round up the requiredBits to a number of bytes.
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int requiredBytes = (requiredBits + 0x07) >> 3;
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Scootch the first bits to be written down to the low-order bits.
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        value >>= 64 - (requiredBytes * 8);
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Write the header byte, which includes the type and
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * requiredBytes - 1.
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        out.writeByte(type | ((requiredBytes - 1) << 5));
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Write the value, per se.
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (requiredBytes > 0) {
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.writeByte((byte) value);
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            value >>= 8;
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            requiredBytes--;
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
48599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Helper for {@code addContents()} methods, which adds
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * contents for a particular {@link Annotation}, calling itself
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * recursively should it encounter a nested annotation.
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
489de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * @param file {@code non-null;} the file to add to
49099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param annotation {@code non-null;} the annotation to add contents for
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static void addContents(DexFile file, Annotation annotation) {
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TypeIdsSection typeIds = file.getTypeIds();
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringIdsSection stringIds = file.getStringIds();
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        typeIds.intern(annotation.getType());
497de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (NameValuePair pair : annotation.getNameValuePairs()) {
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            stringIds.intern(pair.getName());
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            addContents(file, pair.getValue());
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
50599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Helper for {@code addContents()} methods, which adds
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * contents for a particular constant, calling itself recursively
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * should it encounter a {@link CstArray} and calling {@link
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * #addContents(DexFile,Annotation)} recursively should it
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * encounter a {@link CstAnnotation}.
510de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
511de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * @param file {@code non-null;} the file to add to
51299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param cst {@code non-null;} the constant to add contents for
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static void addContents(DexFile file, Constant cst) {
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cst instanceof CstAnnotation) {
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            addContents(file, ((CstAnnotation) cst).getAnnotation());
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst instanceof CstArray) {
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            CstArray.List list = ((CstArray) cst).getList();
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int size = list.size();
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < size; i++) {
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                addContents(file, list.get(i));
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            file.internIfAppropriate(cst);
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
528