📄 utf8.java
字号:
package UTF;import java.io.DataOutput;import java.io.IOException;import Clazz.jq_ClassFileConstants;import Run_Time.Debug;import Util.Assert;import Util.Collections.UnmodifiableIterator;/** * @author John Whaley <jwhaley@alum.mit.edu> * @version $Id: Utf8.java,v 1.17 2003/05/23 21:10:56 joewhaley Exp $ */public class Utf8 implements jq_ClassFileConstants { public static /*final*/ boolean TRACE = false; public static final int STARTING_TABLE_SIZE = 16384; public static final int STARTING_HASH_SIZE = 9999; public static final int STARTING_CHAIN_SIZE = 4; public static Utf8[] table = new Utf8[STARTING_TABLE_SIZE]; public static int size = -1; public static int[][] chains = new int[STARTING_HASH_SIZE][]; // for hashing public static final Utf8 BYTE_DESC = Utf8.get((char)TC_BYTE+""); public static final Utf8 CHAR_DESC = Utf8.get((char)TC_CHAR+""); public static final Utf8 DOUBLE_DESC = Utf8.get((char)TC_DOUBLE+""); public static final Utf8 FLOAT_DESC = Utf8.get((char)TC_FLOAT+""); public static final Utf8 INT_DESC = Utf8.get((char)TC_INT+""); public static final Utf8 LONG_DESC = Utf8.get((char)TC_LONG+""); public static final Utf8 SHORT_DESC = Utf8.get((char)TC_SHORT+""); public static final Utf8 BOOLEAN_DESC = Utf8.get((char)TC_BOOLEAN+""); public static final Utf8 VOID_DESC = Utf8.get((char)TC_VOID+""); public static Utf8 get(String s) { return get(toUtf8(s)); } public static Utf8 get(byte[] b) { int id = getID(b); return table[id]; } public static Utf8 get(byte[] b, int startIndex, int endIndex) { int id = getID(b, startIndex, endIndex); return table[id]; } public static int getID(byte[] b) { int hash = hashCode(b); int chain_index = Math.abs(hash) % chains.length; int[] chain = chains[chain_index]; if (chain == null) { chains[chain_index] = chain = new int[STARTING_CHAIN_SIZE]; return addToTable_helper(b, hash, chain, 0); } for (int i=0; i<chain.length; ++i) { int id = chain[i]-1; if (id == -1) { // end of chain return addToTable_helper(b, hash, chain, i); } Utf8 utf8 = table[id]; // ??? check hash before memcmp ??? if (memcmp(utf8.data, b)) { // ??? swap first one and this one ??? return id; } } int[] newchain = new int[chain.length<<1]; System.arraycopy(chain, 0, newchain, 0, chain.length); chains[chain_index] = newchain; return addToTable_helper(b, hash, newchain, chain.length); // free chain // todo: rehash when the table gets too full... } public static int getID(byte[] b, int startIndex, int endIndex) { int hash = hashCode(b, startIndex, endIndex); int chain_index = Math.abs(hash) % chains.length; int[] chain = chains[chain_index]; if (chain == null) { chains[chain_index] = chain = new int[STARTING_CHAIN_SIZE]; byte[] b2 = new byte[endIndex-startIndex]; System.arraycopy(b, startIndex, b2, 0, endIndex-startIndex); return addToTable_helper(b2, hash, chain, 0); } for (int i=0; i<chain.length; ++i) { int id = chain[i]-1; if (id == -1) { // end of chain byte[] b2 = new byte[endIndex-startIndex]; System.arraycopy(b, startIndex, b2, 0, endIndex-startIndex); return addToTable_helper(b2, hash, chain, i); } Utf8 utf8 = table[id]; // ??? check hash before memcmp ??? if (memcmp(utf8.data, b, startIndex, endIndex)) { // ??? swap first one and this one ??? return id; } } int[] newchain = new int[chain.length<<1]; System.arraycopy(chain, 0, newchain, 0, chain.length); chains[chain_index] = newchain; byte[] b2 = new byte[endIndex-startIndex]; System.arraycopy(b, startIndex, b2, 0, endIndex-startIndex); return addToTable_helper(b2, hash, newchain, chain.length); // free(chain) // todo: rehash when the table gets too full... } public boolean isValidMethodDescriptor() { if (data.length < 3) return false; if (data[0] != TC_PARAM) return false; int i=1; while (data[i] != TC_PARAMEND) {here: switch (data[i]) { case TC_BYTE: case TC_CHAR: case TC_DOUBLE: case TC_FLOAT: case TC_INT: case TC_LONG: case TC_SHORT: case TC_BOOLEAN: case TC_ARRAY: break; case TC_CLASS: for (;;) { if (++i == data.length) return false; if (data[i] == TC_CLASSEND) break here; } default: return false; } if (++i == data.length) return false; } ++i; return ((data[i] == TC_VOID) && (i == data.length-1)) || isValidTypeDescriptor(i); } public boolean isValidTypeDescriptor() { return isValidTypeDescriptor(0); } private boolean isValidTypeDescriptor(int i) { for (;;) { if (data.length == i) return false; switch (data[i]) { case TC_BYTE: case TC_CHAR: case TC_DOUBLE: case TC_FLOAT: case TC_INT: case TC_LONG: case TC_SHORT: case TC_BOOLEAN: return i == data.length-1; case TC_ARRAY: ++i; continue; case TC_CLASS: for (;;) { if (++i == data.length) return false; if (data[i] == TC_CLASSEND) return i == data.length-1; } default: return false; } } } public boolean isDescriptor(byte desc) { return (data.length > 0) && (data[0] == desc); } public Utf8 getArrayElementDescriptor() { Assert._assert(isDescriptor(TC_ARRAY)); return get(data, 1, data.length); } public Utf8 getClassName() { Assert._assert(isDescriptor(TC_CLASS)); return get(data, 1, data.length-1); } public Utf8 getAsArrayDescriptor() { Assert._assert(isValidTypeDescriptor()); // todo: might need to reevaluate making a new array on every query. byte[] b = new byte[data.length+1]; b[0] = TC_ARRAY; System.arraycopy(data, 0, b, 1, data.length); return get(b); } public Utf8 getAsClassDescriptor() { Assert._assert(data[0] != TC_ARRAY); // todo: might need to reevaluate making a new array on every query. byte[] b = new byte[data.length+2]; b[0] = TC_CLASS; System.arraycopy(data, 0, b, 1, data.length); b[data.length+1] = TC_CLASSEND; return get(b); } public MethodDescriptorIterator getParamDescriptors() { return new MethodDescriptorIterator(); } public class MethodDescriptorIterator extends UnmodifiableIterator { int currentIndex; MethodDescriptorIterator() { Assert._assert(isDescriptor(TC_PARAM)); currentIndex = 0; } public boolean hasNext() { return data[currentIndex+1] != TC_PARAMEND; } public Object next() { return nextUtf8(); } public Utf8 nextUtf8() { byte b = data[++currentIndex]; int startIndex = currentIndex; while (b == TC_ARRAY) { b = data[++currentIndex]; } if (b == TC_CLASS) { while (b != TC_CLASSEND) { b = data[++currentIndex]; } } else { if ((b != TC_BYTE) && (b != TC_CHAR) && (b != TC_DOUBLE) && (b != TC_FLOAT) && (b != TC_INT) && (b != TC_LONG) && (b != TC_SHORT) && (b != TC_BOOLEAN)) { throw new ClassFormatError("bad method descriptor: "+fromUtf8(data)+" index: "+currentIndex); } } return get(data, startIndex, currentIndex+1); } public Utf8 getReturnDescriptor() { Assert._assert(!hasNext()); return get(data, currentIndex+2, data.length); } } //// Implementation stuff below. // Helper function. private static boolean memcmp(byte[] b1, byte[] b2) { if (b1.length != b2.length) return false; for (int i=b1.length; --i>=0; ) { if (b1[i] != b2[i]) return false; } return true; } private static boolean memcmp(byte[] b1, byte[] b2, int startIndex, int endIndex) { if (b1.length != (endIndex-startIndex)) return false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -