1 package com.sun.org.apache.bcel.internal.classfile; 2 3 56 57 import com.sun.org.apache.bcel.internal.Constants; 58 import com.sun.org.apache.bcel.internal.util.ByteSequence; 59 import java.io.*; 60 import java.util.ArrayList ; 61 import java.util.zip.*; 62 63 69 public abstract class Utility { 70 private static int consumed_chars; 75 private static boolean wide=false; 84 90 public static final String accessToString(int access_flags) { 91 return accessToString(access_flags, false); 92 } 93 94 106 public static final String accessToString(int access_flags, 107 boolean for_class) 108 { 109 StringBuffer buf = new StringBuffer (); 110 111 int p = 0; 112 for(int i=0; p < Constants.MAX_ACC_FLAG; i++) { p = pow2(i); 114 115 if((access_flags & p) != 0) { 116 121 if(for_class && ((p == Constants.ACC_SUPER) || (p == Constants.ACC_INTERFACE))) 122 continue; 123 124 buf.append(Constants.ACCESS_NAMES[i] + " "); 125 } 126 } 127 128 return buf.toString().trim(); 129 } 130 131 134 public static final String classOrInterface(int access_flags) { 135 return ((access_flags & Constants.ACC_INTERFACE) != 0)? "interface" : "class"; 136 } 137 138 152 public static final String codeToString(byte[] code, 153 ConstantPool constant_pool, 154 int index, int length, boolean verbose) 155 { 156 StringBuffer buf = new StringBuffer (code.length * 20); ByteSequence stream = new ByteSequence(code); 158 159 try { 160 for(int i=0; i < index; i++) codeToString(stream, constant_pool, verbose); 162 163 for(int i=0; stream.available() > 0; i++) { 164 if((length < 0) || (i < length)) { 165 String indices = fillup(stream.getIndex() + ":", 6, true, ' '); 166 buf.append(indices + codeToString(stream, constant_pool, verbose) + '\n'); 167 } 168 } 169 } catch(IOException e) { 170 System.out.println(buf.toString()); 171 e.printStackTrace(); 172 throw new ClassFormatError ("Byte code error: " + e); 173 } 174 175 return buf.toString(); 176 } 177 178 public static final String codeToString(byte[] code, 179 ConstantPool constant_pool, 180 int index, int length) { 181 return codeToString(code, constant_pool, index, length, true); 182 } 183 184 193 public static final String codeToString(ByteSequence bytes, 194 ConstantPool constant_pool, boolean verbose) 195 throws IOException 196 { 197 short opcode = (short)bytes.readUnsignedByte(); 198 int default_offset=0, low, high, npairs; 199 int index, vindex, constant; 200 int[] match, jump_table; 201 int no_pad_bytes=0, offset; 202 StringBuffer buf = new StringBuffer (Constants.OPCODE_NAMES[opcode]); 203 204 207 if((opcode == Constants.TABLESWITCH) || (opcode == Constants.LOOKUPSWITCH)) { 208 int remainder = bytes.getIndex() % 4; 209 no_pad_bytes = (remainder == 0)? 0 : 4 - remainder; 210 211 for(int i=0; i < no_pad_bytes; i++) { 212 byte b; 213 214 if((b=bytes.readByte()) != 0) 215 System.err.println("Warning: Padding byte != 0 in " + 216 Constants.OPCODE_NAMES[opcode] + ":" + b); 217 } 218 219 default_offset = bytes.readInt(); 221 } 222 223 switch(opcode) { 224 226 case Constants.TABLESWITCH: 227 low = bytes.readInt(); 228 high = bytes.readInt(); 229 230 offset = bytes.getIndex() - 12 - no_pad_bytes - 1; 231 default_offset += offset; 232 233 buf.append("\tdefault = " + default_offset + ", low = " + low + 234 ", high = " + high + "("); 235 236 jump_table = new int[high - low + 1]; 237 for(int i=0; i < jump_table.length; i++) { 238 jump_table[i] = offset + bytes.readInt(); 239 buf.append(jump_table[i]); 240 241 if(i < jump_table.length - 1) 242 buf.append(", "); 243 } 244 buf.append(")"); 245 246 break; 247 248 250 case Constants.LOOKUPSWITCH: { 251 252 npairs = bytes.readInt(); 253 offset = bytes.getIndex() - 8 - no_pad_bytes - 1; 254 255 match = new int[npairs]; 256 jump_table = new int[npairs]; 257 default_offset += offset; 258 259 buf.append("\tdefault = " + default_offset + ", npairs = " + npairs + 260 " ("); 261 262 for(int i=0; i < npairs; i++) { 263 match[i] = bytes.readInt(); 264 265 jump_table[i] = offset + bytes.readInt(); 266 267 buf.append("(" + match[i] + ", " + jump_table[i] + ")"); 268 269 if(i < npairs - 1) 270 buf.append(", "); 271 } 272 buf.append(")"); 273 } 274 break; 275 276 279 case Constants.GOTO: case Constants.IFEQ: case Constants.IFGE: case Constants.IFGT: 280 case Constants.IFLE: case Constants.IFLT: case Constants.JSR: case Constants.IFNE: 281 case Constants.IFNONNULL: case Constants.IFNULL: case Constants.IF_ACMPEQ: 282 case Constants.IF_ACMPNE: case Constants.IF_ICMPEQ: case Constants.IF_ICMPGE: case Constants.IF_ICMPGT: 283 case Constants.IF_ICMPLE: case Constants.IF_ICMPLT: case Constants.IF_ICMPNE: 284 buf.append("\t\t#" + ((bytes.getIndex() - 1) + bytes.readShort())); 285 break; 286 287 289 case Constants.GOTO_W: case Constants.JSR_W: 290 buf.append("\t\t#" + ((bytes.getIndex() - 1) + bytes.readInt())); 291 break; 292 293 295 case Constants.ALOAD: case Constants.ASTORE: case Constants.DLOAD: case Constants.DSTORE: case Constants.FLOAD: 296 case Constants.FSTORE: case Constants.ILOAD: case Constants.ISTORE: case Constants.LLOAD: case Constants.LSTORE: 297 case Constants.RET: 298 if(wide) { 299 vindex = bytes.readUnsignedShort(); 300 wide=false; } 302 else 303 vindex = bytes.readUnsignedByte(); 304 305 buf.append("\t\t%" + vindex); 306 break; 307 308 313 case Constants.WIDE: 314 wide = true; 315 buf.append("\t(wide)"); 316 break; 317 318 320 case Constants.NEWARRAY: 321 buf.append("\t\t<" + Constants.TYPE_NAMES[bytes.readByte()] + ">"); 322 break; 323 324 326 case Constants.GETFIELD: case Constants.GETSTATIC: case Constants.PUTFIELD: case Constants.PUTSTATIC: 327 index = bytes.readUnsignedShort(); 328 buf.append("\t\t" + 329 constant_pool.constantToString(index, Constants.CONSTANT_Fieldref) + 330 (verbose? " (" + index + ")" : "")); 331 break; 332 333 335 case Constants.NEW: 336 case Constants.CHECKCAST: 337 buf.append("\t"); 338 case Constants.INSTANCEOF: 339 index = bytes.readUnsignedShort(); 340 buf.append("\t<" + constant_pool.constantToString(index, 341 Constants.CONSTANT_Class) + 342 ">" + (verbose? " (" + index + ")" : "")); 343 break; 344 345 347 case Constants.INVOKESPECIAL: case Constants.INVOKESTATIC: case Constants.INVOKEVIRTUAL: 348 index = bytes.readUnsignedShort(); 349 buf.append("\t" + constant_pool.constantToString(index, 350 Constants.CONSTANT_Methodref) + 351 (verbose? " (" + index + ")" : "")); 352 break; 353 354 case Constants.INVOKEINTERFACE: 355 index = bytes.readUnsignedShort(); 356 int nargs = bytes.readUnsignedByte(); buf.append("\t" + 358 constant_pool.constantToString(index, 359 Constants.CONSTANT_InterfaceMethodref) + 360 (verbose? " (" + index + ")\t" : "") + nargs + "\t" + 361 bytes.readUnsignedByte()); break; 363 364 366 case Constants.LDC_W: case Constants.LDC2_W: 367 index = bytes.readUnsignedShort(); 368 369 buf.append("\t\t" + constant_pool.constantToString 370 (index, constant_pool.getConstant(index).getTag()) + 371 (verbose? " (" + index + ")" : "")); 372 break; 373 374 case Constants.LDC: 375 index = bytes.readUnsignedByte(); 376 377 buf.append("\t\t" + 378 constant_pool.constantToString 379 (index, constant_pool.getConstant(index).getTag()) + 380 (verbose? " (" + index + ")" : "")); 381 break; 382 383 385 case Constants.ANEWARRAY: 386 index = bytes.readUnsignedShort(); 387 388 buf.append("\t\t<" + compactClassName(constant_pool.getConstantString 389 (index, Constants.CONSTANT_Class), false) + 390 ">" + (verbose? " (" + index + ")": "")); 391 break; 392 393 395 case Constants.MULTIANEWARRAY: { 396 index = bytes.readUnsignedShort(); 397 int dimensions = bytes.readUnsignedByte(); 398 399 buf.append("\t<" + compactClassName(constant_pool.getConstantString 400 (index, Constants.CONSTANT_Class), false) + 401 ">\t" + dimensions + (verbose? " (" + index + ")" : "")); 402 } 403 break; 404 405 407 case Constants.IINC: 408 if(wide) { 409 vindex = bytes.readUnsignedShort(); 410 constant = bytes.readShort(); 411 wide = false; 412 } 413 else { 414 vindex = bytes.readUnsignedByte(); 415 constant = bytes.readByte(); 416 } 417 buf.append("\t\t%" + vindex + "\t" + constant); 418 break; 419 420 default: 421 if(Constants.NO_OF_OPERANDS[opcode] > 0) { 422 for(int i=0; i < Constants.TYPE_OF_OPERANDS[opcode].length; i++) { 423 buf.append("\t\t"); 424 switch(Constants.TYPE_OF_OPERANDS[opcode][i]) { 425 case Constants.T_BYTE: buf.append(bytes.readByte()); break; 426 case Constants.T_SHORT: buf.append(bytes.readShort()); break; 427 case Constants.T_INT: buf.append(bytes.readInt()); break; 428 429 default: System.err.println("Unreachable default case reached!"); 431 System.exit(-1); 432 } 433 } 434 } 435 } 436 437 return buf.toString(); 438 } 439 440 public static final String codeToString(ByteSequence bytes, ConstantPool constant_pool) 441 throws IOException 442 { 443 return codeToString(bytes, constant_pool, true); 444 } 445 446 453 public static final String compactClassName(String str) { 454 return compactClassName(str, true); 455 } 456 457 468 public static final String compactClassName(String str, 469 String prefix, 470 boolean chopit) 471 { 472 int len = prefix.length(); 473 474 str = str.replace('/', '.'); 476 if(chopit) { 477 if(str.startsWith(prefix) && 479 (str.substring(len).indexOf('.') == -1)) 480 str = str.substring(len); 481 } 482 483 return str; 484 } 485 486 496 public static final String compactClassName(String str, boolean chopit) { 497 return compactClassName(str, "java.lang.", chopit); 498 } 499 500 private static final boolean is_digit(char ch) { 501 return (ch >= '0') && (ch <= '9'); 502 } 503 504 private static final boolean is_space(char ch) { 505 return (ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n'); 506 } 507 508 511 public static final int setBit(int flag, int i) { 512 return flag | pow2(i); 513 } 514 515 518 public static final int clearBit(int flag, int i) { 519 int bit = pow2(i); 520 return (flag & bit) == 0? flag : flag ^ bit; 521 } 522 523 526 public static final boolean isSet(int flag, int i) { 527 return (flag & pow2(i)) != 0; 528 } 529 530 538 public final static String methodTypeToSignature(String ret, String [] argv) 539 throws ClassFormatError 540 { 541 StringBuffer buf = new StringBuffer ("("); 542 String str; 543 544 if(argv != null) 545 for(int i=0; i < argv.length; i++) { 546 str = getSignature(argv[i]); 547 548 if(str.endsWith("V")) throw new ClassFormatError ("Invalid type: " + argv[i]); 550 551 buf.append(str); 552 } 553 554 str = getSignature(ret); 555 556 buf.append(")" + str); 557 558 return buf.toString(); 559 } 560 561 566 public static final String [] methodSignatureArgumentTypes(String signature) 567 throws ClassFormatError 568 { 569 return methodSignatureArgumentTypes(signature, true); 570 } 571 572 578 public static final String [] methodSignatureArgumentTypes(String signature, 579 boolean chopit) 580 throws ClassFormatError 581 { 582 ArrayList vec = new ArrayList (); 583 int index; 584 String [] types; 585 586 try { if(signature.charAt(0) != '(') 588 throw new ClassFormatError ("Invalid method signature: " + signature); 589 590 index = 1; 592 while(signature.charAt(index) != ')') { 593 vec.add(signatureToString(signature.substring(index), chopit)); 594 index += consumed_chars; } 596 } catch(StringIndexOutOfBoundsException e) { throw new ClassFormatError ("Invalid method signature: " + signature); 598 } 599 600 types = new String [vec.size()]; 601 vec.toArray(types); 602 return types; 603 } 604 609 public static final String methodSignatureReturnType(String signature) 610 throws ClassFormatError 611 { 612 return methodSignatureReturnType(signature, true); 613 } 614 620 public static final String methodSignatureReturnType(String signature, 621 boolean chopit) 622 throws ClassFormatError 623 { 624 int index; 625 String type; 626 627 try { 628 index = signature.lastIndexOf(')') + 1; 630 type = signatureToString(signature.substring(index), chopit); 631 } catch(StringIndexOutOfBoundsException e) { throw new ClassFormatError ("Invalid method signature: " + signature); 633 } 634 635 return type; 636 } 637 638 646 public static final String methodSignatureToString(String signature, 647 String name, 648 String access) { 649 return methodSignatureToString(signature, name, access, true); 650 } 651 652 public static final String methodSignatureToString(String signature, 653 String name, 654 String access, 655 boolean chopit) { 656 return methodSignatureToString(signature, name, access, chopit, null); 657 } 658 659 686 public static final String methodSignatureToString(String signature, 687 String name, 688 String access, 689 boolean chopit, 690 LocalVariableTable vars) 691 throws ClassFormatError 692 { 693 StringBuffer buf = new StringBuffer ("("); 694 String type; 695 int index; 696 int var_index = (access.indexOf("static") >= 0)? 0 : 1; 697 698 try { if(signature.charAt(0) != '(') 700 throw new ClassFormatError ("Invalid method signature: " + signature); 701 702 index = 1; 704 while(signature.charAt(index) != ')') { 705 buf.append(signatureToString(signature.substring(index), chopit)); 706 707 if(vars != null) { 708 LocalVariable l = vars.getLocalVariable(var_index); 709 710 if(l != null) 711 buf.append(" " + l.getName()); 712 } else 713 buf.append(" arg" + var_index); 714 715 var_index++; 716 buf.append(", "); 717 index += consumed_chars; } 719 720 index++; 722 type = signatureToString(signature.substring(index), chopit); 724 725 } catch(StringIndexOutOfBoundsException e) { throw new ClassFormatError ("Invalid method signature: " + signature); 727 } 728 729 if(buf.length() > 1) buf.setLength(buf.length() - 2); 731 732 buf.append(")"); 733 734 return access + ((access.length() > 0)? " " : "") + type + " " + name + buf.toString(); 736 } 737 738 private static final int pow2(int n) { 740 return 1 << n; 741 } 742 743 751 public static final String replace(String str, String old, String new_) { 752 int index, old_index; 753 StringBuffer buf = new StringBuffer (); 754 755 try { 756 if((index = str.indexOf(old)) != -1) { old_index = 0; 759 while((index = str.indexOf(old, old_index)) != -1) { 761 buf.append(str.substring(old_index, index)); buf.append(new_); 764 old_index = index + old.length(); } 766 767 buf.append(str.substring(old_index)); str = buf.toString(); 769 } 770 } catch(StringIndexOutOfBoundsException e) { System.err.println(e); 772 } 773 774 return str; 775 } 776 777 783 public static final String signatureToString(String signature) { 784 return signatureToString(signature, true); 785 } 786 787 821 public static final String signatureToString(String signature, 822 boolean chopit) 823 { 824 consumed_chars = 1; 826 try { 827 switch(signature.charAt(0)) { 828 case 'B' : return "byte"; 829 case 'C' : return "char"; 830 case 'D' : return "double"; 831 case 'F' : return "float"; 832 case 'I' : return "int"; 833 case 'J' : return "long"; 834 835 case 'L' : { int index = signature.indexOf(';'); 838 if(index < 0) 839 throw new ClassFormatError ("Invalid signature: " + signature); 840 841 consumed_chars = index + 1; 843 return compactClassName(signature.substring(1, index), chopit); 844 } 845 846 case 'S' : return "short"; 847 case 'Z' : return "boolean"; 848 849 case '[' : { int n; 851 StringBuffer buf, brackets; 852 String type; 853 char ch; 854 int consumed_chars; 856 brackets = new StringBuffer (); 858 for(n=0; signature.charAt(n) == '['; n++) 860 brackets.append("[]"); 861 862 consumed_chars = n; 864 type = signatureToString(signature.substring(n), chopit); 866 867 Utility.consumed_chars += consumed_chars; 868 return type + brackets.toString(); 869 } 870 871 case 'V' : return "void"; 872 873 default : throw new ClassFormatError ("Invalid signature: `" + 874 signature + "'"); 875 } 876 } catch(StringIndexOutOfBoundsException e) { throw new ClassFormatError ("Invalid signature: " + e + ":" + signature); 878 } 879 } 880 881 887 public static String getSignature(String type) { 888 StringBuffer buf = new StringBuffer (); 889 char[] chars = type.toCharArray(); 890 boolean char_found = false, delim = false; 891 int index = -1; 892 893 loop: 894 for(int i=0; i < chars.length; i++) { 895 switch(chars[i]) { 896 case ' ': case '\t': case '\n': case '\r': case '\f': 897 if(char_found) 898 delim = true; 899 break; 900 901 case '[': 902 if(!char_found) 903 throw new RuntimeException ("Illegal type: " + type); 904 905 index = i; 906 break loop; 907 908 default: 909 char_found = true; 910 if(!delim) 911 buf.append(chars[i]); 912 } 913 } 914 915 int brackets = 0; 916 917 if(index > 0) 918 brackets = countBrackets(type.substring(index)); 919 920 type = buf.toString(); 921 buf.setLength(0); 922 923 for(int i=0; i < brackets; i++) 924 buf.append('['); 925 926 boolean found = false; 927 928 for(int i=Constants.T_BOOLEAN; (i <= Constants.T_VOID) && !found; i++) { 929 if(Constants.TYPE_NAMES[i].equals(type)) { 930 found = true; 931 buf.append(Constants.SHORT_TYPE_NAMES[i]); 932 } 933 } 934 935 if(!found) buf.append('L' + type.replace('.', '/') + ';'); 937 938 return buf.toString(); 939 } 940 941 private static int countBrackets(String brackets) { 942 char[] chars = brackets.toCharArray(); 943 int count = 0; 944 boolean open = false; 945 946 for(int i=0; i<chars.length; i++) { 947 switch(chars[i]) { 948 case '[': 949 if(open) 950 throw new RuntimeException ("Illegally nested brackets:" + brackets); 951 open = true; 952 break; 953 954 case ']': 955 if(!open) 956 throw new RuntimeException ("Illegally nested brackets:" + brackets); 957 open = false; 958 count++; 959 break; 960 961 default: 962 } 964 } 965 966 if(open) 967 throw new RuntimeException ("Illegally nested brackets:" + brackets); 968 969 return count; 970 } 971 972 979 public static final byte typeOfMethodSignature(String signature) 980 throws ClassFormatError 981 { 982 int index; 983 984 try { 985 if(signature.charAt(0) != '(') 986 throw new ClassFormatError ("Invalid method signature: " + signature); 987 988 index = signature.lastIndexOf(')') + 1; 989 return typeOfSignature(signature.substring(index)); 990 } catch(StringIndexOutOfBoundsException e) { 991 throw new ClassFormatError ("Invalid method signature: " + signature); 992 } 993 } 994 995 1002 public static final byte typeOfSignature(String signature) 1003 throws ClassFormatError 1004 { 1005 try { 1006 switch(signature.charAt(0)) { 1007 case 'B' : return Constants.T_BYTE; 1008 case 'C' : return Constants.T_CHAR; 1009 case 'D' : return Constants.T_DOUBLE; 1010 case 'F' : return Constants.T_FLOAT; 1011 case 'I' : return Constants.T_INT; 1012 case 'J' : return Constants.T_LONG; 1013 case 'L' : return Constants.T_REFERENCE; 1014 case '[' : return Constants.T_ARRAY; 1015 case 'V' : return Constants.T_VOID; 1016 case 'Z' : return Constants.T_BOOLEAN; 1017 case 'S' : return Constants.T_SHORT; 1018 default: 1019 throw new ClassFormatError ("Invalid method signature: " + signature); 1020 } 1021 } catch(StringIndexOutOfBoundsException e) { 1022 throw new ClassFormatError ("Invalid method signature: " + signature); 1023 } 1024 } 1025 1026 1028 public static short searchOpcode(String name) { 1029 name = name.toLowerCase(); 1030 1031 for(short i=0; i < Constants.OPCODE_NAMES.length; i++) 1032 if(Constants.OPCODE_NAMES[i].equals(name)) 1033 return i; 1034 1035 return -1; 1036 } 1037 1038 1042 private static final short byteToShort(byte b) { 1043 return (b < 0)? (short)(256 + b) : (short)b; 1044 } 1045 1046 1050 public static final String toHexString(byte[] bytes) { 1051 StringBuffer buf = new StringBuffer (); 1052 1053 for(int i=0; i < bytes.length; i++) { 1054 short b = byteToShort(bytes[i]); 1055 String hex = Integer.toString(b, 0x10); 1056 1057 if(b < 0x10) buf.append('0'); 1059 1060 buf.append(hex); 1061 1062 if(i < bytes.length - 1) 1063 buf.append(' '); 1064 } 1065 1066 return buf.toString(); 1067 } 1068 1069 1079 public static final String format(int i, int length, boolean left_justify, char fill) { 1080 return fillup(Integer.toString(i), length, left_justify, fill); 1081 } 1082 1083 1092 public static final String fillup(String str, int length, boolean left_justify, char fill) { 1093 int len = length - str.length(); 1094 char[] buf = new char[(len < 0)? 0 : len]; 1095 1096 for(int j=0; j < buf.length; j++) 1097 buf[j] = fill; 1098 1099 if(left_justify) 1100 return str + new String (buf); 1101 else 1102 return new String (buf) + str; 1103 } 1104 1105 static final boolean equals(byte[] a, byte[] b) { 1106 int size; 1107 1108 if((size=a.length) != b.length) 1109 return false; 1110 1111 for(int i=0; i < size; i++) 1112 if(a[i] != b[i]) 1113 return false; 1114 1115 return true; 1116 } 1117 1118 public static final void printArray(PrintStream out, Object [] obj) { 1119 out.println(printArray(obj, true)); 1120 } 1121 1122 public static final void printArray(PrintWriter out, Object [] obj) { 1123 out.println(printArray(obj, true)); 1124 } 1125 1126 public static final String printArray(Object [] obj) { 1127 return printArray(obj, true); 1128 } 1129 1130 public static final String printArray(Object [] obj, boolean braces) { 1131 if(obj == null) 1132 return null; 1133 1134 StringBuffer buf = new StringBuffer (); 1135 if(braces) 1136 buf.append('{'); 1137 1138 for(int i=0; i < obj.length; i++) { 1139 if(obj[i] != null) 1140 buf.append(obj[i].toString()); 1141 else 1142 buf.append("null"); 1143 1144 if(i < obj.length - 1) 1145 buf.append(", "); 1146 } 1147 1148 if(braces) 1149 buf.append('}'); 1150 1151 return buf.toString(); 1152 } 1153 1154 1156 public static boolean isJavaIdentifierPart(char ch) { 1157 return ((ch >= 'a') && (ch <= 'z')) || 1158 ((ch >= 'A') && (ch <= 'Z')) || 1159 ((ch >= '0') && (ch <= '9')) || 1160 (ch == '_'); 1161 } 1162 1163 1179 public static String encode(byte[] bytes, boolean compress) throws IOException { 1180 if(compress) { 1181 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 1182 GZIPOutputStream gos = new GZIPOutputStream(baos); 1183 1184 gos.write(bytes, 0, bytes.length); 1185 gos.close(); 1186 baos.close(); 1187 1188 bytes = baos.toByteArray(); 1189 } 1190 1191 CharArrayWriter caw = new CharArrayWriter(); 1192 JavaWriter jw = new JavaWriter(caw); 1193 1194 for(int i=0; i < bytes.length; i++) { 1195 int in = bytes[i] & 0x000000ff; jw.write(in); 1197 } 1198 1199 return caw.toString(); 1200 } 1201 1202 1207 public static byte[] decode(String s, boolean uncompress) throws IOException { 1208 char[] chars = s.toCharArray(); 1209 1210 CharArrayReader car = new CharArrayReader(chars); 1211 JavaReader jr = new JavaReader(car); 1212 1213 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 1214 1215 int ch; 1216 1217 while((ch = jr.read()) >= 0) { 1218 bos.write(ch); 1219 } 1220 1221 bos.close(); 1222 car.close(); 1223 jr.close(); 1224 1225 byte[] bytes = bos.toByteArray(); 1226 1227 if(uncompress) { 1228 GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(bytes)); 1229 1230 byte[] tmp = new byte[bytes.length * 3]; int count = 0; 1232 int b; 1233 1234 while((b = gis.read()) >= 0) 1235 tmp[count++] = (byte)b; 1236 1237 bytes = new byte[count]; 1238 System.arraycopy(tmp, 0, bytes, 0, count); 1239 } 1240 1241 return bytes; 1242 } 1243 1244 private static final int FREE_CHARS = 48; 1246 private static int[] CHAR_MAP = new int[FREE_CHARS]; 1247 private static int[] MAP_CHAR = new int[256]; private static final char ESCAPE_CHAR = '$'; 1249 1250 static { 1251 int j = 0, k = 0; 1252 for(int i='A'; i <= 'Z'; i++) { 1253 CHAR_MAP[j] = i; 1254 MAP_CHAR[i] = j; 1255 j++; 1256 } 1257 1258 for(int i='g'; i <= 'z'; i++) { 1259 CHAR_MAP[j] = i; 1260 MAP_CHAR[i] = j; 1261 j++; 1262 } 1263 1264 CHAR_MAP[j] = '$'; 1265 MAP_CHAR['$'] = j; 1266 j++; 1267 1268 CHAR_MAP[j] = '_'; 1269 MAP_CHAR['_'] = j; 1270 } 1271 1272 1275 private static class JavaReader extends FilterReader { 1276 public JavaReader(Reader in) { 1277 super(in); 1278 } 1279 1280 public int read() throws IOException { 1281 int b = in.read(); 1282 1283 if(b != ESCAPE_CHAR) { 1284 return b; 1285 } else { 1286 int i = in.read(); 1287 1288 if(i < 0) 1289 return -1; 1290 1291 if(((i >= '0') && (i <= '9')) || ((i >= 'a') && (i <= 'f'))) { int j = in.read(); 1293 1294 if(j < 0) 1295 return -1; 1296 1297 char[] tmp = { (char)i, (char)j }; 1298 int s = Integer.parseInt(new String (tmp), 16); 1299 1300 return s; 1301 } else { return MAP_CHAR[i]; 1303 } 1304 } 1305 } 1306 1307 public int read(char[] cbuf, int off, int len) throws IOException { 1308 for(int i=0; i < len; i++) 1309 cbuf[off + i] = (char)read(); 1310 1311 return len; 1312 } 1313 } 1314 1315 1318 private static class JavaWriter extends FilterWriter { 1319 public JavaWriter(Writer out) { 1320 super(out); 1321 } 1322 1323 public void write(int b) throws IOException { 1324 if(isJavaIdentifierPart((char)b) && (b != ESCAPE_CHAR)) { 1325 out.write(b); 1326 } else { 1327 out.write(ESCAPE_CHAR); 1329 if(b >= 0 && b < FREE_CHARS) { 1331 out.write(CHAR_MAP[b]); 1332 } else { char[] tmp = Integer.toHexString(b).toCharArray(); 1334 1335 if(tmp.length == 1) { 1336 out.write('0'); 1337 out.write(tmp[0]); 1338 } else { 1339 out.write(tmp[0]); 1340 out.write(tmp[1]); 1341 } 1342 } 1343 } 1344 } 1345 1346 public void write(char[] cbuf, int off, int len) throws IOException { 1347 for(int i=0; i < len; i++) 1348 write(cbuf[off + i]); 1349 } 1350 1351 public void write(String str, int off, int len) throws IOException { 1352 write(str.toCharArray(), off, len); 1353 } 1354 } 1355} 1356 | Popular Tags |