001/*** 002 * ASM: a very small and fast Java bytecode manipulation framework 003 * Copyright (c) 2000-2011 INRIA, France Telecom 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or without 007 * modification, are permitted provided that the following conditions 008 * are met: 009 * 1. Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 2. Redistributions in binary form must reproduce the above copyright 012 * notice, this list of conditions and the following disclaimer in the 013 * documentation and/or other materials provided with the distribution. 014 * 3. Neither the name of the copyright holders nor the names of its 015 * contributors may be used to endorse or promote products derived from 016 * this software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 028 * THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.springframework.asm; 031 032import java.lang.reflect.Constructor; 033import java.lang.reflect.Method; 034 035/** 036 * A Java field or method type. This class can be used to make it easier to 037 * manipulate type and method descriptors. 038 * 039 * @author Eric Bruneton 040 * @author Chris Nokleberg 041 */ 042public class Type { 043 044 /** 045 * The sort of the <tt>void</tt> type. See {@link #getSort getSort}. 046 */ 047 public static final int VOID = 0; 048 049 /** 050 * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}. 051 */ 052 public static final int BOOLEAN = 1; 053 054 /** 055 * The sort of the <tt>char</tt> type. See {@link #getSort getSort}. 056 */ 057 public static final int CHAR = 2; 058 059 /** 060 * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}. 061 */ 062 public static final int BYTE = 3; 063 064 /** 065 * The sort of the <tt>short</tt> type. See {@link #getSort getSort}. 066 */ 067 public static final int SHORT = 4; 068 069 /** 070 * The sort of the <tt>int</tt> type. See {@link #getSort getSort}. 071 */ 072 public static final int INT = 5; 073 074 /** 075 * The sort of the <tt>float</tt> type. See {@link #getSort getSort}. 076 */ 077 public static final int FLOAT = 6; 078 079 /** 080 * The sort of the <tt>long</tt> type. See {@link #getSort getSort}. 081 */ 082 public static final int LONG = 7; 083 084 /** 085 * The sort of the <tt>double</tt> type. See {@link #getSort getSort}. 086 */ 087 public static final int DOUBLE = 8; 088 089 /** 090 * The sort of array reference types. See {@link #getSort getSort}. 091 */ 092 public static final int ARRAY = 9; 093 094 /** 095 * The sort of object reference types. See {@link #getSort getSort}. 096 */ 097 public static final int OBJECT = 10; 098 099 /** 100 * The sort of method types. See {@link #getSort getSort}. 101 */ 102 public static final int METHOD = 11; 103 104 /** 105 * The <tt>void</tt> type. 106 */ 107 public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24) 108 | (5 << 16) | (0 << 8) | 0, 1); 109 110 /** 111 * The <tt>boolean</tt> type. 112 */ 113 public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24) 114 | (0 << 16) | (5 << 8) | 1, 1); 115 116 /** 117 * The <tt>char</tt> type. 118 */ 119 public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24) 120 | (0 << 16) | (6 << 8) | 1, 1); 121 122 /** 123 * The <tt>byte</tt> type. 124 */ 125 public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24) 126 | (0 << 16) | (5 << 8) | 1, 1); 127 128 /** 129 * The <tt>short</tt> type. 130 */ 131 public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24) 132 | (0 << 16) | (7 << 8) | 1, 1); 133 134 /** 135 * The <tt>int</tt> type. 136 */ 137 public static final Type INT_TYPE = new Type(INT, null, ('I' << 24) 138 | (0 << 16) | (0 << 8) | 1, 1); 139 140 /** 141 * The <tt>float</tt> type. 142 */ 143 public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24) 144 | (2 << 16) | (2 << 8) | 1, 1); 145 146 /** 147 * The <tt>long</tt> type. 148 */ 149 public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24) 150 | (1 << 16) | (1 << 8) | 2, 1); 151 152 /** 153 * The <tt>double</tt> type. 154 */ 155 public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24) 156 | (3 << 16) | (3 << 8) | 2, 1); 157 158 // ------------------------------------------------------------------------ 159 // Fields 160 // ------------------------------------------------------------------------ 161 162 /** 163 * The sort of this Java type. 164 */ 165 private final int sort; 166 167 /** 168 * A buffer containing the internal name of this Java type. This field is 169 * only used for reference types. 170 */ 171 private final char[] buf; 172 173 /** 174 * The offset of the internal name of this Java type in {@link #buf buf} or, 175 * for primitive types, the size, descriptor and getOpcode offsets for this 176 * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset 177 * for IALOAD or IASTORE, byte 3 the offset for all other instructions). 178 */ 179 private final int off; 180 181 /** 182 * The length of the internal name of this Java type. 183 */ 184 private final int len; 185 186 // ------------------------------------------------------------------------ 187 // Constructors 188 // ------------------------------------------------------------------------ 189 190 /** 191 * Constructs a reference type. 192 * 193 * @param sort 194 * the sort of the reference type to be constructed. 195 * @param buf 196 * a buffer containing the descriptor of the previous type. 197 * @param off 198 * the offset of this descriptor in the previous buffer. 199 * @param len 200 * the length of this descriptor. 201 */ 202 private Type(final int sort, final char[] buf, final int off, final int len) { 203 this.sort = sort; 204 this.buf = buf; 205 this.off = off; 206 this.len = len; 207 } 208 209 /** 210 * Returns the Java type corresponding to the given type descriptor. 211 * 212 * @param typeDescriptor 213 * a field or method type descriptor. 214 * @return the Java type corresponding to the given type descriptor. 215 */ 216 public static Type getType(final String typeDescriptor) { 217 return getType(typeDescriptor.toCharArray(), 0); 218 } 219 220 /** 221 * Returns the Java type corresponding to the given internal name. 222 * 223 * @param internalName 224 * an internal name. 225 * @return the Java type corresponding to the given internal name. 226 */ 227 public static Type getObjectType(final String internalName) { 228 char[] buf = internalName.toCharArray(); 229 return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length); 230 } 231 232 /** 233 * Returns the Java type corresponding to the given method descriptor. 234 * Equivalent to <code>Type.getType(methodDescriptor)</code>. 235 * 236 * @param methodDescriptor 237 * a method descriptor. 238 * @return the Java type corresponding to the given method descriptor. 239 */ 240 public static Type getMethodType(final String methodDescriptor) { 241 return getType(methodDescriptor.toCharArray(), 0); 242 } 243 244 /** 245 * Returns the Java method type corresponding to the given argument and 246 * return types. 247 * 248 * @param returnType 249 * the return type of the method. 250 * @param argumentTypes 251 * the argument types of the method. 252 * @return the Java type corresponding to the given argument and return 253 * types. 254 */ 255 public static Type getMethodType(final Type returnType, 256 final Type... argumentTypes) { 257 return getType(getMethodDescriptor(returnType, argumentTypes)); 258 } 259 260 /** 261 * Returns the Java type corresponding to the given class. 262 * 263 * @param c 264 * a class. 265 * @return the Java type corresponding to the given class. 266 */ 267 public static Type getType(final Class<?> c) { 268 if (c.isPrimitive()) { 269 if (c == Integer.TYPE) { 270 return INT_TYPE; 271 } else if (c == Void.TYPE) { 272 return VOID_TYPE; 273 } else if (c == Boolean.TYPE) { 274 return BOOLEAN_TYPE; 275 } else if (c == Byte.TYPE) { 276 return BYTE_TYPE; 277 } else if (c == Character.TYPE) { 278 return CHAR_TYPE; 279 } else if (c == Short.TYPE) { 280 return SHORT_TYPE; 281 } else if (c == Double.TYPE) { 282 return DOUBLE_TYPE; 283 } else if (c == Float.TYPE) { 284 return FLOAT_TYPE; 285 } else /* if (c == Long.TYPE) */{ 286 return LONG_TYPE; 287 } 288 } else { 289 return getType(getDescriptor(c)); 290 } 291 } 292 293 /** 294 * Returns the Java method type corresponding to the given constructor. 295 * 296 * @param c 297 * a {@link Constructor Constructor} object. 298 * @return the Java method type corresponding to the given constructor. 299 */ 300 public static Type getType(final Constructor<?> c) { 301 return getType(getConstructorDescriptor(c)); 302 } 303 304 /** 305 * Returns the Java method type corresponding to the given method. 306 * 307 * @param m 308 * a {@link Method Method} object. 309 * @return the Java method type corresponding to the given method. 310 */ 311 public static Type getType(final Method m) { 312 return getType(getMethodDescriptor(m)); 313 } 314 315 /** 316 * Returns the Java types corresponding to the argument types of the given 317 * method descriptor. 318 * 319 * @param methodDescriptor 320 * a method descriptor. 321 * @return the Java types corresponding to the argument types of the given 322 * method descriptor. 323 */ 324 public static Type[] getArgumentTypes(final String methodDescriptor) { 325 char[] buf = methodDescriptor.toCharArray(); 326 int off = 1; 327 int size = 0; 328 while (true) { 329 char car = buf[off++]; 330 if (car == ')') { 331 break; 332 } else if (car == 'L') { 333 while (buf[off++] != ';') { 334 } 335 ++size; 336 } else if (car != '[') { 337 ++size; 338 } 339 } 340 Type[] args = new Type[size]; 341 off = 1; 342 size = 0; 343 while (buf[off] != ')') { 344 args[size] = getType(buf, off); 345 off += args[size].len + (args[size].sort == OBJECT ? 2 : 0); 346 size += 1; 347 } 348 return args; 349 } 350 351 /** 352 * Returns the Java types corresponding to the argument types of the given 353 * method. 354 * 355 * @param method 356 * a method. 357 * @return the Java types corresponding to the argument types of the given 358 * method. 359 */ 360 public static Type[] getArgumentTypes(final Method method) { 361 Class<?>[] classes = method.getParameterTypes(); 362 Type[] types = new Type[classes.length]; 363 for (int i = classes.length - 1; i >= 0; --i) { 364 types[i] = getType(classes[i]); 365 } 366 return types; 367 } 368 369 /** 370 * Returns the Java type corresponding to the return type of the given 371 * method descriptor. 372 * 373 * @param methodDescriptor 374 * a method descriptor. 375 * @return the Java type corresponding to the return type of the given 376 * method descriptor. 377 */ 378 public static Type getReturnType(final String methodDescriptor) { 379 char[] buf = methodDescriptor.toCharArray(); 380 int off = 1; 381 while (true) { 382 char car = buf[off++]; 383 if (car == ')') { 384 return getType(buf, off); 385 } else if (car == 'L') { 386 while (buf[off++] != ';') { 387 } 388 } 389 } 390 } 391 392 /** 393 * Returns the Java type corresponding to the return type of the given 394 * method. 395 * 396 * @param method 397 * a method. 398 * @return the Java type corresponding to the return type of the given 399 * method. 400 */ 401 public static Type getReturnType(final Method method) { 402 return getType(method.getReturnType()); 403 } 404 405 /** 406 * Computes the size of the arguments and of the return value of a method. 407 * 408 * @param desc 409 * the descriptor of a method. 410 * @return the size of the arguments of the method (plus one for the 411 * implicit this argument), argSize, and the size of its return 412 * value, retSize, packed into a single int i = 413 * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to 414 * <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>). 415 */ 416 public static int getArgumentsAndReturnSizes(final String desc) { 417 int n = 1; 418 int c = 1; 419 while (true) { 420 char car = desc.charAt(c++); 421 if (car == ')') { 422 car = desc.charAt(c); 423 return n << 2 424 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); 425 } else if (car == 'L') { 426 while (desc.charAt(c++) != ';') { 427 } 428 n += 1; 429 } else if (car == '[') { 430 while ((car = desc.charAt(c)) == '[') { 431 ++c; 432 } 433 if (car == 'D' || car == 'J') { 434 n -= 1; 435 } 436 } else if (car == 'D' || car == 'J') { 437 n += 2; 438 } else { 439 n += 1; 440 } 441 } 442 } 443 444 /** 445 * Returns the Java type corresponding to the given type descriptor. For 446 * method descriptors, buf is supposed to contain nothing more than the 447 * descriptor itself. 448 * 449 * @param buf 450 * a buffer containing a type descriptor. 451 * @param off 452 * the offset of this descriptor in the previous buffer. 453 * @return the Java type corresponding to the given type descriptor. 454 */ 455 private static Type getType(final char[] buf, final int off) { 456 int len; 457 switch (buf[off]) { 458 case 'V': 459 return VOID_TYPE; 460 case 'Z': 461 return BOOLEAN_TYPE; 462 case 'C': 463 return CHAR_TYPE; 464 case 'B': 465 return BYTE_TYPE; 466 case 'S': 467 return SHORT_TYPE; 468 case 'I': 469 return INT_TYPE; 470 case 'F': 471 return FLOAT_TYPE; 472 case 'J': 473 return LONG_TYPE; 474 case 'D': 475 return DOUBLE_TYPE; 476 case '[': 477 len = 1; 478 while (buf[off + len] == '[') { 479 ++len; 480 } 481 if (buf[off + len] == 'L') { 482 ++len; 483 while (buf[off + len] != ';') { 484 ++len; 485 } 486 } 487 return new Type(ARRAY, buf, off, len + 1); 488 case 'L': 489 len = 1; 490 while (buf[off + len] != ';') { 491 ++len; 492 } 493 return new Type(OBJECT, buf, off + 1, len - 1); 494 // case '(': 495 default: 496 return new Type(METHOD, buf, off, buf.length - off); 497 } 498 } 499 500 // ------------------------------------------------------------------------ 501 // Accessors 502 // ------------------------------------------------------------------------ 503 504 /** 505 * Returns the sort of this Java type. 506 * 507 * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR}, 508 * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, 509 * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, 510 * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD 511 * METHOD}. 512 */ 513 public int getSort() { 514 return sort; 515 } 516 517 /** 518 * Returns the number of dimensions of this array type. This method should 519 * only be used for an array type. 520 * 521 * @return the number of dimensions of this array type. 522 */ 523 public int getDimensions() { 524 int i = 1; 525 while (buf[off + i] == '[') { 526 ++i; 527 } 528 return i; 529 } 530 531 /** 532 * Returns the type of the elements of this array type. This method should 533 * only be used for an array type. 534 * 535 * @return Returns the type of the elements of this array type. 536 */ 537 public Type getElementType() { 538 return getType(buf, off + getDimensions()); 539 } 540 541 /** 542 * Returns the binary name of the class corresponding to this type. This 543 * method must not be used on method types. 544 * 545 * @return the binary name of the class corresponding to this type. 546 */ 547 public String getClassName() { 548 switch (sort) { 549 case VOID: 550 return "void"; 551 case BOOLEAN: 552 return "boolean"; 553 case CHAR: 554 return "char"; 555 case BYTE: 556 return "byte"; 557 case SHORT: 558 return "short"; 559 case INT: 560 return "int"; 561 case FLOAT: 562 return "float"; 563 case LONG: 564 return "long"; 565 case DOUBLE: 566 return "double"; 567 case ARRAY: 568 StringBuilder sb = new StringBuilder(getElementType().getClassName()); 569 for (int i = getDimensions(); i > 0; --i) { 570 sb.append("[]"); 571 } 572 return sb.toString(); 573 case OBJECT: 574 return new String(buf, off, len).replace('/', '.').intern(); 575 default: 576 return null; 577 } 578 } 579 580 /** 581 * Returns the internal name of the class corresponding to this object or 582 * array type. The internal name of a class is its fully qualified name (as 583 * returned by Class.getName(), where '.' are replaced by '/'. This method 584 * should only be used for an object or array type. 585 * 586 * @return the internal name of the class corresponding to this object type. 587 */ 588 public String getInternalName() { 589 return new String(buf, off, len).intern(); 590 } 591 592 /** 593 * Returns the argument types of methods of this type. This method should 594 * only be used for method types. 595 * 596 * @return the argument types of methods of this type. 597 */ 598 public Type[] getArgumentTypes() { 599 return getArgumentTypes(getDescriptor()); 600 } 601 602 /** 603 * Returns the return type of methods of this type. This method should only 604 * be used for method types. 605 * 606 * @return the return type of methods of this type. 607 */ 608 public Type getReturnType() { 609 return getReturnType(getDescriptor()); 610 } 611 612 /** 613 * Returns the size of the arguments and of the return value of methods of 614 * this type. This method should only be used for method types. 615 * 616 * @return the size of the arguments (plus one for the implicit this 617 * argument), argSize, and the size of the return value, retSize, 618 * packed into a single 619 * int i = <tt>(argSize << 2) | retSize</tt> 620 * (argSize is therefore equal to <tt>i >> 2</tt>, 621 * and retSize to <tt>i & 0x03</tt>). 622 */ 623 public int getArgumentsAndReturnSizes() { 624 return getArgumentsAndReturnSizes(getDescriptor()); 625 } 626 627 // ------------------------------------------------------------------------ 628 // Conversion to type descriptors 629 // ------------------------------------------------------------------------ 630 631 /** 632 * Returns the descriptor corresponding to this Java type. 633 * 634 * @return the descriptor corresponding to this Java type. 635 */ 636 public String getDescriptor() { 637 StringBuilder buf = new StringBuilder(); 638 getDescriptor(buf); 639 return buf.toString(); 640 } 641 642 /** 643 * Returns the descriptor corresponding to the given argument and return 644 * types. 645 * 646 * @param returnType 647 * the return type of the method. 648 * @param argumentTypes 649 * the argument types of the method. 650 * @return the descriptor corresponding to the given argument and return 651 * types. 652 */ 653 public static String getMethodDescriptor(final Type returnType, 654 final Type... argumentTypes) { 655 StringBuilder buf = new StringBuilder(); 656 buf.append('('); 657 for (int i = 0; i < argumentTypes.length; ++i) { 658 argumentTypes[i].getDescriptor(buf); 659 } 660 buf.append(')'); 661 returnType.getDescriptor(buf); 662 return buf.toString(); 663 } 664 665 /** 666 * Appends the descriptor corresponding to this Java type to the given 667 * string buffer. 668 * 669 * @param buf 670 * the string buffer to which the descriptor must be appended. 671 */ 672 private void getDescriptor(final StringBuilder buf) { 673 if (this.buf == null) { 674 // descriptor is in byte 3 of 'off' for primitive types (buf == 675 // null) 676 buf.append((char) ((off & 0xFF000000) >>> 24)); 677 } else if (sort == OBJECT) { 678 buf.append('L'); 679 buf.append(this.buf, off, len); 680 buf.append(';'); 681 } else { // sort == ARRAY || sort == METHOD 682 buf.append(this.buf, off, len); 683 } 684 } 685 686 // ------------------------------------------------------------------------ 687 // Direct conversion from classes to type descriptors, 688 // without intermediate Type objects 689 // ------------------------------------------------------------------------ 690 691 /** 692 * Returns the internal name of the given class. The internal name of a 693 * class is its fully qualified name, as returned by Class.getName(), where 694 * '.' are replaced by '/'. 695 * 696 * @param c 697 * an object or array class. 698 * @return the internal name of the given class. 699 */ 700 public static String getInternalName(final Class<?> c) { 701 return c.getName().replace('.', '/'); 702 } 703 704 /** 705 * Returns the descriptor corresponding to the given Java type. 706 * 707 * @param c 708 * an object class, a primitive class or an array class. 709 * @return the descriptor corresponding to the given class. 710 */ 711 public static String getDescriptor(final Class<?> c) { 712 StringBuilder buf = new StringBuilder(); 713 getDescriptor(buf, c); 714 return buf.toString(); 715 } 716 717 /** 718 * Returns the descriptor corresponding to the given constructor. 719 * 720 * @param c 721 * a {@link Constructor Constructor} object. 722 * @return the descriptor of the given constructor. 723 */ 724 public static String getConstructorDescriptor(final Constructor<?> c) { 725 Class<?>[] parameters = c.getParameterTypes(); 726 StringBuilder buf = new StringBuilder(); 727 buf.append('('); 728 for (int i = 0; i < parameters.length; ++i) { 729 getDescriptor(buf, parameters[i]); 730 } 731 return buf.append(")V").toString(); 732 } 733 734 /** 735 * Returns the descriptor corresponding to the given method. 736 * 737 * @param m 738 * a {@link Method Method} object. 739 * @return the descriptor of the given method. 740 */ 741 public static String getMethodDescriptor(final Method m) { 742 Class<?>[] parameters = m.getParameterTypes(); 743 StringBuilder buf = new StringBuilder(); 744 buf.append('('); 745 for (int i = 0; i < parameters.length; ++i) { 746 getDescriptor(buf, parameters[i]); 747 } 748 buf.append(')'); 749 getDescriptor(buf, m.getReturnType()); 750 return buf.toString(); 751 } 752 753 /** 754 * Appends the descriptor of the given class to the given string buffer. 755 * 756 * @param buf 757 * the string buffer to which the descriptor must be appended. 758 * @param c 759 * the class whose descriptor must be computed. 760 */ 761 private static void getDescriptor(final StringBuilder buf, final Class<?> c) { 762 Class<?> d = c; 763 while (true) { 764 if (d.isPrimitive()) { 765 char car; 766 if (d == Integer.TYPE) { 767 car = 'I'; 768 } else if (d == Void.TYPE) { 769 car = 'V'; 770 } else if (d == Boolean.TYPE) { 771 car = 'Z'; 772 } else if (d == Byte.TYPE) { 773 car = 'B'; 774 } else if (d == Character.TYPE) { 775 car = 'C'; 776 } else if (d == Short.TYPE) { 777 car = 'S'; 778 } else if (d == Double.TYPE) { 779 car = 'D'; 780 } else if (d == Float.TYPE) { 781 car = 'F'; 782 } else /* if (d == Long.TYPE) */{ 783 car = 'J'; 784 } 785 buf.append(car); 786 return; 787 } else if (d.isArray()) { 788 buf.append('['); 789 d = d.getComponentType(); 790 } else { 791 buf.append('L'); 792 String name = d.getName(); 793 int len = name.length(); 794 for (int i = 0; i < len; ++i) { 795 char car = name.charAt(i); 796 buf.append(car == '.' ? '/' : car); 797 } 798 buf.append(';'); 799 return; 800 } 801 } 802 } 803 804 // ------------------------------------------------------------------------ 805 // Corresponding size and opcodes 806 // ------------------------------------------------------------------------ 807 808 /** 809 * Returns the size of values of this type. This method must not be used for 810 * method types. 811 * 812 * @return the size of values of this type, i.e., 2 for <tt>long</tt> and 813 * <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise. 814 */ 815 public int getSize() { 816 // the size is in byte 0 of 'off' for primitive types (buf == null) 817 return buf == null ? (off & 0xFF) : 1; 818 } 819 820 /** 821 * Returns a JVM instruction opcode adapted to this Java type. This method 822 * must not be used for method types. 823 * 824 * @param opcode 825 * a JVM instruction opcode. This opcode must be one of ILOAD, 826 * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, 827 * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN. 828 * @return an opcode that is similar to the given opcode, but adapted to 829 * this Java type. For example, if this type is <tt>float</tt> and 830 * <tt>opcode</tt> is IRETURN, this method returns FRETURN. 831 */ 832 public int getOpcode(final int opcode) { 833 if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) { 834 // the offset for IALOAD or IASTORE is in byte 1 of 'off' for 835 // primitive types (buf == null) 836 return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4); 837 } else { 838 // the offset for other instructions is in byte 2 of 'off' for 839 // primitive types (buf == null) 840 return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4); 841 } 842 } 843 844 // ------------------------------------------------------------------------ 845 // Equals, hashCode and toString 846 // ------------------------------------------------------------------------ 847 848 /** 849 * Tests if the given object is equal to this type. 850 * 851 * @param o 852 * the object to be compared to this type. 853 * @return <tt>true</tt> if the given object is equal to this type. 854 */ 855 @Override 856 public boolean equals(final Object o) { 857 if (this == o) { 858 return true; 859 } 860 if (!(o instanceof Type)) { 861 return false; 862 } 863 Type t = (Type) o; 864 if (sort != t.sort) { 865 return false; 866 } 867 if (sort >= ARRAY) { 868 if (len != t.len) { 869 return false; 870 } 871 for (int i = off, j = t.off, end = i + len; i < end; i++, j++) { 872 if (buf[i] != t.buf[j]) { 873 return false; 874 } 875 } 876 } 877 return true; 878 } 879 880 /** 881 * Returns a hash code value for this type. 882 * 883 * @return a hash code value for this type. 884 */ 885 @Override 886 public int hashCode() { 887 int hc = 13 * sort; 888 if (sort >= ARRAY) { 889 for (int i = off, end = i + len; i < end; i++) { 890 hc = 17 * (hc + buf[i]); 891 } 892 } 893 return hc; 894 } 895 896 /** 897 * Returns a string representation of this type. 898 * 899 * @return the descriptor of this type. 900 */ 901 @Override 902 public String toString() { 903 return getDescriptor(); 904 } 905}