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