1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * This file is available under and governed by the GNU General Public 27 * License version 2 only, as published by the Free Software Foundation. 28 * However, the following notice accompanied the original version of this 29 * file: 30 * 31 * ASM: a very small and fast Java bytecode manipulation framework 32 * Copyright (c) 2000-2011 INRIA, France Telecom 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. Neither the name of the copyright holders nor the names of its 44 * contributors may be used to endorse or promote products derived from 45 * this software without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 57 * THE POSSIBILITY OF SUCH DAMAGE. 58 */ 59 package jdk.internal.org.objectweb.asm; 60 61 import java.lang.reflect.Constructor; 62 import java.lang.reflect.Method; 63 64 /** 65 * A Java field or method type. This class can be used to make it easier to 66 * manipulate type and method descriptors. 67 * 68 * @author Eric Bruneton 69 * @author Chris Nokleberg 70 */ 71 public class Type { 72 73 /** 74 * The sort of the <tt>void</tt> type. See {@link #getSort getSort}. 75 */ 76 public static final int VOID = 0; 77 78 /** 79 * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}. 80 */ 81 public static final int BOOLEAN = 1; 82 83 /** 84 * The sort of the <tt>char</tt> type. See {@link #getSort getSort}. 85 */ 86 public static final int CHAR = 2; 87 88 /** 89 * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}. 90 */ 91 public static final int BYTE = 3; 92 93 /** 94 * The sort of the <tt>short</tt> type. See {@link #getSort getSort}. 95 */ 96 public static final int SHORT = 4; 97 98 /** 99 * The sort of the <tt>int</tt> type. See {@link #getSort getSort}. 100 */ 101 public static final int INT = 5; 102 103 /** 104 * The sort of the <tt>float</tt> type. See {@link #getSort getSort}. 105 */ 106 public static final int FLOAT = 6; 107 108 /** 109 * The sort of the <tt>long</tt> type. See {@link #getSort getSort}. 110 */ 111 public static final int LONG = 7; 112 113 /** 114 * The sort of the <tt>double</tt> type. See {@link #getSort getSort}. 115 */ 116 public static final int DOUBLE = 8; 117 118 /** 119 * The sort of array reference types. See {@link #getSort getSort}. 120 */ 121 public static final int ARRAY = 9; 122 123 /** 124 * The sort of object reference types. See {@link #getSort getSort}. 125 */ 126 public static final int OBJECT = 10; 127 128 /** 129 * The sort of method types. See {@link #getSort getSort}. 130 */ 131 public static final int METHOD = 11; 132 133 /** 134 * The <tt>void</tt> type. 135 */ 136 public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24) 137 | (5 << 16) | (0 << 8) | 0, 1); 138 139 /** 140 * The <tt>boolean</tt> type. 141 */ 142 public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24) 143 | (0 << 16) | (5 << 8) | 1, 1); 144 145 /** 146 * The <tt>char</tt> type. 147 */ 148 public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24) 149 | (0 << 16) | (6 << 8) | 1, 1); 150 151 /** 152 * The <tt>byte</tt> type. 153 */ 154 public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24) 155 | (0 << 16) | (5 << 8) | 1, 1); 156 157 /** 158 * The <tt>short</tt> type. 159 */ 160 public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24) 161 | (0 << 16) | (7 << 8) | 1, 1); 162 163 /** 164 * The <tt>int</tt> type. 165 */ 166 public static final Type INT_TYPE = new Type(INT, null, ('I' << 24) 167 | (0 << 16) | (0 << 8) | 1, 1); 168 169 /** 170 * The <tt>float</tt> type. 171 */ 172 public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24) 173 | (2 << 16) | (2 << 8) | 1, 1); 174 175 /** 176 * The <tt>long</tt> type. 177 */ 178 public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24) 179 | (1 << 16) | (1 << 8) | 2, 1); 180 181 /** 182 * The <tt>double</tt> type. 183 */ 184 public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24) 185 | (3 << 16) | (3 << 8) | 2, 1); 186 187 // ------------------------------------------------------------------------ 188 // Fields 189 // ------------------------------------------------------------------------ 190 191 /** 192 * The sort of this Java type. 193 */ 194 private final int sort; 195 196 /** 197 * A buffer containing the internal name of this Java type. This field is 198 * only used for reference types. 199 */ 200 private final char[] buf; 201 202 /** 203 * The offset of the internal name of this Java type in {@link #buf buf} or, 204 * for primitive types, the size, descriptor and getOpcode offsets for this 205 * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset 206 * for IALOAD or IASTORE, byte 3 the offset for all other instructions). 207 */ 208 private final int off; 209 210 /** 211 * The length of the internal name of this Java type. 212 */ 213 private final int len; 214 215 // ------------------------------------------------------------------------ 216 // Constructors 217 // ------------------------------------------------------------------------ 218 219 /** 220 * Constructs a reference type. 221 * 222 * @param sort the sort of the reference type to be constructed. 223 * @param buf a buffer containing the descriptor of the previous type. 224 * @param off the offset of this descriptor in the previous buffer. 225 * @param len the length of this descriptor. 226 */ 227 private Type(final int sort, final char[] buf, final int off, final int len) 228 { 229 this.sort = sort; 230 this.buf = buf; 231 this.off = off; 232 this.len = len; 233 } 234 235 /** 236 * Returns the Java type corresponding to the given type descriptor. 237 * 238 * @param typeDescriptor a field or method type descriptor. 239 * @return the Java type corresponding to the given type descriptor. 240 */ 241 public static Type getType(final String typeDescriptor) { 242 return getType(typeDescriptor.toCharArray(), 0); 243 } 244 245 /** 246 * Returns the Java type corresponding to the given internal name. 247 * 248 * @param internalName an internal name. 249 * @return the Java type corresponding to the given internal name. 250 */ 251 public static Type getObjectType(final String internalName) { 252 char[] buf = internalName.toCharArray(); 253 return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length); 254 } 255 256 /** 257 * Returns the Java type corresponding to the given method descriptor. 258 * Equivalent to <code>Type.getType(methodDescriptor)</code>. 259 * 260 * @param methodDescriptor a method descriptor. 261 * @return the Java type corresponding to the given method descriptor. 262 */ 263 public static Type getMethodType(final String methodDescriptor) { 264 return getType(methodDescriptor.toCharArray(), 0); 265 } 266 267 /** 268 * Returns the Java method type corresponding to the given argument and 269 * return types. 270 * 271 * @param returnType the return type of the method. 272 * @param argumentTypes the argument types of the method. 273 * @return the Java type corresponding to the given argument and return types. 274 */ 275 public static Type getMethodType(final Type returnType, final Type... argumentTypes) { 276 return getType(getMethodDescriptor(returnType, argumentTypes)); 277 } 278 279 /** 280 * Returns the Java type corresponding to the given class. 281 * 282 * @param c a class. 283 * @return the Java type corresponding to the given class. 284 */ 285 public static Type getType(final Class<?> c) { 286 if (c.isPrimitive()) { 287 if (c == Integer.TYPE) { 288 return INT_TYPE; 289 } else if (c == Void.TYPE) { 290 return VOID_TYPE; 291 } else if (c == Boolean.TYPE) { 292 return BOOLEAN_TYPE; 293 } else if (c == Byte.TYPE) { 294 return BYTE_TYPE; 295 } else if (c == Character.TYPE) { 296 return CHAR_TYPE; 297 } else if (c == Short.TYPE) { 298 return SHORT_TYPE; 299 } else if (c == Double.TYPE) { 300 return DOUBLE_TYPE; 301 } else if (c == Float.TYPE) { 302 return FLOAT_TYPE; 303 } else /* if (c == Long.TYPE) */{ 304 return LONG_TYPE; 305 } 306 } else { 307 return getType(getDescriptor(c)); 308 } 309 } 310 311 /** 312 * Returns the Java method type corresponding to the given constructor. 313 * 314 * @param c a {@link Constructor Constructor} object. 315 * @return the Java method type corresponding to the given constructor. 316 */ 317 public static Type getType(final Constructor<?> c) { 318 return getType(getConstructorDescriptor(c)); 319 } 320 321 /** 322 * Returns the Java method type corresponding to the given method. 323 * 324 * @param m a {@link Method Method} object. 325 * @return the Java method type corresponding to the given method. 326 */ 327 public static Type getType(final Method m) { 328 return getType(getMethodDescriptor(m)); 329 } 330 331 /** 332 * Returns the Java types corresponding to the argument types of the given 333 * method descriptor. 334 * 335 * @param methodDescriptor a method descriptor. 336 * @return the Java types corresponding to the argument types of the given 337 * method descriptor. 338 */ 339 public static Type[] getArgumentTypes(final String methodDescriptor) { 340 char[] buf = methodDescriptor.toCharArray(); 341 int off = 1; 342 int size = 0; 343 while (true) { 344 char car = buf[off++]; 345 if (car == ')') { 346 break; 347 } else if (car == 'L') { 348 while (buf[off++] != ';') { 349 } 350 ++size; 351 } else if (car != '[') { 352 ++size; 353 } 354 } 355 Type[] args = new Type[size]; 356 off = 1; 357 size = 0; 358 while (buf[off] != ')') { 359 args[size] = getType(buf, off); 360 off += args[size].len + (args[size].sort == OBJECT ? 2 : 0); 361 size += 1; 362 } 363 return args; 364 } 365 366 /** 367 * Returns the Java types corresponding to the argument types of the given 368 * method. 369 * 370 * @param method a method. 371 * @return the Java types corresponding to the argument types of the given 372 * method. 373 */ 374 public static Type[] getArgumentTypes(final Method method) { 375 Class<?>[] classes = method.getParameterTypes(); 376 Type[] types = new Type[classes.length]; 377 for (int i = classes.length - 1; i >= 0; --i) { 378 types[i] = getType(classes[i]); 379 } 380 return types; 381 } 382 383 /** 384 * Returns the Java type corresponding to the return type of the given 385 * method descriptor. 386 * 387 * @param methodDescriptor a method descriptor. 388 * @return the Java type corresponding to the return type of the given 389 * method descriptor. 390 */ 391 public static Type getReturnType(final String methodDescriptor) { 392 char[] buf = methodDescriptor.toCharArray(); 393 return getType(buf, methodDescriptor.indexOf(')') + 1); 394 } 395 396 /** 397 * Returns the Java type corresponding to the return type of the given 398 * method. 399 * 400 * @param method a method. 401 * @return the Java type corresponding to the return type of the given 402 * method. 403 */ 404 public static Type getReturnType(final Method method) { 405 return getType(method.getReturnType()); 406 } 407 408 /** 409 * Computes the size of the arguments and of the return value of a method. 410 * 411 * @param desc the descriptor of a method. 412 * @return the size of the arguments of the method (plus one for the 413 * implicit this argument), argSize, and the size of its return 414 * value, retSize, packed into a single int i = 415 * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal 416 * to <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>). 417 */ 418 public static int getArgumentsAndReturnSizes(final String desc) { 419 int n = 1; 420 int c = 1; 421 while (true) { 422 char car = desc.charAt(c++); 423 if (car == ')') { 424 car = desc.charAt(c); 425 return n << 2 426 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1)); 427 } else if (car == 'L') { 428 while (desc.charAt(c++) != ';') { 429 } 430 n += 1; 431 } else if (car == '[') { 432 while ((car = desc.charAt(c)) == '[') { 433 ++c; 434 } 435 if (car == 'D' || car == 'J') { 436 n -= 1; 437 } 438 } else if (car == 'D' || car == 'J') { 439 n += 2; 440 } else { 441 n += 1; 442 } 443 } 444 } 445 446 /** 447 * Returns the Java type corresponding to the given type descriptor. For 448 * method descriptors, buf is supposed to contain nothing more than the 449 * descriptor itself. 450 * 451 * @param buf a buffer containing a type descriptor. 452 * @param off 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, 0, buf.length); 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}, 508 * {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT SHORT}, 509 * {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG}, 510 * {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY}, 511 * {@link #OBJECT OBJECT} or {@link #METHOD 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 StringBuffer b = new StringBuffer(getElementType().getClassName()); 569 for (int i = getDimensions(); i > 0; --i) { 570 b.append("[]"); 571 } 572 return b.toString(); 573 case OBJECT: 574 return new String(buf, off, len).replace('/', '.'); 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); 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 int i = <tt>(argSize << 2) | retSize</tt> 619 * (argSize is therefore equal to <tt>i >> 2</tt>, and retSize to 620 * <tt>i & 0x03</tt>). 621 */ 622 public int getArgumentsAndReturnSizes() { 623 return getArgumentsAndReturnSizes(getDescriptor()); 624 } 625 626 // ------------------------------------------------------------------------ 627 // Conversion to type descriptors 628 // ------------------------------------------------------------------------ 629 630 /** 631 * Returns the descriptor corresponding to this Java type. 632 * 633 * @return the descriptor corresponding to this Java type. 634 */ 635 public String getDescriptor() { 636 StringBuffer buf = new StringBuffer(); 637 getDescriptor(buf); 638 return buf.toString(); 639 } 640 641 /** 642 * Returns the descriptor corresponding to the given argument and return 643 * types. 644 * 645 * @param returnType the return type of the method. 646 * @param argumentTypes the argument types of the method. 647 * @return the descriptor corresponding to the given argument and return 648 * types. 649 */ 650 public static String getMethodDescriptor( 651 final Type returnType, 652 final Type... argumentTypes) 653 { 654 StringBuffer buf = new StringBuffer(); 655 buf.append('('); 656 for (int i = 0; i < argumentTypes.length; ++i) { 657 argumentTypes[i].getDescriptor(buf); 658 } 659 buf.append(')'); 660 returnType.getDescriptor(buf); 661 return buf.toString(); 662 } 663 664 /** 665 * Appends the descriptor corresponding to this Java type to the given 666 * string buffer. 667 * 668 * @param buf the string buffer to which the descriptor must be appended. 669 */ 670 private void getDescriptor(final StringBuffer buf) { 671 if (this.buf == null) { 672 // descriptor is in byte 3 of 'off' for primitive types (buf == null) 673 buf.append((char) ((off & 0xFF000000) >>> 24)); 674 } else if (sort == OBJECT) { 675 buf.append('L'); 676 buf.append(this.buf, off, len); 677 buf.append(';'); 678 } else { // sort == ARRAY || sort == METHOD 679 buf.append(this.buf, off, len); 680 } 681 } 682 683 // ------------------------------------------------------------------------ 684 // Direct conversion from classes to type descriptors, 685 // without intermediate Type objects 686 // ------------------------------------------------------------------------ 687 688 /** 689 * Returns the internal name of the given class. The internal name of a 690 * class is its fully qualified name, as returned by Class.getName(), where 691 * '.' are replaced by '/'. 692 * 693 * @param c an object or array class. 694 * @return the internal name of the given class. 695 */ 696 public static String getInternalName(final Class<?> c) { 697 return c.getName().replace('.', '/'); 698 } 699 700 /** 701 * Returns the descriptor corresponding to the given Java type. 702 * 703 * @param c an object class, a primitive class or an array class. 704 * @return the descriptor corresponding to the given class. 705 */ 706 public static String getDescriptor(final Class<?> c) { 707 StringBuffer buf = new StringBuffer(); 708 getDescriptor(buf, c); 709 return buf.toString(); 710 } 711 712 /** 713 * Returns the descriptor corresponding to the given constructor. 714 * 715 * @param c a {@link Constructor Constructor} object. 716 * @return the descriptor of the given constructor. 717 */ 718 public static String getConstructorDescriptor(final Constructor<?> c) { 719 Class<?>[] parameters = c.getParameterTypes(); 720 StringBuffer buf = new StringBuffer(); 721 buf.append('('); 722 for (int i = 0; i < parameters.length; ++i) { 723 getDescriptor(buf, parameters[i]); 724 } 725 return buf.append(")V").toString(); 726 } 727 728 /** 729 * Returns the descriptor corresponding to the given method. 730 * 731 * @param m a {@link Method Method} object. 732 * @return the descriptor of the given method. 733 */ 734 public static String getMethodDescriptor(final Method m) { 735 Class<?>[] parameters = m.getParameterTypes(); 736 StringBuffer buf = new StringBuffer(); 737 buf.append('('); 738 for (int i = 0; i < parameters.length; ++i) { 739 getDescriptor(buf, parameters[i]); 740 } 741 buf.append(')'); 742 getDescriptor(buf, m.getReturnType()); 743 return buf.toString(); 744 } 745 746 /** 747 * Appends the descriptor of the given class to the given string buffer. 748 * 749 * @param buf the string buffer to which the descriptor must be appended. 750 * @param c the class whose descriptor must be computed. 751 */ 752 private static void getDescriptor(final StringBuffer buf, final Class<?> c) { 753 Class<?> d = c; 754 while (true) { 755 if (d.isPrimitive()) { 756 char car; 757 if (d == Integer.TYPE) { 758 car = 'I'; 759 } else if (d == Void.TYPE) { 760 car = 'V'; 761 } else if (d == Boolean.TYPE) { 762 car = 'Z'; 763 } else if (d == Byte.TYPE) { 764 car = 'B'; 765 } else if (d == Character.TYPE) { 766 car = 'C'; 767 } else if (d == Short.TYPE) { 768 car = 'S'; 769 } else if (d == Double.TYPE) { 770 car = 'D'; 771 } else if (d == Float.TYPE) { 772 car = 'F'; 773 } else /* if (d == Long.TYPE) */{ 774 car = 'J'; 775 } 776 buf.append(car); 777 return; 778 } else if (d.isArray()) { 779 buf.append('['); 780 d = d.getComponentType(); 781 } else { 782 buf.append('L'); 783 String name = d.getName(); 784 int len = name.length(); 785 for (int i = 0; i < len; ++i) { 786 char car = name.charAt(i); 787 buf.append(car == '.' ? '/' : car); 788 } 789 buf.append(';'); 790 return; 791 } 792 } 793 } 794 795 // ------------------------------------------------------------------------ 796 // Corresponding size and opcodes 797 // ------------------------------------------------------------------------ 798 799 /** 800 * Returns the size of values of this type. This method must not be used for 801 * method types. 802 * 803 * @return the size of values of this type, i.e., 2 for <tt>long</tt> and 804 * <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise. 805 */ 806 public int getSize() { 807 // the size is in byte 0 of 'off' for primitive types (buf == null) 808 return buf == null ? (off & 0xFF) : 1; 809 } 810 811 /** 812 * Returns a JVM instruction opcode adapted to this Java type. This method 813 * must not be used for method types. 814 * 815 * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD, 816 * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL, 817 * ISHR, IUSHR, IAND, IOR, IXOR and IRETURN. 818 * @return an opcode that is similar to the given opcode, but adapted to 819 * this Java type. For example, if this type is <tt>float</tt> and 820 * <tt>opcode</tt> is IRETURN, this method returns FRETURN. 821 */ 822 public int getOpcode(final int opcode) { 823 if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) { 824 // the offset for IALOAD or IASTORE is in byte 1 of 'off' for 825 // primitive types (buf == null) 826 return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4); 827 } else { 828 // the offset for other instructions is in byte 2 of 'off' for 829 // primitive types (buf == null) 830 return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4); 831 } 832 } 833 834 // ------------------------------------------------------------------------ 835 // Equals, hashCode and toString 836 // ------------------------------------------------------------------------ 837 838 /** 839 * Tests if the given object is equal to this type. 840 * 841 * @param o the object to be compared to this type. 842 * @return <tt>true</tt> if the given object is equal to this type. 843 */ 844 @Override 845 public boolean equals(final Object o) { 846 if (this == o) { 847 return true; 848 } 849 if (!(o instanceof Type)) { 850 return false; 851 } 852 Type t = (Type) o; 853 if (sort != t.sort) { 854 return false; 855 } 856 if (sort >= ARRAY) { 857 if (len != t.len) { 858 return false; 859 } 860 for (int i = off, j = t.off, end = i + len; i < end; i++, j++) { 861 if (buf[i] != t.buf[j]) { 862 return false; 863 } 864 } 865 } 866 return true; 867 } 868 869 /** 870 * Returns a hash code value for this type. 871 * 872 * @return a hash code value for this type. 873 */ 874 @Override 875 public int hashCode() { 876 int hc = 13 * sort; 877 if (sort >= ARRAY) { 878 for (int i = off, end = i + len; i < end; i++) { 879 hc = 17 * (hc + buf[i]); 880 } 881 } 882 return hc; 883 } 884 885 /** 886 * Returns a string representation of this type. 887 * 888 * @return the descriptor of this type. 889 */ 890 @Override 891 public String toString() { 892 return getDescriptor(); 893 } 894 } --- EOF ---