1 /*
2  * Copyright (C) 2007 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 com.android.dx.dex.file;
18 
19 import com.android.dex.SizeOf;
20 import com.android.dx.rop.cst.CstMemberRef;
21 import com.android.dx.rop.cst.CstNat;
22 import com.android.dx.util.AnnotatedOutput;
23 import com.android.dx.util.Hex;
24 
25 /**
26  * Representation of a member (field or method) reference inside a
27  * Dalvik file.
28  */
29 public abstract class MemberIdItem extends IdItem {
30     /** {@code non-null;} the constant for the member */
31     private final CstMemberRef cst;
32 
33     /**
34      * Constructs an instance.
35      *
36      * @param cst {@code non-null;} the constant for the member
37      */
MemberIdItem(CstMemberRef cst)38     public MemberIdItem(CstMemberRef cst) {
39         super(cst.getDefiningClass());
40 
41         this.cst = cst;
42     }
43 
44     /** {@inheritDoc} */
45     @Override
writeSize()46     public int writeSize() {
47         return SizeOf.MEMBER_ID_ITEM;
48     }
49 
50     /** {@inheritDoc} */
51     @Override
addContents(DexFile file)52     public void addContents(DexFile file) {
53         super.addContents(file);
54 
55         StringIdsSection stringIds = file.getStringIds();
56         stringIds.intern(getRef().getNat().getName());
57     }
58 
59     /** {@inheritDoc} */
60     @Override
writeTo(DexFile file, AnnotatedOutput out)61     public final void writeTo(DexFile file, AnnotatedOutput out) {
62         TypeIdsSection typeIds = file.getTypeIds();
63         StringIdsSection stringIds = file.getStringIds();
64         CstNat nat = cst.getNat();
65         int classIdx = typeIds.indexOf(getDefiningClass());
66         int nameIdx = stringIds.indexOf(nat.getName());
67         int typoidIdx = getTypoidIdx(file);
68 
69         if (out.annotates()) {
70             out.annotate(0, indexString() + ' ' + cst.toHuman());
71             out.annotate(2, "  class_idx: " + Hex.u2(classIdx));
72             out.annotate(2, String.format("  %-10s %s", getTypoidName() + ':',
73                             Hex.u2(typoidIdx)));
74             out.annotate(4, "  name_idx:  " + Hex.u4(nameIdx));
75         }
76 
77         out.writeShort(classIdx);
78         out.writeShort(typoidIdx);
79         out.writeInt(nameIdx);
80     }
81 
82     /**
83      * Returns the index of the type-like thing associated with
84      * this item, in order that it may be written out. Subclasses must
85      * override this to get whatever it is they need to store.
86      *
87      * @param file {@code non-null;} the file being written
88      * @return the index in question
89      */
getTypoidIdx(DexFile file)90     protected abstract int getTypoidIdx(DexFile file);
91 
92     /**
93      * Returns the field name of the type-like thing associated with
94      * this item, for listing-generating purposes. Subclasses must override
95      * this.
96      *
97      * @return {@code non-null;} the name in question
98      */
getTypoidName()99     protected abstract String getTypoidName();
100 
101     /**
102      * Gets the member constant.
103      *
104      * @return {@code non-null;} the constant
105      */
getRef()106     public final CstMemberRef getRef() {
107         return cst;
108     }
109 }
110