DexBackedField.java revision 0a18ea7f8b62e51945a79ac37802133a24c9a742
1/*
2 * Copyright 2012, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 *     * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *     * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32package org.jf.dexlib2.dexbacked;
33
34import org.jf.dexlib2.base.reference.BaseFieldReference;
35import org.jf.dexlib2.dexbacked.raw.FieldIdItem;
36import org.jf.dexlib2.dexbacked.util.AnnotationsDirectory;
37import org.jf.dexlib2.dexbacked.util.StaticInitialValueIterator;
38import org.jf.dexlib2.iface.ClassDef;
39import org.jf.dexlib2.iface.Field;
40import org.jf.dexlib2.iface.value.EncodedValue;
41
42import javax.annotation.Nonnull;
43import javax.annotation.Nullable;
44import java.util.Set;
45
46public class DexBackedField extends BaseFieldReference implements Field {
47    @Nonnull public final DexBackedDexFile dexFile;
48    @Nonnull public final ClassDef classDef;
49
50    public final int accessFlags;
51    @Nullable public final EncodedValue initialValue;
52    public final int annotationSetOffset;
53
54    public final int fieldIndex;
55
56    private int fieldIdItemOffset;
57
58    public DexBackedField(@Nonnull DexReader reader,
59                          @Nonnull DexBackedClassDef classDef,
60                          int previousFieldIndex,
61                          @Nonnull StaticInitialValueIterator staticInitialValueIterator,
62                          @Nonnull AnnotationsDirectory.AnnotationIterator annotationIterator) {
63        this.dexFile = reader.dexBuf;
64        this.classDef = classDef;
65
66        int fieldIndexDiff = reader.readSmallUleb128();
67        this.fieldIndex = fieldIndexDiff + previousFieldIndex;
68        this.accessFlags = reader.readSmallUleb128();
69
70        this.annotationSetOffset = annotationIterator.seekTo(fieldIndex);
71        this.initialValue = staticInitialValueIterator.getNextOrNull();
72    }
73
74    public DexBackedField(@Nonnull DexReader reader,
75                          @Nonnull DexBackedClassDef classDef,
76                          int previousFieldIndex,
77                          @Nonnull AnnotationsDirectory.AnnotationIterator annotationIterator) {
78        this.dexFile = reader.dexBuf;
79        this.classDef = classDef;
80
81        int fieldIndexDiff = reader.readSmallUleb128();
82        this.fieldIndex = fieldIndexDiff + previousFieldIndex;
83        this.accessFlags = reader.readSmallUleb128();
84
85        this.annotationSetOffset = annotationIterator.seekTo(fieldIndex);
86        this.initialValue = null;
87    }
88
89    @Nonnull
90    @Override
91    public String getName() {
92        return dexFile.getString(dexFile.readSmallUint(getFieldIdItemOffset() + FieldIdItem.NAME_OFFSET));
93    }
94
95    @Nonnull
96    @Override
97    public String getType() {
98        return dexFile.getType(dexFile.readUshort(getFieldIdItemOffset() + FieldIdItem.TYPE_OFFSET));
99    }
100
101    @Nonnull @Override public String getDefiningClass() { return classDef.getType(); }
102    @Override public int getAccessFlags() { return accessFlags; }
103    @Nullable @Override public EncodedValue getInitialValue() { return initialValue; }
104
105    @Nonnull
106    @Override
107    public Set<? extends DexBackedAnnotation> getAnnotations() {
108        return AnnotationsDirectory.getAnnotations(dexFile, annotationSetOffset);
109    }
110
111    /**
112     * Skips the reader over the specified number of encoded_field structures
113     *
114     * @param reader The reader to skip
115     * @param count The number of encoded_field structures to skip over
116     */
117    public static void skipAllFields(@Nonnull DexReader reader, int count) {
118        for (int i=0; i<count; i++) {
119            reader.skipUleb128();
120            reader.skipUleb128();
121        }
122    }
123
124    private int getFieldIdItemOffset() {
125        if (fieldIdItemOffset == 0) {
126            fieldIdItemOffset = dexFile.getFieldIdItemOffset(fieldIndex);
127        }
128        return fieldIdItemOffset;
129    }
130}
131