1 19 20 package jode.bytecode; 21 import java.io.DataOutputStream ; 22 import java.io.IOException ; 23 import java.util.Hashtable ; 24 25 30 public class GrowableConstantPool extends ConstantPool { 31 Hashtable entryToIndex = new Hashtable (); 32 boolean written; 33 34 37 private class Key { 38 int tag; 39 Object objData; 40 int intData; 41 42 public Key(int tag, Object objData, int intData) { 43 this.tag = tag; 44 this.objData = objData; 45 this.intData = intData; 46 } 47 48 public int hashCode() { 49 return tag ^ objData.hashCode() ^ intData; 50 } 51 52 public boolean equals(Object o) { 53 if (o instanceof Key) { 54 Key k = (Key) o; 55 return tag == k.tag && intData == k.intData 56 && objData.equals(k.objData); 57 } 58 return false; 59 } 60 } 61 62 public GrowableConstantPool () { 63 count = 1; 64 tags = new int[128]; 65 indices1 = new int[128]; 66 indices2 = new int[128]; 67 constants = new Object [128]; 68 written = false; 69 } 70 71 public final void grow(int wantedSize) { 72 if (written) 73 throw new IllegalStateException ("adding to written ConstantPool"); 74 if (tags.length < wantedSize) { 75 int newSize = Math.max(tags.length*2, wantedSize); 76 int[] tmpints = new int[newSize]; 77 System.arraycopy(tags, 0, tmpints, 0, count); 78 tags = tmpints; 79 tmpints = new int[newSize]; 80 System.arraycopy(indices1, 0, tmpints, 0, count); 81 indices1 = tmpints; 82 tmpints = new int[newSize]; 83 System.arraycopy(indices2, 0, tmpints, 0, count); 84 indices2 = tmpints; 85 Object [] tmpobjs = new Object [newSize]; 86 System.arraycopy(constants, 0, tmpobjs, 0, count); 87 constants = tmpobjs; 88 } 89 } 90 91 private int putConstant(int tag, Object constant) { 92 Key key = new Key(tag, constant, 0); 93 Integer index = (Integer ) entryToIndex.get(key); 94 if (index != null) 95 return index.intValue(); 96 int newIndex = count; 97 grow(count + 1); 98 tags[newIndex] = tag; 99 constants[newIndex] = constant; 100 entryToIndex.put(key, new Integer (newIndex)); 101 count++; 102 return newIndex; 103 } 104 105 private int putLongConstant(int tag, Object constant) { 106 Key key = new Key(tag, constant, 0); 107 Integer index = (Integer ) entryToIndex.get(key); 108 if (index != null) 109 return index.intValue(); 110 int newIndex = count; 111 grow(count + 2); 112 tags[newIndex] = tag; 113 tags[newIndex+1] = -tag; 114 constants[newIndex] = constant; 115 entryToIndex.put(key, new Integer (newIndex)); 116 count += 2; 117 return newIndex; 118 } 119 120 int putIndexed(int tag, Object obj1, int index1, int index2) { 121 Key key = new Key(tag, obj1, index2); 122 Integer indexObj = (Integer ) entryToIndex.get(key); 123 if (indexObj != null) { 124 125 int index = indexObj.intValue(); 126 indices1[index] = index1; 127 indices2[index] = index2; 128 return index; 129 } 130 grow(count+1); 131 tags[count] = tag; 132 indices1[count] = index1; 133 indices2[count] = index2; 134 entryToIndex.put(key, new Integer (count)); 135 return count++; 136 } 137 138 public final int putUTF8(String utf) { 139 return putConstant(UTF8, utf); 140 } 141 142 public int putClassName(String name) { 143 name = name.replace('.','/'); 144 TypeSignature.checkTypeSig("L"+name+";"); 145 return putIndexed(CLASS, name, putUTF8(name), 0); 146 } 147 148 public int putClassType(String name) { 149 TypeSignature.checkTypeSig(name); 150 if (name.charAt(0) == 'L') 151 name = name.substring(1, name.length()-1); 152 else if (name.charAt(0) != '[') 153 throw new IllegalArgumentException ("wrong class type: "+name); 154 return putIndexed(CLASS, name, putUTF8(name), 0); 155 } 156 157 public int putRef(int tag, Reference ref) { 158 String className = ref.getClazz(); 159 String typeSig = ref.getType(); 160 if (tag == FIELDREF) 161 TypeSignature.checkTypeSig(typeSig); 162 else 163 TypeSignature.checkMethodTypeSig(typeSig); 164 165 166 int classIndex = putClassType(className); 167 int nameIndex = putUTF8(ref.getName()); 168 int typeIndex = putUTF8(typeSig); 169 int nameTypeIndex = putIndexed(NAMEANDTYPE, 170 ref.getName(), nameIndex, typeIndex); 171 return putIndexed(tag, className, classIndex, nameTypeIndex); 172 } 173 174 180 public int putConstant(Object c) { 181 if (c instanceof String ) { 182 return putIndexed(STRING, c, putUTF8((String ) c), 0); 183 } else { 184 int tag; 185 if (c instanceof Integer ) 186 tag = INTEGER; 187 else if (c instanceof Float ) 188 tag = FLOAT; 189 else 190 throw new IllegalArgumentException 191 ("illegal constant " + c + " of type: " + c.getClass()); 192 return putConstant(tag, c); 193 } 194 } 195 196 202 public int putLongConstant(Object c) { 203 int tag; 204 if (c instanceof Long ) 205 tag = LONG; 206 else if (c instanceof Double ) 207 tag = DOUBLE; 208 else 209 throw new IllegalArgumentException 210 ("illegal long constant " + c + " of type: " + c.getClass()); 211 return putLongConstant(tag, c); 212 } 213 214 220 public int reserveConstant(Object c) { 221 if (c instanceof String ) { 222 return putIndexed(STRING, c, -1, 0); 223 } else { 224 return putConstant(c); 225 } 226 } 227 228 234 public int reserveLongConstant(Object c) { 235 return putLongConstant(c); 236 } 237 238 public int copyConstant(ConstantPool cp, int index) 239 throws ClassFormatException { 240 return putConstant(cp.getConstant(index)); 241 } 242 243 public void write(DataOutputStream stream) 244 throws IOException { 245 written = true; 246 stream.writeShort(count); 247 for (int i=1; i< count; i++) { 248 int tag = tags[i]; 249 stream.writeByte(tag); 250 switch (tag) { 251 case CLASS: 252 stream.writeShort(indices1[i]); 253 break; 254 case FIELDREF: 255 case METHODREF: 256 case INTERFACEMETHODREF: 257 stream.writeShort(indices1[i]); 258 stream.writeShort(indices2[i]); 259 break; 260 case STRING: 261 stream.writeShort(indices1[i]); 262 break; 263 case INTEGER: 264 stream.writeInt(((Integer )constants[i]).intValue()); 265 break; 266 case FLOAT: 267 stream.writeFloat(((Float )constants[i]).floatValue()); 268 break; 269 case LONG: 270 stream.writeLong(((Long )constants[i]).longValue()); 271 i++; 272 break; 273 case DOUBLE: 274 stream.writeDouble(((Double )constants[i]).doubleValue()); 275 i++; 276 break; 277 case NAMEANDTYPE: 278 stream.writeShort(indices1[i]); 279 stream.writeShort(indices2[i]); 280 break; 281 case UTF8: 282 stream.writeUTF((String )constants[i]); 283 break; 284 default: 285 throw new ClassFormatException("unknown constant tag"); 286 } 287 } 288 } 289 } 290 | Popular Tags |