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