EncodedValue.java revision 8543d8b6262a3f89b1c757fd9c39cac9487a5804
1/*
2 * [The "BSD licence"]
3 * Copyright (c) 2009 Ben Gruver
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29package org.jf.dexlib.EncodedValue;
30
31import org.jf.dexlib.CompositeField;
32import org.jf.dexlib.DexFile;
33import org.jf.dexlib.Field;
34import org.jf.dexlib.util.AnnotatedOutput;
35import org.jf.dexlib.util.Input;
36
37public class EncodedValue extends CompositeField<EncodedValue> {
38    private class ValueTypeArgField implements Field<ValueTypeArgField> {
39        private ValueType valueType;
40        private byte valueArg;
41
42        public ValueTypeArgField() {
43        }
44
45        public ValueTypeArgField(ValueType valueType) {
46            this.valueType = valueType;
47        }
48
49        public void writeTo(AnnotatedOutput out) {
50            out.annotate(1, "valuetype=" + Integer.toString(valueType.getMapValue()) + " valueArg=" + Integer.toString(valueArg));
51            byte value = (byte)(valueType.getMapValue() | (valueArg << 5));
52            out.writeByte(value);
53        }
54
55        public void readFrom(Input in) {
56            byte value = in.readByte();
57            valueType = ValueType.fromByte((byte)(value & 0x1F));
58            valueArg = (byte)((value & 0xFF) >>> 5);
59        }
60
61        public int place(int offset) {
62            return offset + 1;
63        }
64
65        public ValueType getValueType() {
66            return valueType;
67        }
68
69        public byte getValueArg() {
70            return valueArg;
71        }
72
73        public void copyTo(DexFile dexFile, ValueTypeArgField copy) {
74            copy.valueType = valueType;
75            copy.valueArg = valueArg;
76        }
77
78        public int hashCode() {
79            return valueType.hashCode() * 31 + ((Byte)valueArg).hashCode();
80        }
81
82        public boolean equals(Object o) {
83            if (!(o instanceof ValueTypeArgField)) {
84                return false;
85            }
86
87            ValueTypeArgField other = (ValueTypeArgField)o;
88            return valueType.equals(other.valueType) && (valueArg == other.valueArg);
89        }
90    }
91
92    private class EncodedValueSubFieldWrapper implements Field<EncodedValueSubFieldWrapper> {
93        private final DexFile dexFile;
94        private EncodedValueSubField subField;
95
96        public EncodedValueSubFieldWrapper(DexFile dexFile) {
97            this.dexFile = dexFile;
98        }
99
100        public EncodedValueSubFieldWrapper(DexFile dexFile, EncodedValueSubField subField) {
101            this.dexFile = dexFile;
102            this.subField = subField;
103        }
104
105        public void writeTo(AnnotatedOutput out) {
106            subField.writeTo(out);
107        }
108
109        public void readFrom(Input in) {
110            subField = EncodedValueSubFieldFactory.makeEncodedValueField(dexFile, getValueType());
111            subField.setInitialValueArg(getValueArg());
112            subField.readFrom(in);
113        }
114
115        public int place(int offset) {
116            return subField.place(offset);
117        }
118
119        public EncodedValueSubField getEncodedValueSubField() {
120            return subField;
121        }
122
123        public void copyTo(DexFile dexFile, EncodedValueSubFieldWrapper copy) {
124            EncodedValueSubField fieldCopy = EncodedValueSubFieldFactory.makeEncodedValueField(dexFile, getValueType());
125            copy.subField = fieldCopy;
126
127            //both fields should be the same type because they were both made with the a call to
128            //EncodedValueSubFieldFactory.makeEncodedValueField using the same value type.
129            subField.copyTo(dexFile, fieldCopy);
130        }
131
132        public int hashCode() {
133            return subField.hashCode();
134        }
135
136        public boolean equals(Object o) {
137            if (!(o instanceof EncodedValueSubFieldWrapper)) {
138                return false;
139            }
140
141            EncodedValueSubFieldWrapper other = (EncodedValueSubFieldWrapper)o;
142            return subField.equals(other.subField);
143        }
144    }
145
146    private final ValueTypeArgField valueTypeArg;
147    private final EncodedValueSubFieldWrapper encodedValue;
148
149    public EncodedValue(final DexFile dexFile) {
150        super("encoded_value");
151        fields = new Field[] {
152                valueTypeArg = new ValueTypeArgField(),
153                encodedValue = new EncodedValueSubFieldWrapper(dexFile)
154        };
155    }
156
157    public EncodedValue(final DexFile dexFile, EncodedValueSubField subField) {
158        super("encoded_value");
159        fields = new Field[] {
160                valueTypeArg = new ValueTypeArgField(subField.getValueType()),
161                encodedValue = new EncodedValueSubFieldWrapper(dexFile, subField)
162        };
163    }
164
165    public int place(int offset) {
166        offset = valueTypeArg.place(offset);
167        int ret = encodedValue.place(offset);
168
169        valueTypeArg.valueArg = encodedValue.getEncodedValueSubField().getValueArg();
170        return ret;
171    }
172
173    public ValueType getValueType() {
174        return valueTypeArg.getValueType();
175    }
176
177    public byte getValueArg() {
178        return valueTypeArg.getValueArg();
179    }
180
181    public EncodedValueSubField getValue() {
182        return encodedValue.getEncodedValueSubField();
183    }
184}
185