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