Path: blob/master/src/java.base/share/classes/java/lang/CharacterName.java
41152 views
/*1* Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.lang;2627import java.io.DataInputStream;28import java.io.InputStream;29import java.lang.ref.SoftReference;30import java.util.Arrays;31import java.util.Locale;32import java.util.zip.InflaterInputStream;33import java.security.AccessController;34import java.security.PrivilegedAction;3536class CharacterName {3738private static SoftReference<CharacterName> refCharName;3940// codepoint -> bkIndex -> lookup -> offset/len41private final byte[] strPool;42private final int[] lookup; // code point -> offset/len in strPool43private final int[] bkIndices; // code point -> lookup index4445// name -> hash -> hsIndices -> cpEntries -> code point46private final int[] cpEntries; // code points that have name in strPool47private final int[] hsIndices; // chain heads, hash indices into "cps"4849private CharacterName() {50try (@SuppressWarnings("removal") DataInputStream dis = new DataInputStream(new InflaterInputStream(51AccessController.doPrivileged(new PrivilegedAction<>() {52public InputStream run() {53return getClass().getResourceAsStream("uniName.dat");54}55})))) {5657int total = dis.readInt();58int bkNum = dis.readInt();59int cpNum = dis.readInt();60int cpEnd = dis.readInt();61byte ba[] = new byte[cpEnd];62lookup = new int[bkNum * 256];63bkIndices = new int[(Character.MAX_CODE_POINT + 1) >> 8];64strPool = new byte[total - cpEnd];65cpEntries = new int[cpNum * 3];66hsIndices = new int[(cpNum / 2) | 1];67Arrays.fill(bkIndices, -1);68Arrays.fill(hsIndices, -1);69dis.readFully(ba);70dis.readFully(strPool);7172int nameOff = 0;73int cpOff = 0;74int cp = 0;75int bk = -1;76int prevBk = -1; // prev bkNo;77int idx = 0;78int next = -1;79int hash = 0;80int hsh = 0;81do {82int len = ba[cpOff++] & 0xff;83if (len == 0) {84len = ba[cpOff++] & 0xff;85// always big-endian86cp = ((ba[cpOff++] & 0xff) << 16) |87((ba[cpOff++] & 0xff) << 8) |88((ba[cpOff++] & 0xff));89} else {90cp++;91}92// cp -> name93int hi = cp >> 8;94if (prevBk != hi) {95bk++;96bkIndices[hi] = bk;97prevBk = hi;98}99lookup[(bk << 8) + (cp & 0xff)] = (nameOff << 8) | len;100// name -> cp101hash = hashN(strPool, nameOff, len);102hsh = (hash & 0x7fffffff) % hsIndices.length;103next = hsIndices[hsh];104hsIndices[hsh] = idx;105idx = addCp(idx, hash, next, cp);106nameOff += len;107} while (cpOff < cpEnd);108} catch (Exception x) {109throw new InternalError(x.getMessage(), x);110}111}112113private static final int hashN(byte[] a, int off, int len) {114int h = 1;115while (len-- > 0) {116h = 31 * h + a[off++];117}118return h;119}120121private int addCp(int idx, int hash, int next, int cp) {122cpEntries[idx++] = hash;123cpEntries[idx++] = next;124cpEntries[idx++] = cp;125return idx;126}127128private int getCpHash(int idx) { return cpEntries[idx]; }129private int getCpNext(int idx) { return cpEntries[idx + 1]; }130private int getCp(int idx) { return cpEntries[idx + 2]; }131132public static CharacterName getInstance() {133SoftReference<CharacterName> ref = refCharName;134CharacterName cname = null;135if (ref == null || (cname = ref.get()) == null) {136cname = new CharacterName();137refCharName = new SoftReference<>(cname);138}139return cname;140}141142public String getName(int cp) {143int off = 0;144int bk = bkIndices[cp >> 8];145if (bk == -1 || (off = lookup[(bk << 8) + (cp & 0xff)]) == 0)146return null;147@SuppressWarnings("deprecation")148String result = new String(strPool, 0, off >>> 8, off & 0xff); // ASCII149return result;150}151152public int getCodePoint(String name) {153byte[] bname = name.getBytes(sun.nio.cs.ISO_8859_1.INSTANCE);154int hsh = hashN(bname, 0, bname.length);155int idx = hsIndices[(hsh & 0x7fffffff) % hsIndices.length];156while (idx != -1) {157if (getCpHash(idx) == hsh) {158int cp = getCp(idx);159int off = -1;160int bk = bkIndices[cp >> 8];161if (bk != -1 && (off = lookup[(bk << 8) + (cp & 0xff)]) != 0) {162int len = off & 0xff;163off = off >>> 8;164if (bname.length == len) {165int i = 0;166while (i < len && bname[i] == strPool[off++]) {167i++;168}169if (i == len) {170return cp;171}172}173}174}175idx = getCpNext(idx);176}177return -1;178}179}180181182