📄 utility.java
字号:
type = buf.toString(); buf.setLength(0); for(int i=0; i < brackets; i++) buf.append('['); boolean found = false; for(int i=Constants.T_BOOLEAN; (i <= Constants.T_VOID) && !found; i++) { if(Constants.TYPE_NAMES[i].equals(type)) { found = true; buf.append(Constants.SHORT_TYPE_NAMES[i]); } } if(!found) // Class name buf.append('L' + type.replace('.', '/') + ';'); return buf.toString(); } private static int countBrackets(String brackets) { char[] chars = brackets.toCharArray(); int count = 0; boolean open = false; for(int i=0; i<chars.length; i++) { switch(chars[i]) { case '[': if(open) throw new RuntimeException("Illegally nested brackets:" + brackets); open = true; break; case ']': if(!open) throw new RuntimeException("Illegally nested brackets:" + brackets); open = false; count++; break; default: // Don't care } } if(open) throw new RuntimeException("Illegally nested brackets:" + brackets); return count; } /** * Return type of method signature as a byte value as defined in <em>Constants</em> * * @param signature in format described above * @return type of method signature * @see Constants */ public static final byte typeOfMethodSignature(String signature) throws ClassFormatError { int index; try { if(signature.charAt(0) != '(') throw new ClassFormatError("Invalid method signature: " + signature); index = signature.lastIndexOf(')') + 1; return typeOfSignature(signature.substring(index)); } catch(StringIndexOutOfBoundsException e) { throw new ClassFormatError("Invalid method signature: " + signature); } } /** * Return type of signature as a byte value as defined in <em>Constants</em> * * @param signature in format described above * @return type of signature * @see Constants */ public static final byte typeOfSignature(String signature) throws ClassFormatError { try { switch(signature.charAt(0)) { case 'B' : return Constants.T_BYTE; case 'C' : return Constants.T_CHAR; case 'D' : return Constants.T_DOUBLE; case 'F' : return Constants.T_FLOAT; case 'I' : return Constants.T_INT; case 'J' : return Constants.T_LONG; case 'L' : return Constants.T_REFERENCE; case '[' : return Constants.T_ARRAY; case 'V' : return Constants.T_VOID; case 'Z' : return Constants.T_BOOLEAN; case 'S' : return Constants.T_SHORT; default: throw new ClassFormatError("Invalid method signature: " + signature); } } catch(StringIndexOutOfBoundsException e) { throw new ClassFormatError("Invalid method signature: " + signature); } } /** Map opcode names to opcode numbers. E.g., return Constants.ALOAD for "aload" */ public static short searchOpcode(String name) { name = name.toLowerCase(); for(short i=0; i < Constants.OPCODE_NAMES.length; i++) if(Constants.OPCODE_NAMES[i].equals(name)) return i; return -1; } /** * Convert (signed) byte to (unsigned) short value, i.e., all negative * values become positive. */ private static final short byteToShort(byte b) { return (b < 0)? (short)(256 + b) : (short)b; } /** Convert bytes into hexidecimal string * * @return bytes as hexidecimal string, e.g. 00 FA 12 ... */ public static final String toHexString(byte[] bytes) { StringBuffer buf = new StringBuffer(); for(int i=0; i < bytes.length; i++) { short b = byteToShort(bytes[i]); String hex = Integer.toString(b, 0x10); if(b < 0x10) // just one digit, prepend '0' buf.append('0'); buf.append(hex); if(i < bytes.length - 1) buf.append(' '); } return buf.toString(); } /** * Return a string for an integer justified left or right and filled up with * `fill' characters if necessary. * * @param i integer to format * @param length length of desired string * @param left_justify format left or right * @param fill fill character * @return formatted int */ public static final String format(int i, int length, boolean left_justify, char fill) { return fillup(Integer.toString(i), length, left_justify, fill); } /** * Fillup char with up to length characters with char `fill' and justify it left or right. * * @param str string to format * @param length length of desired string * @param left_justify format left or right * @param fill fill character * @return formatted string */ public static final String fillup(String str, int length, boolean left_justify, char fill) { int len = length - str.length(); char[] buf = new char[(len < 0)? 0 : len]; for(int j=0; j < buf.length; j++) buf[j] = fill; if(left_justify) return str + new String(buf); else return new String(buf) + str; } static final boolean equals(byte[] a, byte[] b) { int size; if((size=a.length) != b.length) return false; for(int i=0; i < size; i++) if(a[i] != b[i]) return false; return true; } public static final void printArray(PrintStream out, Object[] obj) { out.println(printArray(obj, true)); } public static final void printArray(PrintWriter out, Object[] obj) { out.println(printArray(obj, true)); } public static final String printArray(Object[] obj) { return printArray(obj, true); } public static final String printArray(Object[] obj, boolean braces) { if(obj == null) return null; StringBuffer buf = new StringBuffer(); if(braces) buf.append('{'); for(int i=0; i < obj.length; i++) { if(obj[i] != null) buf.append(obj[i].toString()); else buf.append("null"); if(i < obj.length - 1) buf.append(", "); } if(braces) buf.append('}'); return buf.toString(); } /** @return true, if character is one of (a, ... z, A, ... Z, 0, ... 9, _) */ public static boolean isJavaIdentifierPart(char ch) { return ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) || ((ch >= '0') && (ch <= '9')) || (ch == '_'); } /** Encode byte array it into Java identifier string, i.e., a string * that only contains the following characters: (a, ... z, A, ... Z, * 0, ... 9, _, $). The encoding algorithm itself is not too * clever: if the current byte's ASCII value already is a valid Java * identifier part, leave it as it is. Otherwise it writes the * escape character($) followed by <p><ul><li> the ASCII value as a * hexadecimal string, if the value is not in the range * 200..247</li> <li>a Java identifier char not used in a lowercase * hexadecimal string, if the value is in the range * 200..247</li><ul></p> * * <p>This operation inflates the original byte array by roughly 40-50%</p> * * @param bytes the byte array to convert * @param compress use gzip to minimize string */ public static String encode(byte[] bytes, boolean compress) throws IOException { if(compress) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); GZIPOutputStream gos = new GZIPOutputStream(baos); gos.write(bytes, 0, bytes.length); gos.close(); baos.close(); bytes = baos.toByteArray(); } CharArrayWriter caw = new CharArrayWriter(); JavaWriter jw = new JavaWriter(caw); for(int i=0; i < bytes.length; i++) { int in = bytes[i] & 0x000000ff; // Normalize to unsigned jw.write(in); } return caw.toString(); } /** Decode a string back to a byte array. * * @param bytes the byte array to convert * @param uncompress use gzip to uncompress the stream of bytes */ public static byte[] decode(String s, boolean uncompress) throws IOException { char[] chars = s.toCharArray(); CharArrayReader car = new CharArrayReader(chars); JavaReader jr = new JavaReader(car); ByteArrayOutputStream bos = new ByteArrayOutputStream(); int ch; while((ch = jr.read()) >= 0) { bos.write(ch); } bos.close(); car.close(); jr.close(); byte[] bytes = bos.toByteArray(); if(uncompress) { GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(bytes)); byte[] tmp = new byte[bytes.length * 3]; // Rough estimate int count = 0; int b; while((b = gis.read()) >= 0) tmp[count++] = (byte)b; bytes = new byte[count]; System.arraycopy(tmp, 0, bytes, 0, count); } return bytes; } // A-Z, g-z, _, $ private static final int FREE_CHARS = 48; private static int[] CHAR_MAP = new int[FREE_CHARS]; private static int[] MAP_CHAR = new int[256]; // Reverse map private static final char ESCAPE_CHAR = '$'; static { int j = 0, k = 0; for(int i='A'; i <= 'Z'; i++) { CHAR_MAP[j] = i; MAP_CHAR[i] = j; j++; } for(int i='g'; i <= 'z'; i++) { CHAR_MAP[j] = i; MAP_CHAR[i] = j; j++; } CHAR_MAP[j] = '$'; MAP_CHAR['$'] = j; j++; CHAR_MAP[j] = '_'; MAP_CHAR['_'] = j; } /** Decode characters into bytes. * Used by <a href="Utility.html#decode(java.lang.String, boolean)">decode()</a> */ private static class JavaReader extends FilterReader { public JavaReader(Reader in) { super(in); } public int read() throws IOException { int b = in.read(); if(b != ESCAPE_CHAR) { return b; } else { int i = in.read(); if(i < 0) return -1; if(((i >= '0') && (i <= '9')) || ((i >= 'a') && (i <= 'f'))) { // Normal escape int j = in.read(); if(j < 0) return -1; char[] tmp = { (char)i, (char)j }; int s = Integer.parseInt(new String(tmp), 16); return s; } else { // Special escape return MAP_CHAR[i]; } } } public int read(char[] cbuf, int off, int len) throws IOException { for(int i=0; i < len; i++) cbuf[off + i] = (char)read(); return len; } } /** Encode bytes into valid java identifier characters. * Used by <a href="Utility.html#encode(byte[], boolean)">encode()</a> */ private static class JavaWriter extends FilterWriter { public JavaWriter(Writer out) { super(out); } public void write(int b) throws IOException { if(isJavaIdentifierPart((char)b) && (b != ESCAPE_CHAR)) { out.write(b); } else { out.write(ESCAPE_CHAR); // Escape character // Special escape if(b >= 0 && b < FREE_CHARS) { out.write(CHAR_MAP[b]); } else { // Normal escape char[] tmp = Integer.toHexString(b).toCharArray(); if(tmp.length == 1) { out.write('0'); out.write(tmp[0]); } else { out.write(tmp[0]); out.write(tmp[1]); } } } } public void write(char[] cbuf, int off, int len) throws IOException { for(int i=0; i < len; i++) write(cbuf[off + i]); } public void write(String str, int off, int len) throws IOException { write(str.toCharArray(), off, len); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -