• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * [The "BSD licence"]
3  * Copyright (c) 2010 Ben Gruver (JesusFreke)
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 
29 package org.jf.dexlib;
30 
31 import org.jf.dexlib.Util.AnnotatedOutput;
32 import org.jf.dexlib.Util.Input;
33 
34 public class TypeIdItem extends Item<TypeIdItem> {
35     private StringIdItem typeDescriptor;
36 
37     /**
38      * Creates a new uninitialized <code>TypeIdItem</code>
39      * @param dexFile The <code>DexFile</code> that this item belongs to
40      */
TypeIdItem(DexFile dexFile)41     protected TypeIdItem(DexFile dexFile) {
42         super(dexFile);
43     }
44 
45     /**
46      * Creates a new <code>TypeIdItem</code> for the given <code>StringIdItem</code>
47      * @param dexFile The <code>DexFile</code> that this item will belong to
48      * @param typeDescriptor The <code>StringIdItem</code> containing the type descriptor that
49      * this <code>TypeIdItem</code> represents
50      */
TypeIdItem(DexFile dexFile, StringIdItem typeDescriptor)51     private TypeIdItem(DexFile dexFile, StringIdItem typeDescriptor) {
52         super(dexFile);
53         this.typeDescriptor = typeDescriptor;
54     }
55 
56     /**
57      * Returns a <code>TypeIdItem</code> for the given values, and that has been interned into
58      * the given <code>DexFile</code>
59      * @param dexFile The <code>DexFile</code> that this item will belong to
60      * @param typeDescriptor The <code>StringIdItem</code> containing the type descriptor that
61      * this <code>TypeIdItem</code> represents
62      * @return a <code>TypeIdItem</code> for the given values, and that has been interned into
63      * the given <code>DexFile</code>
64      */
internTypeIdItem(DexFile dexFile, StringIdItem typeDescriptor)65     public static TypeIdItem internTypeIdItem(DexFile dexFile, StringIdItem typeDescriptor) {
66         TypeIdItem typeIdItem = new TypeIdItem(dexFile, typeDescriptor);
67         return dexFile.TypeIdsSection.intern(typeIdItem);
68     }
69 
70     /**
71      * Returns a <code>TypeIdItem</code> for the given values, and that has been interned into
72      * the given <code>DexFile</code>
73      * @param dexFile The <code>DexFile</code> that this item will belong to
74      * @param typeDescriptor The string containing the type descriptor that this
75      * <code>TypeIdItem</code> represents
76      * @return a <code>TypeIdItem</code> for the given values, and that has been interned into
77      * the given <code>DexFile</code>
78      */
internTypeIdItem(DexFile dexFile, String typeDescriptor)79     public static TypeIdItem internTypeIdItem(DexFile dexFile, String typeDescriptor) {
80         StringIdItem stringIdItem = StringIdItem.internStringIdItem(dexFile, typeDescriptor);
81         if (stringIdItem == null) {
82             return null;
83         }
84         TypeIdItem typeIdItem = new TypeIdItem(dexFile, stringIdItem);
85         return dexFile.TypeIdsSection.intern(typeIdItem);
86     }
87 
88     /**
89      * Looks up the <code>TypeIdItem</code> from the given <code>DexFile</code> for the given
90      * type descriptor
91      * @param dexFile the <code>Dexfile</code> to find the type in
92      * @param typeDescriptor The string containing the type descriptor to look up
93      * @return a <code>TypeIdItem</code> from the given <code>DexFile</code> for the given
94      * type descriptor, or null if it doesn't exist
95      */
lookupTypeIdItem(DexFile dexFile, String typeDescriptor)96     public static TypeIdItem lookupTypeIdItem(DexFile dexFile, String typeDescriptor) {
97         StringIdItem stringIdItem = StringIdItem.lookupStringIdItem(dexFile, typeDescriptor);
98         if (stringIdItem == null) {
99             return null;
100         }
101         TypeIdItem typeIdItem = new TypeIdItem(dexFile, stringIdItem);
102         return dexFile.TypeIdsSection.getInternedItem(typeIdItem);
103     }
104 
105     /** {@inheritDoc} */
readItem(Input in, ReadContext readContext)106     protected void readItem(Input in, ReadContext readContext) {
107         int stringIdIndex = in.readInt();
108         this.typeDescriptor = dexFile.StringIdsSection.getItemByIndex(stringIdIndex);
109     }
110 
111     /** {@inheritDoc} */
placeItem(int offset)112     protected int placeItem(int offset) {
113         return offset + 4;
114     }
115 
116     /** {@inheritDoc} */
writeItem(AnnotatedOutput out)117     protected void writeItem(AnnotatedOutput out) {
118         if (out.annotates()) {
119             out.annotate(4, typeDescriptor.getConciseIdentity());
120         }
121 
122         out.writeInt(typeDescriptor.getIndex());
123     }
124 
125     /** {@inheritDoc} */
getItemType()126     public ItemType getItemType() {
127         return ItemType.TYPE_TYPE_ID_ITEM;
128     }
129 
130     /** {@inheritDoc} */
getConciseIdentity()131     public String getConciseIdentity() {
132         return "type_id_item: " + getTypeDescriptor();
133     }
134 
135     /** {@inheritDoc} */
compareTo(TypeIdItem o)136     public int compareTo(TypeIdItem o) {
137         //sort by the index of the StringIdItem
138         return typeDescriptor.compareTo(o.typeDescriptor);
139     }
140 
141     /**
142      * Returns the type descriptor as a <code>String</code> for this type
143      * @return the type descriptor as a <code>String</code> for this type
144      */
getTypeDescriptor()145     public String getTypeDescriptor() {
146         return typeDescriptor.getStringValue();
147     }
148 
149     /**
150      * Returns the "shorty" representation of this type, used to create the shorty prototype string for a method
151      * @return the "shorty" representation of this type, used to create the shorty prototype string for a method
152      */
toShorty()153     public String toShorty() {
154         String type = getTypeDescriptor();
155         if (type.length() > 1) {
156             return "L";
157         } else {
158             return type;
159         }
160     }
161 
162     /**
163      * Calculates the number of 2-byte registers that an instance of this type requires
164      * @return The number of 2-byte registers that an instance of this type requires
165      */
getRegisterCount()166     public int getRegisterCount() {
167         String type = this.getTypeDescriptor();
168         /** Only the long and double primitive types are 2 words,
169          * everything else is a single word
170          */
171         if (type.charAt(0) == 'J' || type.charAt(0) == 'D') {
172             return 2;
173         } else {
174             return 1;
175         }
176     }
177 
178     @Override
hashCode()179     public int hashCode() {
180         return typeDescriptor.hashCode();
181     }
182 
183     @Override
equals(Object o)184     public boolean equals(Object o) {
185         if (this==o) {
186             return true;
187         }
188         if (o==null || !this.getClass().equals(o.getClass())) {
189             return false;
190         }
191 
192         //This assumes that the referenced items have been interned in both objects.
193         //This is a valid assumption because all outside code must use the static
194         //"getInterned..." style methods to make new items, and any item created
195         //internally is guaranteed to be interned
196         TypeIdItem other = (TypeIdItem)o;
197         return typeDescriptor == other.typeDescriptor;
198     }
199 }
200