📄 character.java
字号:
/** * Returns a value indicating a character category. * * @param ch the character to be tested. * @return the Unicode category of the character as an integer. */ public static int getType(char ch) { return getCharProp(ch).category; } public static boolean isISOControl(char ch) { if (ch < 32) { // U+0000 - U+001F return (true); } if (ch < 127) { return (false); } if (ch < 160) { // U+007F - U+009F return (true); } return (false); } public static boolean isJavaIdentifierPart(char ch) { switch (getType(ch)) { case UPPERCASE_LETTER: case LOWERCASE_LETTER: case TITLECASE_LETTER: case MODIFIER_LETTER: case OTHER_LETTER: case CURRENCY_SYMBOL: case CONNECTOR_PUNCTUATION: case DECIMAL_DIGIT_NUMBER: case LETTER_NUMBER: case COMBINING_SPACING_MARK: case NON_SPACING_MARK: return (true); default: return isIdentifierIgnorable(ch); } } public static boolean isJavaIdentifierStart(char ch) { switch (getType(ch)) { case UPPERCASE_LETTER: case LOWERCASE_LETTER: case TITLECASE_LETTER: case MODIFIER_LETTER: case OTHER_LETTER: case CURRENCY_SYMBOL: case CONNECTOR_PUNCTUATION: return (true); default: return (false); } } public static boolean isSpaceChar(char ch) { switch (getType(ch)) { case SPACE_SEPARATOR: case LINE_SEPARATOR: case PARAGRAPH_SEPARATOR: return (true); default: return (false); } } public static boolean isUnicodeIdentifierPart(char ch) { switch (getType(ch)) { case UPPERCASE_LETTER: case LOWERCASE_LETTER: case TITLECASE_LETTER: case MODIFIER_LETTER: case OTHER_LETTER: case CONNECTOR_PUNCTUATION: case DECIMAL_DIGIT_NUMBER: case LETTER_NUMBER: case COMBINING_SPACING_MARK: case NON_SPACING_MARK: return (true); default: return isIdentifierIgnorable(ch); } } public static boolean isUnicodeIdentifierStart(char ch) { return (isLetter(ch)); } public static boolean isWhitespace(char ch) { switch ((int)ch) { case 0x0009: // HORIZONTAL TABULATION. case 0x000A: // LINE FEED. case 0x000B: // VERTICAL TABULATION. case 0x000C: // FORM FEED. case 0x000D: // CARRIAGE RETURN. case 0x001C: // FILE SEPARATOR. case 0x001D: // GROUP SEPARATOR. case 0x001E: // RECORD SEPARATOR. case 0x001F: // UNIT SEPARATOR. return (true); } switch (getType(ch)) { case SPACE_SEPARATOR: // but not a no-break separator return (!getCharProp(ch).noBreak); case LINE_SEPARATOR: case PARAGRAPH_SEPARATOR: return (true); default: return (false); } } private static class CharacterProperties { char unicode; int category; boolean noBreak; short numeric; char upper; char lower; char title; static IntegerHashtable cache = new IntegerHashtable(); CharacterProperties(char unicode, int category, boolean noBreak, short numeric, char upper, char lower, char title) { this.unicode = unicode; this.category = category; this.noBreak = noBreak; this.numeric = numeric; this.upper = upper; this.lower = lower; this.title = title; cache.put((int)unicode, this); } private static byte propTable[]; // three basic type tables of N entries are // better than one tablee of N objects private static char rangeStart[]; private static char rangeEnd[]; private static int rangeOffset[]; static { try { propTable = getResource("kaffe/lang/unicode.tbl"); } catch (IOException e) { throw new Error("Missing Kaffe Unicode Database table: " + e); } byte tbl[]; try { tbl = getResource("kaffe/lang/unicode.idx"); } catch (IOException e) { throw new Error("Missing Kaffe Unicode Database index: " + e); } if (tbl.length % 7 != 0) { throw new Error("Corrupted Kaffe Unicode Database"); } int n = tbl.length / 7; rangeStart = new char[n]; rangeEnd = new char[n]; rangeOffset = new int[n]; for (int i = 0, o = 0; i < n; i++, o += 7) { rangeStart[i] = (char)(((tbl[o] & 0xFF) << 8) + (tbl[o + 1] & 0xFF)); rangeEnd[i] = (char)(((tbl[o + 2] & 0xFF) << 8) + (tbl[o + 3] & 0xFF)); rangeOffset[i] = (int)(((tbl[o + 4] & 0xFF) << 16) + ((tbl[o + 5] & 0xFF) << 8) + (tbl[o + 6] & 0xFF)); } } // Read in a resource and convert it to a byte array private static byte[] getResource(String name) throws IOException { String pathSep = System.getProperties().getProperty("path.separator"); String classpath = System.getProperties().getProperty("java.class.path"); StringTokenizer t = new StringTokenizer(classpath, pathSep); InputStream in = null; while (t.hasMoreTokens()) { try { ZipFile zf = new ZipFile(t.nextToken()); if (zf != null) { ZipEntry ze = zf.getEntry(name); if (ze != null) { in = zf.getInputStream(ze); break; } } } catch (IOException e) { /* Be more error tolerant: if a classpath * entry is not existant or corrupted, * ignore it. * * We can not print the exception since * CharacterProperties are not initialized yet. */ } }// InputStream in = Character.class.getResourceAsStream(name); if (in == null) { throw new IOException("not found"); } ByteArrayOutputStream out = new ByteArrayOutputStream(5000); byte[] buf = new byte[1024]; int r; while ((r = in.read(buf)) != -1) { out.write(buf, 0, r); } return out.toByteArray(); } /** * Lookup the corresponding range for the character ch. * @param ch the character searched. * @return the index of his range or -1. */ private static int getIndex(char ch) { // use local tables char start[] = rangeStart; char end[] = rangeEnd; int lo = 0; int hi = start.length - 1; while (lo <= hi) { int med = (lo + hi) >> 1; if (ch < start[med]) { hi = med - 1; } else if (ch > end[med]) { lo = med + 1; } else { return med; } } return -1; } /** * Decode the properties of the character ch with the range index * index. * @param ch the query character. * @param index the range index for this character. * @return the properties of the character ch. */ private static CharacterProperties decodeProp(char ch, int index) { byte tbl[] = propTable; byte method = (byte)((rangeOffset[index] >> 20) & 0x3); int offset = rangeOffset[index] & 0xFFFFF; if (method == 0) { // not compressed, add delta to offset offset += 3 * ((int)ch - (int)rangeStart[index]); } else if (method == 3) { // not compressed, extended entry offset += 9 * ((int)ch - (int)rangeStart[index]); } boolean noBreak = false; int category = tbl[offset] & 0x1F; if (category == 31) { category = 12; noBreak = true; } if (method < 3) { // 0: not compressed // 1: compressed, same value // 2: compressed, one increment char generic = (char)(((tbl[offset + 1] & 0xFF) << 8) + (tbl[offset + 2] & 0xFF)); if (method == 2) { // compressed, one increment, add delta to value generic += (short)(0xFFFF & ((int)ch - (int)rangeStart[index])); } switch ((tbl[offset] >> 5) & 0x3) { // field case 0: // none return new CharacterProperties(ch, category, noBreak, (short)-1, (char)0x0000, (char)0x0000, (char)0x0000); case 1: // uppercase and titlecase return new CharacterProperties(ch, category, noBreak, (short)-1, generic, (char)0x0000, generic); case 2: // lowercase return new CharacterProperties(ch, category, noBreak, (short)-1, (char)0x0000, generic, (char)0x0000); default: // numeric return new CharacterProperties(ch, category, noBreak, (short)generic, (char)0x0000, (char)0x0000, (char)0x0000); } } // 3: not compressed, extended entry short numeric = (short)(((tbl[offset + 1] & 0xFF) << 8) + (tbl[offset + 2] & 0xFF)); char upper = (char)(((tbl[offset + 3] & 0xFF) << 8) + (tbl[offset + 4] & 0xFF)); char lower = (char)(((tbl[offset + 5] & 0xFF) << 8) + (tbl[offset + 6] & 0xFF)); char title = (char)(((tbl[offset + 7] & 0xFF) << 8) + (tbl[offset + 8] & 0xFF)); return new CharacterProperties(ch, category, noBreak, numeric, upper, lower, title); } } private static CharacterProperties getCharProp(char ch) { // consult the cache CharacterProperties chProp = (CharacterProperties)CharacterProperties.cache.get((int)ch); if (chProp != null) { return chProp; } // lookup int index = CharacterProperties.getIndex(ch); if (index < 0) { chProp = new CharacterProperties(ch, UNASSIGNED, false, (short)-1, (char)0x0000, (char)0x0000, (char)0x0000); } else { chProp = CharacterProperties.decodeProp(ch, index); } return chProp; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -