/*
* Copyright (c) 2009-2012 Panxiaobo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.dex2jar.reader;
import com.googlecode.dex2jar.DexException;
import com.googlecode.dex2jar.DexType;
import com.googlecode.dex2jar.reader.io.DataIn;
/**
* 读取静态常量
*
* @author <a href="mailto:pxb1988@gmail.com">Panxiaobo</a>
* @version $Rev$
*/
/* default */class Constant {
private static final int VALUE_BYTE = 0;
private static final int VALUE_SHORT = 2;
private static final int VALUE_CHAR = 3;
private static final int VALUE_INT = 4;
private static final int VALUE_LONG = 6;
private static final int VALUE_FLOAT = 16;
private static final int VALUE_DOUBLE = 17;
private static final int VALUE_STRING = 23;
private static final int VALUE_TYPE = 24;
private static final int VALUE_FIELD = 25;
private static final int VALUE_METHOD = 26;
private static final int VALUE_ENUM = 27;
private static final int VALUE_ARRAY = 28;
private static final int VALUE_ANNOTATION = 29;
private static final int VALUE_NULL = 30;
private static final int VALUE_BOOLEAN = 31;
/**
* 读取静态常量
*
* @param dex
* @param in
* @return
*/
public static Object ReadConstant(DexFileReader dex, DataIn in) {
int b = in.readUByte();
int type = b & 0x1f;
switch (type) {
case VALUE_BYTE:
return new Byte((byte) readIntBits(in, b));
case VALUE_SHORT:
return new Short((short) readIntBits(in, b));
case VALUE_INT:
return new Integer((int) readIntBits(in, b));
case VALUE_LONG:
return new Long(readIntBits(in, b));
case VALUE_CHAR:
return new Character((char) readUIntBits(in, b));
case VALUE_STRING:
return dex.getString((int) readUIntBits(in, b));
case VALUE_FLOAT:
return Float.intBitsToFloat((int) (readFloatBits(in, b) >> 32));
case VALUE_DOUBLE:
return Double.longBitsToDouble(readFloatBits(in, b));
case VALUE_NULL:
return null;
case VALUE_BOOLEAN: {
return new Boolean(((b >> 5) & 0x3) != 0);
}
case VALUE_TYPE: {
int type_id = (int) readUIntBits(in, b);
return new DexType(dex.getType(type_id));
}
case VALUE_ENUM: {
return dex.getField((int) readUIntBits(in, b));
}
case VALUE_METHOD: {
int method_id = (int) readUIntBits(in, b);
return dex.getMethod(method_id);
}
case VALUE_FIELD: {
int field_id = (int) readUIntBits(in, b);
return dex.getField(field_id);
}
case VALUE_ARRAY: {
int size = (int) in.readULeb128();
Object[] array = new Object[size];
for (int i = 0; i < size; i++) {
array[i] = ReadConstant(dex, in);
}
return array;
}
case VALUE_ANNOTATION: {
int _type = (int) in.readULeb128();
String _typeString = dex.getType(_type);
int size = (int) in.readULeb128();
Annotation ann = new Annotation(_typeString, true);
for (int i = 0; i < size; i++) {
int nameid = (int) in.readULeb128();
String nameString = dex.getString(nameid);
Object o = ReadConstant(dex, in);
ann.items.add(new Annotation.Item(nameString, o));
}
return ann;
}
default:
throw new DexException("Not support yet.");
}
}
public static long readIntBits(DataIn in, int before) {
int length = ((before >> 5) & 0x7) + 1;
long value = 0;
for (int j = 0; j < length; j++) {
value |= ((long) in.readUByte()) << (j * 8);
}
int shift = (8 - length) * 8;
return value << shift >> shift;
}
public static long readUIntBits(DataIn in, int before) {
int length = ((before >> 5) & 0x7) + 1;
long value = 0;
for (int j = 0; j < length; j++) {
value |= ((long) in.readUByte()) << (j * 8);
}
return value;
}
public static long readFloatBits(DataIn in, int before) {
int bytes = ((before >> 5) & 0x7) + 1;
long result = 0L;
for (int i = 0; i < bytes; ++i) {
result |= ((long) in.readUByte()) << (i * 8);
}
result <<= (8 - bytes) * 8;
return result;
}
}