1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dex.reader; 18 19 import static dex.structure.DexEncodedValueType.*; 20 import dex.reader.DexFileReader.FieldIdItem; 21 import dex.structure.DexAnnotation; 22 import dex.structure.DexEncodedValue; 23 import dex.structure.DexEncodedValueType; 24 25 import java.util.ArrayList; 26 import java.util.List; 27 28 /* package */final class DexEncodedValueImpl implements DexEncodedValue { 29 30 private final DexBuffer buffer; 31 private byte typeAndValueArg; 32 private DexEncodedValueType type; 33 private String[] stringPool; 34 private Object value; 35 private int[] typeIds; 36 private final FieldIdItem[] fieldIdItems; 37 private final DexAnnotation annotation; 38 39 /** 40 * 41 * @param buffer 42 * the buffer with the correct position 43 * @param annotation 44 * @param stringPool 45 * @param fieldIdItems 46 */ DexEncodedValueImpl(DexBuffer buffer, DexAnnotation annotation, int[] typeIds, String[] stringPool, FieldIdItem[] fieldIdItems)47 public DexEncodedValueImpl(DexBuffer buffer, DexAnnotation annotation, 48 int[] typeIds, String[] stringPool, FieldIdItem[] fieldIdItems) { 49 this.buffer = buffer; 50 this.annotation = annotation; 51 this.typeIds = typeIds; 52 this.stringPool = stringPool; 53 this.fieldIdItems = fieldIdItems; 54 parseValue(); 55 } 56 parseValue()57 private void parseValue() { 58 typeAndValueArg = buffer.readUByte(); 59 type = DexEncodedValueType.get(typeAndValueArg); 60 int valueArg = DexEncodedValueType.valueArg(typeAndValueArg); 61 switch (type) { 62 case VALUE_BYTE: 63 value = getByteValue(valueArg); 64 break; 65 case VALUE_SHORT: 66 value = getShortValue(valueArg); 67 break; 68 case VALUE_CHAR: 69 value = getCharValue(valueArg); 70 break; 71 case VALUE_INT: 72 value = getIntValue(valueArg); 73 break; 74 case VALUE_LONG: 75 value = getLongValue(valueArg); 76 break; 77 case VALUE_FLOAT: 78 value = getFloatValue(valueArg); 79 break; 80 case VALUE_DOUBLE: 81 value = getDoubleValue(valueArg); 82 break; 83 case VALUE_STRING: 84 value = getStringValue(valueArg); 85 break; 86 case VALUE_TYPE: 87 value = getTypeValue(valueArg); 88 break; 89 case VALUE_FIELD: 90 value = getFieldValue(valueArg); 91 break; 92 case VALUE_METHOD: 93 value = getMethodValue(valueArg); 94 break; 95 case VALUE_ENUM: 96 value = getEnumValue(valueArg); 97 break; 98 case VALUE_ARRAY: 99 value = getArrayValue(valueArg); 100 break; 101 case VALUE_ANNOTATION: 102 value = getAnnotationValue(valueArg); 103 break; 104 case VALUE_NULL: 105 value = getNullValue(valueArg); 106 break; 107 case VALUE_BOOLEAN: 108 value = getBooleanValue(valueArg); 109 break; 110 default: 111 throw new IllegalArgumentException("DexEncodedValueType " + type 112 + " not recognized"); 113 } 114 } 115 116 /** 117 * VALUE_BOOLEAN 0x1f boolean (0...1) (none) one-bit value; 0 for false and 118 * 1 for true. The bit is represented in the value_arg. 119 */ getBooleanValue(int valueArg)120 private Boolean getBooleanValue(int valueArg) { 121 return valueArg == 1; 122 } 123 124 /** VALUE_NULL 0x1e (none; must be 0) (none) null reference value */ getNullValue(int valueArg)125 private Object getNullValue(int valueArg) { 126 return null; // must be like that! 127 } 128 129 /** 130 * VALUE_ANNOTATION 0x1d (none; must be 0) encoded_annotation a 131 * sub-annotation, in the format specified by "encoded_annotation Format" 132 * below. The size of the value is implicit in the encoding. 133 */ getAnnotationValue(int valueArg)134 private Object getAnnotationValue(int valueArg) { 135 // use the buffer directly to get adjusted offset 136 return new DexEncodedAnnotationImpl(buffer, annotation, typeIds, 137 stringPool, fieldIdItems); 138 } 139 140 /** 141 * VALUE_ARRAY 0x1c (none; must be 0) encoded_array an array of values, in 142 * the format specified by "encoded_array Format" below. The size of the 143 * value is implicit in the encoding. 144 */ getArrayValue(int valueArg)145 private List<DexEncodedValue> getArrayValue(int valueArg) { 146 int size = buffer.readUleb128(); 147 List<DexEncodedValue> values = new ArrayList<DexEncodedValue>(size); 148 for (int i = 0; i < size; i++) { 149 values.add(new DexEncodedValueImpl(buffer, annotation, typeIds, 150 stringPool, fieldIdItems)); 151 } 152 return values; 153 } 154 155 /** 156 * VALUE_ENUM 0x1b size - 1 (0...3) ubyte[size] unsigned (zero-extended) 157 * four-byte integer value, interpreted as an index into the field_ids 158 * section and representing the value of an enumerated type constant 159 */ getEnumValue(int valueArg)160 private Object getEnumValue(int valueArg) { 161 int fieldOffset = buffer.readInt(valueArg + 1); 162 FieldIdItem fieldIdItem = fieldIdItems[fieldOffset]; 163 // FORMAT La/b/E;!CONSTANT 164 String constantName = stringPool[fieldIdItem.name_idx]; 165 String typeName = stringPool[typeIds[fieldIdItem.type_idx]]; 166 return typeName + "!" + constantName; 167 } 168 169 /** 170 * VALUE_METHOD 0x1a size - 1 (0...3) ubyte[size] unsigned (zero-extended) 171 * four-byte integer value, interpreted as an index into the method_ids 172 * section and representing a reflective method value 173 */ getMethodValue(int valueArg)174 private Object getMethodValue(int valueArg) { 175 // FIXME lookup value 176 buffer.skip(valueArg + 1); 177 return null; 178 } 179 180 /** 181 * VALUE_FIELD 0x19 size - 1 (0...3) ubyte[size] unsigned (zero-extended) 182 * four-byte integer value, interpreted as an index into the field_ids 183 * section and representing a reflective field value 184 */ getFieldValue(int valueArg)185 private Object getFieldValue(int valueArg) { 186 int fieldOffset = buffer.readInt(valueArg + 1); 187 FieldIdItem fieldIdItem = fieldIdItems[fieldOffset]; 188 // FORMAT La/b/E;!CONSTANT 189 String fieldName = stringPool[fieldIdItem.name_idx]; 190 String typeName = stringPool[typeIds[fieldIdItem.type_idx]]; 191 return typeName + "!" + fieldName; 192 } 193 194 /** 195 * VALUE_TYPE 0x18 size - 1 (0...3) ubyte[size] unsigned (zero-extended) 196 * four-byte integer value, interpreted as an index into the type_ids 197 * section and representing a reflective type/class value 198 */ getTypeValue(int valueArg)199 private Object getTypeValue(int valueArg) { 200 valueArg++; // size - 1 (0...3) 201 // FIXME SPEC!! states: unsigned (zero-extended) four-byte integer value 202 return stringPool[typeIds[buffer.readInt(valueArg)]]; 203 } 204 205 /** 206 * VALUE_STRING 0x17 size - 1 (0...3) ubyte[size] unsigned (zero-extended) 207 * four-byte integer value, interpreted as an index into the string_ids 208 * section and representing a string value 209 */ getStringValue(int valueArg)210 private Object getStringValue(int valueArg) { 211 valueArg++; 212 return stringPool[buffer.readInt(valueArg)]; 213 } 214 215 /** 216 * VALUE_DOUBLE 0x11 size - 1 (0...7) ubyte[size] eight-byte bit pattern, 217 * zero-extended to the right, and interpreted as an IEEE754 64-bit floating 218 * point value 219 */ getDoubleValue(int valueArg)220 private Object getDoubleValue(int valueArg) { 221 return buffer.readDouble(valueArg + 1); 222 } 223 224 /** 225 * VALUE_FLOAT 0x10 size - 1 (0...3) ubyte[size] four-byte bit pattern, 226 * zero-extended to the right, and interpreted as an IEEE754 32-bit floating 227 * point value 228 */ getFloatValue(int valueArg)229 private Float getFloatValue(int valueArg) { 230 return buffer.readFloat(valueArg + 1); 231 } 232 233 /** 234 * VALUE_LONG 0x06 size - 1 (0...7) ubyte[size] signed eight-byte integer 235 * value, sign-extended 236 */ getLongValue(int valueArg)237 private Long getLongValue(int valueArg) { 238 return buffer.readLong(valueArg + 1); 239 } 240 241 /** 242 * VALUE_INT 0x04 size - 1 (0...3) ubyte[size] signed four-byte integer 243 * value, sign-extended 244 */ getIntValue(int valueArg)245 private Integer getIntValue(int valueArg) { 246 return buffer.readInt(valueArg + 1); 247 } 248 249 /** 250 * VALUE_CHAR 0x03 size - 1 (0...1) ubyte[size] unsigned two-byte integer 251 * value, zero-extended 252 */ getCharValue(int valueArg)253 private Character getCharValue(int valueArg) { 254 return buffer.readChar(valueArg + 1); 255 } 256 257 /** 258 * VALUE_SHORT 0x02 size - 1 (0...1) ubyte[size] signed two-byte integer 259 * value, sign-extended 260 */ getShortValue(int valueArg)261 private Short getShortValue(int valueArg) { 262 return buffer.readShort(valueArg + 1); 263 } 264 265 /** 266 * VALUE_BYTE 0x00 (none; must be 0) ubyte[1] signed one-byte integer value 267 */ getByteValue(int valueArg)268 private Byte getByteValue(int valueArg) { 269 assert valueArg == 0 : "Illegal valueArg for VALUE_BYTE: " + valueArg; 270 return null; 271 } 272 getType()273 public DexEncodedValueType getType() { 274 return type; 275 } 276 getValue()277 public Object getValue() { 278 return value; 279 } 280 281 @Override toString()282 public String toString() { 283 StringBuilder builder = new StringBuilder(); 284 builder.append("="); 285 if (type == VALUE_ARRAY) { 286 if (getValue() instanceof List<?>) { 287 List<?> values = (List<?>) getValue(); 288 for (Object object : values) { 289 DexEncodedValue val = (DexEncodedValue) object; 290 builder.append(val.getValue()); 291 } 292 } 293 } else { 294 builder.append(getValue()); 295 } 296 return builder.toString(); 297 } 298 } 299