00001 package de.fub.bytecode.classfile;
00002
00003 import de.fub.bytecode.Constants;
00004 import de.fub.bytecode.util.ByteSequence;
00005 import java.io.*;
00006 import java.util.Vector;
00007
00008
00009
00010
00011
00012
00013
00014 public abstract class Utility {
00015 private static int consumed_chars;
00016
00017
00018
00019
00020 private static boolean wide=false;
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 public static final String accessToString(int access_flags) {
00036 return accessToString(access_flags, false);
00037 }
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 public static final String accessToString(int access_flags,
00051 boolean for_class)
00052 {
00053 StringBuffer buf = new StringBuffer();
00054
00055 int p = 0;
00056 for(int i=0; p < Constants.MAX_ACC_FLAG; i++) {
00057 p = pow2(i);
00058
00059 if((access_flags & p) != 0) {
00060
00061
00062
00063
00064
00065 if(for_class && ((p == Constants.ACC_SUPER) || (p == Constants.ACC_INTERFACE)))
00066 continue;
00067
00068 buf.append(Constants.ACCESS_NAMES[i] + " ");
00069 }
00070 }
00071
00072 return buf.toString().trim();
00073 }
00074
00075
00076
00077
00078 private static final short byteToShort(byte b) {
00079 return (b < 0)? (short)(256 + b) : (short)b;
00080 }
00081
00082
00083
00084 public static final String classOrInterface(int access_flags) {
00085 return ((access_flags & Constants.ACC_INTERFACE) != 0)? "interface" : "class";
00086 }
00087
00088
00089
00090 public static final int clearBit(int flag, int i) {
00091 int bit = pow2(i);
00092 return (flag & bit) == 0? flag : flag ^ bit;
00093 }
00094 public static final String codeToString(byte[] code,
00095 ConstantPool constant_pool,
00096 int index, int length) {
00097 return codeToString(code, constant_pool, index, length, true);
00098 }
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 public static final String codeToString(byte[] code,
00114 ConstantPool constant_pool,
00115 int index, int length, boolean verbose)
00116 {
00117 StringBuffer buf = new StringBuffer(code.length * 20);
00118 ByteSequence stream = new ByteSequence(code);
00119
00120 try {
00121 for(int i=0; i < index; i++)
00122 codeToString(stream, constant_pool, verbose);
00123
00124 for(int i=0; stream.available() > 0; i++) {
00125 if((length < 0) || (i < length)) {
00126 String indices = fillup(stream.getIndex() + ":", 6, true, ' ');
00127 buf.append(indices + codeToString(stream, constant_pool, verbose) + '\n');
00128 }
00129 }
00130 } catch(IOException e) {
00131 System.out.println(buf.toString());
00132 e.printStackTrace();
00133 throw new ClassFormatError("Byte code error: " + e);
00134 }
00135
00136 return buf.toString();
00137 }
00138 public static final String codeToString(ByteSequence bytes, ConstantPool constant_pool)
00139 throws IOException
00140 {
00141 return codeToString(bytes, constant_pool, true);
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 public static final String codeToString(ByteSequence bytes,
00153 ConstantPool constant_pool, boolean verbose)
00154 throws IOException
00155 {
00156 short opcode = (short)bytes.readUnsignedByte();
00157 int default_offset=0, low, high, npairs;
00158 int index, vindex, constant;
00159 int[] match, jump_table;
00160 int no_pad_bytes=0, offset;
00161 StringBuffer buf = new StringBuffer(Constants.OPCODE_NAMES[opcode]);
00162
00163
00164
00165
00166 if((opcode == Constants.TABLESWITCH) || (opcode == Constants.LOOKUPSWITCH)) {
00167 int remainder = bytes.getIndex() % 4;
00168 no_pad_bytes = (remainder == 0)? 0 : 4 - remainder;
00169
00170 for(int i=0; i < no_pad_bytes; i++) {
00171 byte b;
00172
00173 if((b=bytes.readByte()) != 0)
00174 System.err.println("Ooops. Padding byte != 0 " + b);
00175 }
00176
00177
00178 default_offset = bytes.readInt();
00179 }
00180
00181 switch(opcode) {
00182
00183
00184 case Constants.TABLESWITCH:
00185 low = bytes.readInt();
00186 high = bytes.readInt();
00187
00188 offset = bytes.getIndex() - 12 - no_pad_bytes - 1;
00189 default_offset += offset;
00190
00191 buf.append("\tdefault = " + default_offset + ", low = " + low +
00192 ", high = " + high + "(");
00193
00194 jump_table = new int[high - low + 1];
00195 for(int i=0; i < jump_table.length; i++) {
00196 jump_table[i] = offset + bytes.readInt();
00197 buf.append(jump_table[i]);
00198
00199 if(i < jump_table.length - 1)
00200 buf.append(", ");
00201 }
00202 buf.append(")");
00203
00204 break;
00205
00206
00207
00208 case Constants.LOOKUPSWITCH: {
00209
00210 npairs = bytes.readInt();
00211 offset = bytes.getIndex() - 8 - no_pad_bytes - 1;
00212
00213 match = new int[npairs];
00214 jump_table = new int[npairs];
00215 default_offset += offset;
00216
00217 buf.append("\tdefault = " + default_offset + ", npairs = " + npairs +
00218 " (");
00219
00220 for(int i=0; i < npairs; i++) {
00221 match[i] = bytes.readInt();
00222
00223 jump_table[i] = offset + bytes.readInt();
00224
00225 buf.append("(" + match[i] + ", " + jump_table[i] + ")");
00226
00227 if(i < npairs - 1)
00228 buf.append(", ");
00229 }
00230 buf.append(")");
00231 }
00232 break;
00233
00234
00235
00236
00237 case Constants.GOTO: case Constants.IFEQ: case Constants.IFGE: case Constants.IFGT:
00238 case Constants.IFLE: case Constants.IFLT: case Constants.JSR: case Constants.IFNE:
00239 case Constants.IFNONNULL: case Constants.IFNULL: case Constants.IF_ACMPEQ:
00240 case Constants.IF_ACMPNE: case Constants.IF_ICMPEQ: case Constants.IF_ICMPGE: case Constants.IF_ICMPGT:
00241 case Constants.IF_ICMPLE: case Constants.IF_ICMPLT: case Constants.IF_ICMPNE:
00242 buf.append("\t\t#" + ((bytes.getIndex() - 1) + bytes.readShort()));
00243 break;
00244
00245
00246
00247 case Constants.GOTO_W: case Constants.JSR_W:
00248 buf.append("\t\t#" + ((bytes.getIndex() - 1) + bytes.readInt()));
00249 break;
00250
00251
00252
00253 case Constants.ALOAD: case Constants.ASTORE: case Constants.DLOAD: case Constants.DSTORE: case Constants.FLOAD:
00254 case Constants.FSTORE: case Constants.ILOAD: case Constants.ISTORE: case Constants.LLOAD: case Constants.LSTORE:
00255 case Constants.RET:
00256 if(wide) {
00257 vindex = bytes.readUnsignedShort();
00258 wide=false;
00259 }
00260 else
00261 vindex = bytes.readUnsignedByte();
00262
00263 buf.append("\t\t%" + vindex);
00264 break;
00265
00266
00267
00268
00269
00270
00271 case Constants.WIDE:
00272 wide = true;
00273 buf.append("\t(wide)");
00274 break;
00275
00276
00277
00278 case Constants.NEWARRAY:
00279 buf.append("\t\t<" + Constants.TYPE_NAMES[bytes.readByte()] + ">");
00280 break;
00281
00282
00283
00284 case Constants.GETFIELD: case Constants.GETSTATIC: case Constants.PUTFIELD: case Constants.PUTSTATIC:
00285 index = bytes.readUnsignedShort();
00286 buf.append("\t\t" +
00287 constant_pool.constantToString(index, Constants.CONSTANT_Fieldref) +
00288 (verbose? " (" + index + ")" : ""));
00289 break;
00290
00291
00292
00293 case Constants.NEW:
00294 case Constants.CHECKCAST:
00295 buf.append("\t");
00296 case Constants.INSTANCEOF:
00297 index = bytes.readUnsignedShort();
00298 buf.append("\t<" + constant_pool.constantToString(index,
00299 Constants.CONSTANT_Class) +
00300 ">" + (verbose? " (" + index + ")" : ""));
00301 break;
00302
00303
00304
00305 case Constants.INVOKESPECIAL: case Constants.INVOKESTATIC: case Constants.INVOKEVIRTUAL:
00306 index = bytes.readUnsignedShort();
00307 buf.append("\t" + constant_pool.constantToString(index,
00308 Constants.CONSTANT_Methodref) +
00309 (verbose? " (" + index + ")" : ""));
00310 break;
00311
00312 case Constants.INVOKEINTERFACE:
00313 index = bytes.readUnsignedShort();
00314 int nargs = bytes.readUnsignedByte();
00315 buf.append("\t" +
00316 constant_pool.constantToString(index,
00317 Constants.CONSTANT_InterfaceMethodref) +
00318 (verbose? " (" + index + ")\t" : "") + nargs + "\t" +
00319 bytes.readUnsignedByte());
00320 break;
00321
00322
00323
00324 case Constants.LDC_W: case Constants.LDC2_W:
00325 index = bytes.readUnsignedShort();
00326
00327 buf.append("\t\t" + constant_pool.constantToString
00328 (index, constant_pool.getConstant(index).getTag()) +
00329 (verbose? " (" + index + ")" : ""));
00330 break;
00331
00332 case Constants.LDC:
00333 index = bytes.readUnsignedByte();
00334
00335 buf.append("\t\t" +
00336 constant_pool.constantToString
00337 (index, constant_pool.getConstant(index).getTag()) +
00338 (verbose? " (" + index + ")" : ""));
00339 break;
00340
00341
00342
00343 case Constants.ANEWARRAY:
00344 index = bytes.readUnsignedShort();
00345
00346 buf.append("\t\t<" + compactClassName(constant_pool.getConstantString
00347 (index, Constants.CONSTANT_Class), false) +
00348 ">" + (verbose? " (" + index + ")": ""));
00349 break;
00350
00351
00352
00353 case Constants.MULTIANEWARRAY: {
00354 index = bytes.readUnsignedShort();
00355 int dimensions = bytes.readUnsignedByte();
00356
00357 buf.append("\t<" + compactClassName(constant_pool.getConstantString
00358 (index, Constants.CONSTANT_Class), false) +
00359 ">\t" + dimensions + (verbose? " (" + index + ")" : ""));
00360 }
00361 break;
00362
00363
00364
00365 case Constants.IINC:
00366 if(wide) {
00367 vindex = bytes.readUnsignedShort();
00368 constant = bytes.readShort();
00369 wide = false;
00370 }
00371 else {
00372 vindex = bytes.readUnsignedByte();
00373 constant = bytes.readByte();
00374 }
00375 buf.append("\t\t%" + vindex + "\t" + constant);
00376 break;
00377
00378 default:
00379 if(Constants.NO_OF_OPERANDS[opcode] > 0) {
00380 for(int i=0; i < Constants.TYPE_OF_OPERANDS[opcode].length; i++) {
00381 buf.append("\t\t");
00382 switch(Constants.TYPE_OF_OPERANDS[opcode][i]) {
00383 case Constants.T_BYTE: buf.append(bytes.readByte()); break;
00384 case Constants.T_SHORT: buf.append(bytes.readShort()); break;
00385 case Constants.T_INT: buf.append(bytes.readInt()); break;
00386
00387 default:
00388 System.err.println("Unreachable default case reached!");
00389 System.exit(-1);
00390 }
00391 }
00392 }
00393 }
00394
00395 return buf.toString();
00396 }
00397
00398
00399
00400
00401
00402
00403
00404 public static final String compactClassName(String str) {
00405 return compactClassName(str, true);
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 public static final String compactClassName(String str,
00419 String prefix,
00420 boolean chopit)
00421 {
00422 int len = prefix.length();
00423
00424 str = str.replace('/', '.');
00425
00426 if(chopit) {
00427
00428 if(str.startsWith(prefix) &&
00429 (str.substring(len).indexOf('.') == -1))
00430 str = str.substring(len);
00431 }
00432
00433 return str;
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 public static final String compactClassName(String str, boolean chopit) {
00446 return compactClassName(str, "java.lang.", chopit);
00447 }
00448 private static int countBrackets(String brackets) {
00449 char[] chars = brackets.toCharArray();
00450 int count = 0;
00451 boolean open = false;
00452
00453 for(int i=0; i<chars.length; i++) {
00454 switch(chars[i]) {
00455 case '[':
00456 if(open)
00457 throw new RuntimeException("Illegally nested brackets:" + brackets);
00458 open = true;
00459 break;
00460
00461 case ']':
00462 if(!open)
00463 throw new RuntimeException("Illegally nested brackets:" + brackets);
00464 open = false;
00465 count++;
00466 break;
00467
00468 default:
00469
00470 }
00471 }
00472
00473 if(open)
00474 throw new RuntimeException("Illegally nested brackets:" + brackets);
00475
00476 return count;
00477 }
00478 static final boolean equals(byte[] a, byte[] b) {
00479 int size;
00480
00481 if((size=a.length) != b.length)
00482 return false;
00483
00484 for(int i=0; i < size; i++)
00485 if(a[i] != b[i])
00486 return false;
00487
00488 return true;
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499 public static final String fillup(String str, int length, boolean left_justify, char fill) {
00500 int len = length - str.length();
00501 char[] buf = new char[(len < 0)? 0 : len];
00502
00503 for(int j=0; j < buf.length; j++)
00504 buf[j] = fill;
00505
00506 if(left_justify)
00507 return str + new String(buf);
00508 else
00509 return new String(buf) + str;
00510 }
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521 public static final String format(int i, int length, boolean left_justify, char fill) {
00522 return fillup(Integer.toString(i), length, left_justify, fill);
00523 }
00524
00525
00526
00527
00528
00529
00530 public static String getSignature(String type) {
00531 StringBuffer buf = new StringBuffer();
00532 char[] chars = type.toCharArray();
00533 boolean char_found = false, delim = false;
00534 int index = -1;
00535
00536 loop:
00537 for(int i=0; i<chars.length; i++) {
00538 switch(chars[i]) {
00539 case ' ': case '\t': case '\n': case '\r': case '\f':
00540 if(char_found)
00541 delim = true;
00542 break;
00543
00544 case '[':
00545 if(!char_found)
00546 throw new RuntimeException("Illegal type: " + type);
00547
00548 index = i;
00549 break loop;
00550
00551 default:
00552 char_found = true;
00553 if(!delim)
00554 buf.append(chars[i]);
00555 }
00556 }
00557
00558 int brackets = 0;
00559
00560 if(index > 0)
00561 brackets = countBrackets(type.substring(index));
00562
00563 type = buf.toString();
00564 buf.setLength(0);
00565
00566 for(int i=0; i < brackets; i++)
00567 buf.append('[');
00568
00569 boolean found = false;
00570
00571 for(int i=Constants.T_BOOLEAN; (i <= Constants.T_LONG) && !found; i++) {
00572 if(Constants.TYPE_NAMES[i].equals(type)) {
00573 found = true;
00574 buf.append(Constants.SHORT_TYPE_NAMES[i]);
00575 }
00576 }
00577
00578 if(!found)
00579 buf.append('L' + type.replace('.', '/') + ';');
00580
00581 return buf.toString();
00582 }
00583 private static final boolean is_digit(char ch) {
00584 return (ch >= '0') && (ch <= '9');
00585 }
00586 private static final boolean is_space(char ch) {
00587 return (ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n');
00588 }
00589
00590
00591
00592 public static final boolean isSet(int flag, int i) {
00593 return (flag & pow2(i)) != 0;
00594 }
00595
00596
00597
00598
00599
00600 public static final String[] methodSignatureArgumentTypes(String signature)
00601 throws ClassFormatError
00602 {
00603 return methodSignatureArgumentTypes(signature, true);
00604 }
00605
00606
00607
00608
00609
00610
00611 public static final String[] methodSignatureArgumentTypes(String signature,
00612 boolean chopit)
00613 throws ClassFormatError
00614 {
00615 Vector vec = new Vector();
00616 int index;
00617 String[] types;
00618
00619 try {
00620 if(signature.charAt(0) != '(')
00621 throw new ClassFormatError("Invalid method signature: " + signature);
00622
00623 index = 1;
00624
00625 while(signature.charAt(index) != ')') {
00626 vec.addElement(signatureToString(signature.substring(index), chopit));
00627 index += consumed_chars;
00628 }
00629 } catch(StringIndexOutOfBoundsException e) {
00630 throw new ClassFormatError("Invalid method signature: " + signature);
00631 }
00632
00633 types = new String[vec.size()];
00634 vec.copyInto(types);
00635 return types;
00636 }
00637
00638
00639
00640
00641
00642 public static final String methodSignatureReturnType(String signature)
00643 throws ClassFormatError
00644 {
00645 return methodSignatureReturnType(signature, true);
00646 }
00647
00648
00649
00650
00651
00652
00653 public static final String methodSignatureReturnType(String signature,
00654 boolean chopit)
00655 throws ClassFormatError
00656 {
00657 int index;
00658 String type;
00659
00660 try {
00661
00662 index = signature.lastIndexOf(')') + 1;
00663 type = signatureToString(signature.substring(index), chopit);
00664 } catch(StringIndexOutOfBoundsException e) {
00665 throw new ClassFormatError("Invalid method signature: " + signature);
00666 }
00667
00668 return type;
00669 }
00670
00671
00672
00673
00674
00675
00676
00677
00678 public static final String methodSignatureToString(String signature,
00679 String name,
00680 String access) {
00681 return methodSignatureToString(signature, name, access, true);
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710 public static final String methodSignatureToString(String signature,
00711 String name,
00712 String access,
00713 boolean chopit)
00714 throws ClassFormatError
00715 {
00716 StringBuffer buf = new StringBuffer("(");
00717 String type;
00718 int index;
00719
00720 try {
00721 if(signature.charAt(0) != '(')
00722 throw new ClassFormatError("Invalid method signature: " + signature);
00723
00724 index = 1;
00725
00726 while(signature.charAt(index) != ')') {
00727 buf.append(signatureToString(signature.substring(index), chopit) +
00728 ", ");
00729 index += consumed_chars;
00730 }
00731
00732 index++;
00733
00734
00735 type = signatureToString(signature.substring(index), chopit);
00736
00737 } catch(StringIndexOutOfBoundsException e) {
00738 throw new ClassFormatError("Invalid method signature: " + signature);
00739 }
00740
00741 if(buf.length() > 1)
00742 buf.setLength(buf.length() - 2);
00743
00744 buf.append(")");
00745
00746 return access + ((access.length() > 0)?" " : "") +
00747 type + " " + name + buf.toString();
00748 }
00749
00750
00751
00752
00753
00754
00755
00756
00757 public final static String methodTypeToSignature(String ret, String[] argv)
00758 throws ClassFormatError
00759 {
00760 StringBuffer buf = new StringBuffer("(");
00761 String str;
00762
00763 if(argv != null)
00764 for(int i=0; i < argv.length; i++) {
00765 str = typeToSignature(argv[i]);
00766
00767 if(str.endsWith("V"))
00768 throw new ClassFormatError("Invalid type: " + argv[i]);
00769
00770 buf.append(str);
00771 }
00772
00773 str = typeToSignature(ret);
00774
00775 buf.append(")" + str);
00776
00777 return buf.toString();
00778 }
00779
00780 private static final int pow2(int n) {
00781 return 1 << n;
00782 }
00783 public static final String printArray(Object[] obj) {
00784 return printArray(obj, true);
00785 }
00786 public static final String printArray(Object[] obj, boolean braces) {
00787 if(obj == null)
00788 return null;
00789
00790 StringBuffer buf = new StringBuffer();
00791 if(braces)
00792 buf.append('{');
00793
00794 for(int i=0; i < obj.length; i++) {
00795 if(obj[i] != null)
00796 buf.append(obj[i].toString());
00797 else
00798 buf.append("null");
00799
00800 if(i < obj.length - 1)
00801 buf.append(", ");
00802 }
00803
00804 if(braces)
00805 buf.append('}');
00806
00807 return buf.toString();
00808 }
00809 public static final void printArray(PrintStream out, Object[] obj) {
00810 out.println(printArray(obj, true));
00811 }
00812 public static final void printArray(PrintWriter out, Object[] obj) {
00813 out.println(printArray(obj, true));
00814 }
00815
00816
00817
00818
00819
00820
00821
00822
00823 public static final String replace(String str, String old, String new_) {
00824 int index, old_index;
00825 StringBuffer buf = new StringBuffer();
00826
00827 try {
00828 if((index = str.indexOf(old)) != -1) {
00829 old_index = 0;
00830
00831
00832 while((index = str.indexOf(old, old_index)) != -1) {
00833 buf.append(str.substring(old_index, index));
00834 buf.append(new_);
00835
00836 old_index = index + old.length();
00837 }
00838
00839 buf.append(str.substring(old_index));
00840 str = buf.toString();
00841 }
00842 } catch(StringIndexOutOfBoundsException e) {
00843 System.err.println(e);
00844 }
00845
00846 return str;
00847 }
00848
00849
00850 public static short searchOpcode(String name) {
00851 name = name.toLowerCase();
00852
00853 for(short i=0; i < Constants.OPCODE_NAMES.length; i++)
00854 if(Constants.OPCODE_NAMES[i].equals(name))
00855 return i;
00856
00857 return -1;
00858 }
00859
00860
00861
00862 public static final int setBit(int flag, int i) {
00863 return flag | pow2(i);
00864 }
00865
00866
00867
00868
00869
00870
00871 public static final String signatureToString(String signature) {
00872 return signatureToString(signature, true);
00873 }
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908 public static final String signatureToString(String signature,
00909 boolean chopit)
00910 {
00911 consumed_chars = 1;
00912
00913 try {
00914 switch(signature.charAt(0)) {
00915 case 'B' : return "byte";
00916 case 'C' : return "char";
00917 case 'D' : return "double";
00918 case 'F' : return "float";
00919 case 'I' : return "int";
00920 case 'J' : return "long";
00921
00922 case 'L' : {
00923 int index = signature.indexOf(';');
00924
00925 if(index < 0)
00926 throw new ClassFormatError("Invalid signature: " + signature);
00927
00928 consumed_chars = index + 1;
00929
00930 return compactClassName(signature.substring(1, index), chopit);
00931 }
00932
00933 case 'S' : return "short";
00934 case 'Z' : return "boolean";
00935
00936 case '[' : {
00937 int n;
00938 StringBuffer buf, brackets;
00939 String type;
00940 char ch;
00941 int consumed_chars;
00942
00943 brackets = new StringBuffer();
00944
00945
00946 for(n=0; signature.charAt(n) == '['; n++)
00947 brackets.append("[]");
00948
00949 consumed_chars = n;
00950
00951
00952 type = signatureToString(signature.substring(n), chopit);
00953
00954 Utility.consumed_chars += consumed_chars;
00955 return type + brackets.toString();
00956 }
00957
00958 case 'V' : return "void";
00959
00960 default : throw new ClassFormatError("Invalid signature: `" +
00961 signature + "'");
00962 }
00963 } catch(StringIndexOutOfBoundsException e) {
00964 throw new ClassFormatError("Invalid signature: " + e + ":" + signature);
00965 }
00966 }
00967
00968
00969
00970
00971 public static final String toHexString(byte[] bytes) {
00972 StringBuffer buf = new StringBuffer();
00973
00974 for(int i=0; i < bytes.length; i++) {
00975 short b = byteToShort(bytes[i]);
00976 String hex = Integer.toString(b, 0x10);
00977
00978 if(b < 0x10)
00979 buf.append('0');
00980
00981 buf.append(hex);
00982
00983 if(i < bytes.length - 1)
00984 buf.append(' ');
00985 }
00986
00987 return buf.toString();
00988 }
00989
00990
00991
00992
00993
00994
00995
00996 public static final byte typeOfMethodSignature(String signature)
00997 throws ClassFormatError
00998 {
00999 int index;
01000
01001 try {
01002 if(signature.charAt(0) != '(')
01003 throw new ClassFormatError("Invalid method signature: " + signature);
01004
01005 index = signature.lastIndexOf(')') + 1;
01006 return typeOfSignature(signature.substring(index));
01007 } catch(StringIndexOutOfBoundsException e) {
01008 throw new ClassFormatError("Invalid method signature: " + signature);
01009 }
01010 }
01011
01012
01013
01014
01015
01016
01017
01018 public static final byte typeOfSignature(String signature)
01019 throws ClassFormatError
01020 {
01021 try {
01022 switch(signature.charAt(0)) {
01023 case 'B' : return Constants.T_BYTE;
01024 case 'C' : return Constants.T_CHAR;
01025 case 'D' : return Constants.T_DOUBLE;
01026 case 'F' : return Constants.T_FLOAT;
01027 case 'I' : return Constants.T_INT;
01028 case 'J' : return Constants.T_LONG;
01029 case 'L' : return Constants.T_REFERENCE;
01030 case '[' : return Constants.T_ARRAY;
01031 case 'V' : return Constants.T_VOID;
01032 case 'Z' : return Constants.T_BOOLEAN;
01033 case 'S' : return Constants.T_SHORT;
01034 default:
01035 throw new ClassFormatError("Invalid method signature: " + signature);
01036 }
01037 } catch(StringIndexOutOfBoundsException e) {
01038 throw new ClassFormatError("Invalid method signature: " + signature);
01039 }
01040 }
01041
01042
01043
01044
01045
01046
01047
01048
01049 public final static String typeToSignature(String str) {
01050 return getSignature(str);
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108 }
01109 }