1 35 36 package org.logicalcobwebs.asm; 37 38 import java.lang.reflect.Method ; 39 40 44 45 public class Type { 46 47 50 51 public final static int VOID = 0; 52 53 56 57 public final static int BOOLEAN = 1; 58 59 62 63 public final static int CHAR = 2; 64 65 68 69 public final static int BYTE = 3; 70 71 74 75 public final static int SHORT = 4; 76 77 80 81 public final static int INT = 5; 82 83 86 87 public final static int FLOAT = 6; 88 89 92 93 public final static int LONG = 7; 94 95 98 99 public final static int DOUBLE = 8; 100 101 104 105 public final static int ARRAY = 9; 106 107 110 111 public final static int OBJECT = 10; 112 113 116 117 public final static Type VOID_TYPE = new Type(VOID); 118 119 122 123 public final static Type BOOLEAN_TYPE = new Type(BOOLEAN); 124 125 128 129 public final static Type CHAR_TYPE = new Type(CHAR); 130 131 134 135 public final static Type BYTE_TYPE = new Type(BYTE); 136 137 140 141 public final static Type SHORT_TYPE = new Type(SHORT); 142 143 146 147 public final static Type INT_TYPE = new Type(INT); 148 149 152 153 public final static Type FLOAT_TYPE = new Type(FLOAT); 154 155 158 159 public final static Type LONG_TYPE = new Type(LONG); 160 161 164 165 public final static Type DOUBLE_TYPE = new Type(DOUBLE); 166 167 171 174 175 private final int sort; 176 177 181 182 private char[] buf; 183 184 188 189 private int off; 190 191 194 195 private int len; 196 197 201 206 207 private Type (final int sort) { 208 this.sort = sort; 209 this.len = 1; 210 } 211 212 220 221 private Type ( 222 final int sort, 223 final char[] buf, 224 final int off, 225 final int len) 226 { 227 this.sort = sort; 228 this.buf = buf; 229 this.off = off; 230 this.len = len; 231 } 232 233 239 240 public static Type getType (final String typeDescriptor) { 241 return getType(typeDescriptor.toCharArray(), 0); 242 } 243 244 250 251 public static Type getType (final Class c) { 252 if (c.isPrimitive()) { 253 if (c == Integer.TYPE) { 254 return INT_TYPE; 255 } else if (c == Void.TYPE) { 256 return VOID_TYPE; 257 } else if (c == Boolean.TYPE) { 258 return BOOLEAN_TYPE; 259 } else if (c == Byte.TYPE) { 260 return BYTE_TYPE; 261 } else if (c == Character.TYPE) { 262 return CHAR_TYPE; 263 } else if (c == Short.TYPE) { 264 return SHORT_TYPE; 265 } else if (c == Double.TYPE) { 266 return DOUBLE_TYPE; 267 } else if (c == Float.TYPE) { 268 return FLOAT_TYPE; 269 } else { 270 return LONG_TYPE; 271 } 272 } else { 273 return getType(getDescriptor(c)); 274 } 275 } 276 277 285 286 public static Type[] getArgumentTypes (final String methodDescriptor) { 287 char[] buf = methodDescriptor.toCharArray(); 288 int off = 1; 289 int size = 0; 290 while (true) { 291 char car = buf[off++]; 292 if (car == ')') { 293 break; 294 } else if (car == 'L') { 295 while (buf[off++] != ';') { 296 } 297 ++size; 298 } else if (car != '[') { 299 ++size; 300 } 301 } 302 Type[] args = new Type[size]; 303 off = 1; 304 size = 0; 305 while (buf[off] != ')') { 306 args[size] = getType(buf, off); 307 off += args[size].len; 308 size += 1; 309 } 310 return args; 311 } 312 313 321 322 public static Type[] getArgumentTypes (final Method method) { 323 Class [] classes = method.getParameterTypes(); 324 Type[] types = new Type[classes.length]; 325 for (int i = classes.length - 1; i >= 0; --i) { 326 types[i] = getType(classes[i]); 327 } 328 return types; 329 } 330 331 339 340 public static Type getReturnType (final String methodDescriptor) { 341 char[] buf = methodDescriptor.toCharArray(); 342 return getType(buf, methodDescriptor.indexOf(')') + 1); 343 } 344 345 353 354 public static Type getReturnType (final Method method) { 355 return getType(method.getReturnType()); 356 } 357 358 365 366 private static Type getType (final char[] buf, final int off) { 367 int len; 368 switch (buf[off]) { 369 case 'V': return VOID_TYPE; 370 case 'Z': return BOOLEAN_TYPE; 371 case 'C': return CHAR_TYPE; 372 case 'B': return BYTE_TYPE; 373 case 'S': return SHORT_TYPE; 374 case 'I': return INT_TYPE; 375 case 'F': return FLOAT_TYPE; 376 case 'J': return LONG_TYPE; 377 case 'D': return DOUBLE_TYPE; 378 case '[': 379 len = 1; 380 while (buf[off + len] == '[') { 381 ++len; 382 } 383 if (buf[off + len] == 'L') { 384 ++len; 385 while (buf[off + len] != ';') { 386 ++len; 387 } 388 } 389 return new Type(ARRAY, buf, off, len + 1); 390 default: 392 len = 1; 393 while (buf[off + len] != ';') { 394 ++len; 395 } 396 return new Type(OBJECT, buf, off, len + 1); 397 } 398 } 399 400 404 412 413 public int getSort () { 414 return sort; 415 } 416 417 423 424 public int getDimensions () { 425 int i = 1; 426 while (buf[off + i] == '[') { 427 ++i; 428 } 429 return i; 430 } 431 432 438 439 public Type getElementType () { 440 return getType(buf, off + getDimensions()); 441 } 442 443 450 451 public String getClassName () { 452 return new String (buf, off + 1, len - 2).replace('/', '.'); 453 } 454 455 462 463 public String getInternalName () { 464 return new String (buf, off + 1, len - 2); 465 } 466 467 471 476 477 public String getDescriptor () { 478 StringBuffer buf = new StringBuffer (); 479 getDescriptor(buf); 480 return buf.toString(); 481 } 482 483 492 493 public static String getMethodDescriptor ( 494 final Type returnType, 495 final Type[] argumentTypes) 496 { 497 StringBuffer buf = new StringBuffer (); 498 buf.append('('); 499 for (int i = 0; i < argumentTypes.length; ++i) { 500 argumentTypes[i].getDescriptor(buf); 501 } 502 buf.append(')'); 503 returnType.getDescriptor(buf); 504 return buf.toString(); 505 } 506 507 513 514 private void getDescriptor (final StringBuffer buf) { 515 switch (sort) { 516 case VOID: buf.append('V'); return; 517 case BOOLEAN: buf.append('Z'); return; 518 case CHAR: buf.append('C'); return; 519 case BYTE: buf.append('B'); return; 520 case SHORT: buf.append('S'); return; 521 case INT: buf.append('I'); return; 522 case FLOAT: buf.append('F'); return; 523 case LONG: buf.append('J'); return; 524 case DOUBLE: buf.append('D'); return; 525 default: buf.append(this.buf, off, len); 528 } 529 } 530 531 536 543 544 public static String getInternalName (final Class c) { 545 return c.getName().replace('.', '/'); 546 } 547 548 554 555 public static String getDescriptor (final Class c) { 556 StringBuffer buf = new StringBuffer (); 557 getDescriptor(buf, c); 558 return buf.toString(); 559 } 560 561 567 568 public static String getMethodDescriptor (final Method m) { 569 Class [] parameters = m.getParameterTypes(); 570 StringBuffer buf = new StringBuffer (); 571 buf.append('('); 572 for (int i = 0; i < parameters.length; ++i) { 573 getDescriptor(buf, parameters[i]); 574 } 575 buf.append(')'); 576 getDescriptor(buf, m.getReturnType()); 577 return buf.toString(); 578 } 579 580 586 587 private static void getDescriptor (final StringBuffer buf, final Class c) { 588 Class d = c; 589 while (true) { 590 if (d.isPrimitive()) { 591 char car; 592 if (d == Integer.TYPE) { 593 car = 'I'; 594 } else if (d == Void.TYPE) { 595 car = 'V'; 596 } else if (d == Boolean.TYPE) { 597 car = 'Z'; 598 } else if (d == Byte.TYPE) { 599 car = 'B'; 600 } else if (d == Character.TYPE) { 601 car = 'C'; 602 } else if (d == Short.TYPE) { 603 car = 'S'; 604 } else if (d == Double.TYPE) { 605 car = 'D'; 606 } else if (d == Float.TYPE) { 607 car = 'F'; 608 } else { 609 car = 'J'; 610 } 611 buf.append(car); 612 return; 613 } else if (d.isArray()) { 614 buf.append('['); 615 d = d.getComponentType(); 616 } else { 617 buf.append('L'); 618 String name = d.getName(); 619 int len = name.length(); 620 for (int i = 0; i < len; ++i) { 621 char car = name.charAt(i); 622 buf.append(car == '.' ? '/' : car); 623 } 624 buf.append(';'); 625 return; 626 } 627 } 628 } 629 630 634 640 641 public int getSize () { 642 return (sort == LONG || sort == DOUBLE ? 2 : 1); 643 } 644 645 655 656 public int getOpcode (final int opcode) { 657 if (opcode == Constants.IALOAD || opcode == Constants.IASTORE) { 658 switch (sort) { 659 case BOOLEAN: 660 case BYTE: 661 return opcode + 5; 662 case CHAR: 663 return opcode + 6; 664 case SHORT: 665 return opcode + 7; 666 case INT: 667 return opcode; 668 case FLOAT: 669 return opcode + 2; 670 case LONG: 671 return opcode + 1; 672 case DOUBLE: 673 return opcode + 3; 674 default: 677 return opcode + 4; 678 } 679 } else { 680 switch (sort) { 681 case VOID: 682 return opcode + 5; 683 case BOOLEAN: 684 case CHAR: 685 case BYTE: 686 case SHORT: 687 case INT: 688 return opcode; 689 case FLOAT: 690 return opcode + 2; 691 case LONG: 692 return opcode + 1; 693 case DOUBLE: 694 return opcode + 3; 695 default: 698 return opcode + 4; 699 } 700 } 701 } 702 703 707 public boolean equals (Object o) { 708 if (this == o) { 709 return true; 710 } 711 if (o == null || !(o instanceof Type)) { 712 return false; 713 } 714 Type t = (Type)o; 715 if (sort != t.sort) { 716 return false; 717 } 718 if (sort == Type.OBJECT || sort == Type.ARRAY) { 719 if (len != t.len) { 720 return false; 721 } 722 for (int i = off, j = t.off, end = i + len; i < end; i++, j++) { 723 if (buf[i] != t.buf[j]) { 724 return false; 725 } 726 } 727 } 728 return true; 729 } 730 731 public int hashCode () { 732 int hc = 13 * sort; 733 if (sort == Type.OBJECT || sort == Type.ARRAY) { 734 for (int i = off, end = i + len; i < end; i++) { 735 hc = 17 * (hc + buf[i]); 736 } 737 } 738 return hc; 739 } 740 } 741 | Popular Tags |