All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tinker.net.dongliu.apk.parser.struct.ResourceValue Maven / Gradle / Ivy

The newest version!
package tinker.net.dongliu.apk.parser.struct;

import tinker.net.dongliu.apk.parser.struct.resource.ResourceTable;
import tinker.net.dongliu.apk.parser.utils.ParseUtils;

import java.util.Locale;

/**
 * Resource entity, may be one entry in resource table, or string value
 * A apk only has one resource table.
 *
 * @author dongliu
 */
public abstract class ResourceValue {
    protected final int value;
    protected int   size;
    protected short dataType;

    protected ResourceValue(int value) {
        this.value = value;
    }

    public int getSize() {
        return size;
    }

    public short getDataType() {
        return dataType;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public void setDataType(short dataType) {
        this.dataType = dataType;
    }

    /**
     * get value as string
     * @return value
     */
    public abstract String toStringValue();

    public static ResourceValue decimal(int value) {
        return new DecimalResourceValue(value);
    }

    public static ResourceValue floatValue(int rawValue, float value) {
        return new FloatResourceValue(rawValue, value);
    }

    public static ResourceValue hexadecimal(int value) {
        return new HexadecimalResourceValue(value);
    }

    public static ResourceValue bool(int value) {
        return new BooleanResourceValue(value);
    }

    public static ResourceValue string(int value, StringPool stringPool) {
        return new StringResourceValue(value, stringPool);
    }

    public static ResourceValue reference(int value, ResourceTable resourceTable, Locale locale) {
        return new ReferenceResourceValue(value, resourceTable, locale);
    }

    public static ResourceValue nullValue() {
        return NullResourceValue.instance;
    }

    public static ResourceValue rgb(int value, int len) {
        return new RGBResourceValue(value, len);
    }

    public static ResourceValue dimension(int value) {
        return new DimensionValue(value);
    }

    public static ResourceValue fraction(int value) {
        return new FractionValue(value);
    }

    public static ResourceValue raw(int value, short type) {
        return new RawValue(value, type);
    }


    private static class DecimalResourceValue extends ResourceValue {

        private DecimalResourceValue(int value) {
            super(value);
        }

        @Override
        public String toStringValue() {
            return String.valueOf(value);
        }
    }

    private static class FloatResourceValue extends ResourceValue {
        private final float mValue;

        private FloatResourceValue(int rawValue, float value) {
            super(rawValue);
            mValue = value;
        }

        @Override
        public String toStringValue() {
            return String.valueOf(mValue);
        }
    }

    private static class HexadecimalResourceValue extends ResourceValue {

        private HexadecimalResourceValue(int value) {
            super(value);
        }

        @Override
        public String toStringValue() {
            return "0x" + Integer.toHexString(value);
        }
    }

    private static class BooleanResourceValue extends ResourceValue {

        private BooleanResourceValue(int value) {
            super(value);
        }

        @Override
        public String toStringValue() {
            return String.valueOf(value != 0);
        }
    }

    private static class StringResourceValue extends ResourceValue {
        private final StringPool stringPool;

        private StringResourceValue(int value, StringPool stringPool) {
            super(value);
            this.stringPool = stringPool;
        }

        @Override
        public String toStringValue() {
            if (value >= 0) {
                return stringPool.get(value);
            } else {
                return null;
            }
        }
    }

    // make public for cyclic reference detect
    public static class ReferenceResourceValue extends ResourceValue {
        private final ResourceTable resourceTable;
        private final Locale        locale;

        private ReferenceResourceValue(int value, ResourceTable resourceTable, Locale locale) {
            super(value);
            this.resourceTable = resourceTable;
            this.locale = locale;
        }

        @Override
        public String toString() {
            return toStringRepresent(false);
        }

        @Override
        public String toStringValue() {
            return toStringRepresent(true);
        }

        private String toStringRepresent(boolean fetchRealValue) {
            long resourceId = getReferenceResourceId();
            return ParseUtils.getResourceById(resourceId, resourceTable, locale, fetchRealValue);
        }

        public long getReferenceResourceId() {
            return value & 0xFFFFFFFFL;
        }
    }

    private static class NullResourceValue extends ResourceValue {
        private static final NullResourceValue instance = new NullResourceValue();

        private NullResourceValue() {
            super(-1);
        }

        @Override
        public String toStringValue() {
            return "";
        }
    }

    private static class RGBResourceValue extends ResourceValue {
        private final int len;

        private RGBResourceValue(int value, int len) {
            super(value);
            this.len = len;
        }

        @Override
        public String toStringValue() {
            StringBuilder sb = new StringBuilder();
            for (int i = len / 2 - 1; i >= 0; i--) {
                sb.append(Integer.toHexString((value >> i * 8) & 0xff));
            }
            return sb.toString();
        }
    }

    private static class DimensionValue extends ResourceValue {

        private DimensionValue(int value) {
            super(value);
        }

        @Override
        public String toStringValue() {
            short unit = (short) (value & 0xff);
            String unitStr;
            switch (unit) {
                case ResValue.ResDataCOMPLEX.UNIT_MM:
                    unitStr = "mm";
                    break;
                case ResValue.ResDataCOMPLEX.UNIT_PX:
                    unitStr = "px";
                    break;
                case ResValue.ResDataCOMPLEX.UNIT_DIP:
                    unitStr = "dp";
                    break;
                case ResValue.ResDataCOMPLEX.UNIT_SP:
                    unitStr = "sp";
                    break;
                case ResValue.ResDataCOMPLEX.UNIT_PT:
                    unitStr = "pt";
                    break;
                case ResValue.ResDataCOMPLEX.UNIT_IN:
                    unitStr = "in";
                    break;
                default:
                    unitStr = "unknown unit:0x" + Integer.toHexString(unit);
            }
            return (value >> 8) + unitStr;
        }
    }

    private static class FractionValue extends ResourceValue {

        private FractionValue(int value) {
            super(value);
        }

        @Override
        public String toStringValue() {
            // The low-order 4 bits of the data value specify the type of the fraction
            short type = (short) (value & 0xf);
            String pstr;
            switch (type) {
                case ResValue.ResDataCOMPLEX.UNIT_FRACTION:
                    pstr = "%";
                    break;
                case ResValue.ResDataCOMPLEX.UNIT_FRACTION_PARENT:
                    pstr = "%p";
                    break;
                default:
                    pstr = "unknown type:0x" + Integer.toHexString(type);
            }
            float f = Float.intBitsToFloat(value >> 4);
            return f + pstr;
        }
    }

    private static class RawValue extends ResourceValue {
        private final short dataType;

        private RawValue(int value, short dataType) {
            super(value);
            this.dataType = dataType;
        }

        @Override
        public String toStringValue() {
            return "{" + dataType + ":" + (value & 0xFFFFFFFFL) + "}";
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy