1 30 package com.tc.asm; 31 32 import java.lang.reflect.Method ; 33 34 41 public class Type { 42 43 46 public final static int VOID = 0; 47 48 51 public final static int BOOLEAN = 1; 52 53 56 public final static int CHAR = 2; 57 58 61 public final static int BYTE = 3; 62 63 66 public final static int SHORT = 4; 67 68 71 public final static int INT = 5; 72 73 76 public final static int FLOAT = 6; 77 78 81 public final static int LONG = 7; 82 83 86 public final static int DOUBLE = 8; 87 88 91 public final static int ARRAY = 9; 92 93 96 public final static int OBJECT = 10; 97 98 101 public final static Type VOID_TYPE = new Type(VOID); 102 103 106 public final static Type BOOLEAN_TYPE = new Type(BOOLEAN); 107 108 111 public final static Type CHAR_TYPE = new Type(CHAR); 112 113 116 public final static Type BYTE_TYPE = new Type(BYTE); 117 118 121 public final static Type SHORT_TYPE = new Type(SHORT); 122 123 126 public final static Type INT_TYPE = new Type(INT); 127 128 131 public final static Type FLOAT_TYPE = new Type(FLOAT); 132 133 136 public final static Type LONG_TYPE = new Type(LONG); 137 138 141 public final static Type DOUBLE_TYPE = new Type(DOUBLE); 142 143 147 150 private final int sort; 151 152 156 private char[] buf; 157 158 162 private int off; 163 164 167 private int len; 168 169 173 178 private Type(final int sort) { 179 this.sort = sort; 180 this.len = 1; 181 } 182 183 191 private Type(final int sort, final char[] buf, final int off, final int len) 192 { 193 this.sort = sort; 194 this.buf = buf; 195 this.off = off; 196 this.len = len; 197 } 198 199 205 public static Type getType(final String typeDescriptor) { 206 return getType(typeDescriptor.toCharArray(), 0); 207 } 208 209 215 public static Type getType(final Class c) { 216 if (c.isPrimitive()) { 217 if (c == Integer.TYPE) { 218 return INT_TYPE; 219 } else if (c == Void.TYPE) { 220 return VOID_TYPE; 221 } else if (c == Boolean.TYPE) { 222 return BOOLEAN_TYPE; 223 } else if (c == Byte.TYPE) { 224 return BYTE_TYPE; 225 } else if (c == Character.TYPE) { 226 return CHAR_TYPE; 227 } else if (c == Short.TYPE) { 228 return SHORT_TYPE; 229 } else if (c == Double.TYPE) { 230 return DOUBLE_TYPE; 231 } else if (c == Float.TYPE) { 232 return FLOAT_TYPE; 233 } else { 234 return LONG_TYPE; 235 } 236 } else { 237 return getType(getDescriptor(c)); 238 } 239 } 240 241 249 public static Type[] getArgumentTypes(final String methodDescriptor) { 250 char[] buf = methodDescriptor.toCharArray(); 251 int off = 1; 252 int size = 0; 253 while (true) { 254 char car = buf[off++]; 255 if (car == ')') { 256 break; 257 } else if (car == 'L') { 258 while (buf[off++] != ';') { 259 } 260 ++size; 261 } else if (car != '[') { 262 ++size; 263 } 264 } 265 Type[] args = new Type[size]; 266 off = 1; 267 size = 0; 268 while (buf[off] != ')') { 269 args[size] = getType(buf, off); 270 off += args[size].len; 271 size += 1; 272 } 273 return args; 274 } 275 276 284 public static Type[] getArgumentTypes(final Method method) { 285 Class [] classes = method.getParameterTypes(); 286 Type[] types = new Type[classes.length]; 287 for (int i = classes.length - 1; i >= 0; --i) { 288 types[i] = getType(classes[i]); 289 } 290 return types; 291 } 292 293 301 public static Type getReturnType(final String methodDescriptor) { 302 char[] buf = methodDescriptor.toCharArray(); 303 return getType(buf, methodDescriptor.indexOf(')') + 1); 304 } 305 306 314 public static Type getReturnType(final Method method) { 315 return getType(method.getReturnType()); 316 } 317 318 325 private static Type getType(final char[] buf, final int off) { 326 int len; 327 switch (buf[off]) { 328 case 'V': 329 return VOID_TYPE; 330 case 'Z': 331 return BOOLEAN_TYPE; 332 case 'C': 333 return CHAR_TYPE; 334 case 'B': 335 return BYTE_TYPE; 336 case 'S': 337 return SHORT_TYPE; 338 case 'I': 339 return INT_TYPE; 340 case 'F': 341 return FLOAT_TYPE; 342 case 'J': 343 return LONG_TYPE; 344 case 'D': 345 return DOUBLE_TYPE; 346 case '[': 347 len = 1; 348 while (buf[off + len] == '[') { 349 ++len; 350 } 351 if (buf[off + len] == 'L') { 352 ++len; 353 while (buf[off + len] != ';') { 354 ++len; 355 } 356 } 357 return new Type(ARRAY, buf, off, len + 1); 358 default: 360 len = 1; 361 while (buf[off + len] != ';') { 362 ++len; 363 } 364 return new Type(OBJECT, buf, off, len + 1); 365 } 366 } 367 368 372 381 public int getSort() { 382 return sort; 383 } 384 385 391 public int getDimensions() { 392 int i = 1; 393 while (buf[off + i] == '[') { 394 ++i; 395 } 396 return i; 397 } 398 399 405 public Type getElementType() { 406 return getType(buf, off + getDimensions()); 407 } 408 409 414 public String getClassName() { 415 switch (sort) { 416 case VOID: 417 return "void"; 418 case BOOLEAN: 419 return "boolean"; 420 case CHAR: 421 return "char"; 422 case BYTE: 423 return "byte"; 424 case SHORT: 425 return "short"; 426 case INT: 427 return "int"; 428 case FLOAT: 429 return "float"; 430 case LONG: 431 return "long"; 432 case DOUBLE: 433 return "double"; 434 case ARRAY: 435 StringBuffer b = new StringBuffer (getElementType().getClassName()); 436 for (int i = getDimensions(); i > 0; --i) { 437 b.append("[]"); 438 } 439 return b.toString(); 440 default: 442 return new String (buf, off + 1, len - 2).replace('/', '.'); 443 } 444 } 445 446 453 public String getInternalName() { 454 return new String (buf, off + 1, len - 2); 455 } 456 457 461 466 public String getDescriptor() { 467 StringBuffer buf = new StringBuffer (); 468 getDescriptor(buf); 469 return buf.toString(); 470 } 471 472 481 public static String getMethodDescriptor( 482 final Type returnType, 483 final Type[] argumentTypes) 484 { 485 StringBuffer buf = new StringBuffer (); 486 buf.append('('); 487 for (int i = 0; i < argumentTypes.length; ++i) { 488 argumentTypes[i].getDescriptor(buf); 489 } 490 buf.append(')'); 491 returnType.getDescriptor(buf); 492 return buf.toString(); 493 } 494 495 501 private void getDescriptor(final StringBuffer buf) { 502 switch (sort) { 503 case VOID: 504 buf.append('V'); 505 return; 506 case BOOLEAN: 507 buf.append('Z'); 508 return; 509 case CHAR: 510 buf.append('C'); 511 return; 512 case BYTE: 513 buf.append('B'); 514 return; 515 case SHORT: 516 buf.append('S'); 517 return; 518 case INT: 519 buf.append('I'); 520 return; 521 case FLOAT: 522 buf.append('F'); 523 return; 524 case LONG: 525 buf.append('J'); 526 return; 527 case DOUBLE: 528 buf.append('D'); 529 return; 530 default: 533 buf.append(this.buf, off, len); 534 } 535 } 536 537 542 549 public static String getInternalName(final Class c) { 550 return c.getName().replace('.', '/'); 551 } 552 553 559 public static String getDescriptor(final Class c) { 560 StringBuffer buf = new StringBuffer (); 561 getDescriptor(buf, c); 562 return buf.toString(); 563 } 564 565 571 public static String getMethodDescriptor(final Method m) { 572 Class [] parameters = m.getParameterTypes(); 573 StringBuffer buf = new StringBuffer (); 574 buf.append('('); 575 for (int i = 0; i < parameters.length; ++i) { 576 getDescriptor(buf, parameters[i]); 577 } 578 buf.append(')'); 579 getDescriptor(buf, m.getReturnType()); 580 return buf.toString(); 581 } 582 583 589 private static void getDescriptor(final StringBuffer buf, final Class c) { 590 Class d = c; 591 while (true) { 592 if (d.isPrimitive()) { 593 char car; 594 if (d == Integer.TYPE) { 595 car = 'I'; 596 } else if (d == Void.TYPE) { 597 car = 'V'; 598 } else if (d == Boolean.TYPE) { 599 car = 'Z'; 600 } else if (d == Byte.TYPE) { 601 car = 'B'; 602 } else if (d == Character.TYPE) { 603 car = 'C'; 604 } else if (d == Short.TYPE) { 605 car = 'S'; 606 } else if (d == Double.TYPE) { 607 car = 'D'; 608 } else if (d == Float.TYPE) { 609 car = 'F'; 610 } else { 611 car = 'J'; 612 } 613 buf.append(car); 614 return; 615 } else if (d.isArray()) { 616 buf.append('['); 617 d = d.getComponentType(); 618 } else { 619 buf.append('L'); 620 String name = d.getName(); 621 int len = name.length(); 622 for (int i = 0; i < len; ++i) { 623 char car = name.charAt(i); 624 buf.append(car == '.' ? '/' : car); 625 } 626 buf.append(';'); 627 return; 628 } 629 } 630 } 631 632 636 642 public int getSize() { 643 return (sort == LONG || sort == DOUBLE ? 2 : 1); 644 } 645 646 656 public int getOpcode(final int opcode) { 657 if (opcode == Opcodes.IALOAD || opcode == Opcodes.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 713 public boolean equals(final Object o) { 714 if (this == o) { 715 return true; 716 } 717 if (o == null || !(o instanceof Type)) { 718 return false; 719 } 720 Type t = (Type) o; 721 if (sort != t.sort) { 722 return false; 723 } 724 if (sort == Type.OBJECT || sort == Type.ARRAY) { 725 if (len != t.len) { 726 return false; 727 } 728 for (int i = off, j = t.off, end = i + len; i < end; i++, j++) { 729 if (buf[i] != t.buf[j]) { 730 return false; 731 } 732 } 733 } 734 return true; 735 } 736 737 742 public int hashCode() { 743 int hc = 13 * sort; 744 if (sort == Type.OBJECT || sort == Type.ARRAY) { 745 for (int i = off, end = i + len; i < end; i++) { 746 hc = 17 * (hc + buf[i]); 747 } 748 } 749 return hc; 750 } 751 752 757 public String toString() { 758 return getDescriptor(); 759 } 760 } 761 | Popular Tags |