src/java.base/share/classes/java/lang/CharacterName.java

Print this page


   1 /*
   2  * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang;
  27 
  28 import java.io.DataInputStream;
  29 import java.io.InputStream;
  30 import java.lang.ref.SoftReference;
  31 import java.util.Arrays;

  32 import java.util.zip.InflaterInputStream;
  33 import java.security.AccessController;
  34 import java.security.PrivilegedAction;
  35 
  36 class CharacterName {
  37 
  38     private static SoftReference<byte[]> refStrPool;
  39     private static int[][] lookup;
  40 
  41     private static synchronized byte[] initNamePool() {
  42         byte[] strPool = null;
  43         if (refStrPool != null && (strPool = refStrPool.get()) != null)
  44             return strPool;
  45         DataInputStream dis = null;
  46         try {
  47             dis = new DataInputStream(new InflaterInputStream(
  48                 AccessController.doPrivileged(new PrivilegedAction<>()
  49                 {



  50                     public InputStream run() {
  51                         return getClass().getResourceAsStream("uniName.dat");
  52                     }
  53                 })));
  54 
  55             lookup = new int[(Character.MAX_CODE_POINT + 1) >> 8][];
  56             int total = dis.readInt();


  57             int cpEnd = dis.readInt();
  58             byte ba[] = new byte[cpEnd];







  59             dis.readFully(ba);

  60 
  61             int nameOff = 0;
  62             int cpOff = 0;
  63             int cp = 0;






  64             do {
  65                 int len = ba[cpOff++] & 0xff;
  66                 if (len == 0) {
  67                     len = ba[cpOff++] & 0xff;
  68                     // always big-endian
  69                     cp = ((ba[cpOff++] & 0xff) << 16) |
  70                          ((ba[cpOff++] & 0xff) <<  8) |
  71                          ((ba[cpOff++] & 0xff));
  72                 }  else {
  73                     cp++;
  74                 }

  75                 int hi = cp >> 8;
  76                 if (lookup[hi] == null) {
  77                     lookup[hi] = new int[0x100];
  78                 }
  79                 lookup[hi][cp&0xff] = (nameOff << 8) | len;








  80                 nameOff += len;
  81             } while (cpOff < cpEnd);
  82             strPool = new byte[total - cpEnd];
  83             dis.readFully(strPool);
  84             refStrPool = new SoftReference<>(strPool);
  85         } catch (Exception x) {
  86             throw new InternalError(x.getMessage(), x);
  87         } finally {
  88             try {
  89                 if (dis != null)
  90                     dis.close();
  91             } catch (Exception xx) {}
  92         }
  93         return strPool;









  94     }
  95 
  96     public static String get(int cp) {
  97         byte[] strPool = null;
  98         if (refStrPool == null || (strPool = refStrPool.get()) == null)
  99             strPool = initNamePool();











 100         int off = 0;
 101         if (lookup[cp>>8] == null ||
 102             (off = lookup[cp>>8][cp&0xff]) == 0)
 103             return null;
 104         @SuppressWarnings("deprecation")
 105         String result = new String(strPool, 0, off >>> 8, off & 0xff);  // ASCII
 106         return result;
 107     }




























 108 }
   1 /*
   2  * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang;
  27 
  28 import java.io.DataInputStream;
  29 import java.io.InputStream;
  30 import java.lang.ref.SoftReference;
  31 import java.util.Arrays;
  32 import java.util.Locale;
  33 import java.util.zip.InflaterInputStream;
  34 import java.security.AccessController;
  35 import java.security.PrivilegedAction;
  36 
  37 class CharacterName {
  38 
  39     private static SoftReference<CharacterName> refCharName;

  40 
  41     // codepoint -> bkIndex -> lookup -> offset/len    
  42     private final byte[] strPool;
  43     private final int[] lookup;      // code point -> offset/len in strPool
  44     private final int[] bkIndices;   // code point -> lookup index
  45 
  46     // name -> hash -> hsIndices -> cpEntries -> code point
  47     private final int[] cpEntries;   // code points that have name in strPool
  48     private final int[] hsIndices;   // chain heads, hash indices into "cps"
  49 
  50     private CharacterName()  {
  51         try (DataInputStream dis = new DataInputStream(new InflaterInputStream(
  52             AccessController.doPrivileged(new PrivilegedAction<>() {
  53                 public InputStream run() {
  54                     return getClass().getResourceAsStream("uniName.dat");
  55                 }
  56             })))) {
  57 

  58             int total = dis.readInt();
  59             int bkNum = dis.readInt();
  60             int cpNum = dis.readInt();
  61             int cpEnd = dis.readInt();
  62             byte ba[] = new byte[cpEnd];
  63             lookup = new int[bkNum * 256];
  64             bkIndices = new int[(Character.MAX_CODE_POINT + 1) >> 8];
  65             strPool = new byte[total - cpEnd];
  66             cpEntries = new int[cpNum * 3];
  67             hsIndices = new int[(cpNum / 2) | 1];
  68             Arrays.fill(bkIndices, -1);
  69             Arrays.fill(hsIndices, -1);
  70             dis.readFully(ba);
  71             dis.readFully(strPool);
  72 
  73             int nameOff = 0;
  74             int cpOff = 0;
  75             int cp = 0;
  76             int bk = -1;
  77             int prevBk = -1;   // prev bkNo;
  78             int idx = 0;
  79             int next = -1;
  80             int hash = 0;
  81             int hsh = 0;
  82             do {
  83                 int len = ba[cpOff++] & 0xff;
  84                 if (len == 0) {
  85                     len = ba[cpOff++] & 0xff;
  86                     // always big-endian
  87                     cp = ((ba[cpOff++] & 0xff) << 16) |
  88                          ((ba[cpOff++] & 0xff) <<  8) |
  89                          ((ba[cpOff++] & 0xff));
  90                 }  else {
  91                     cp++;
  92                 }
  93                 // cp -> name
  94                 int hi = cp >> 8;
  95                 if (prevBk != hi) {
  96                     bk++;
  97                     bkIndices[hi] = bk;
  98                     prevBk = hi;
  99                 }
 100                 lookup[(bk << 8) + (cp & 0xff)] = (nameOff << 8) | len;
 101                 // name -> cp
 102                 hash = hashN(strPool, nameOff, len);
 103                 hsh = (hash & 0x7fffffff) % hsIndices.length;
 104                 next = hsIndices[hsh];
 105                 hsIndices[hsh] = idx;
 106                 idx = addCp(idx, hash, next, cp);
 107                 nameOff += len;
 108             } while (cpOff < cpEnd);



 109         } catch (Exception x) {
 110             throw new InternalError(x.getMessage(), x);
 111         }
 112     }
 113 
 114     private static final int hashN(byte[] a, int off, int len) {
 115         int h = 1;
 116         while (len-- > 0) {
 117             h = 31 * h + a[off++];
 118         }
 119         return h;
 120     }
 121 
 122     private int addCp(int idx, int hash, int next, int cp) {
 123         cpEntries[idx++] = hash;
 124         cpEntries[idx++] = next;
 125         cpEntries[idx++] = cp;
 126         return idx;
 127     }
 128 
 129     private int getCpHash(int idx) { return cpEntries[idx]; }
 130     private int getCpNext(int idx) { return cpEntries[idx + 1]; }
 131     private int getCp(int idx)  { return cpEntries[idx + 2]; }
 132 
 133     public static CharacterName getInstance() {
 134         SoftReference<CharacterName> ref = refCharName;
 135         CharacterName cname = null;
 136         if (ref == null || (cname = ref.get()) == null) {
 137             cname = new CharacterName();
 138             refCharName = new SoftReference<>(cname);
 139         }
 140         return cname;
 141     }
 142 
 143     public String getName(int cp) {
 144         int off = 0;
 145         int bk = bkIndices[cp >> 8];
 146         if (bk == -1 || (off = lookup[(bk << 8) + (cp & 0xff)]) == 0)
 147             return null;
 148         @SuppressWarnings("deprecation")
 149         String result = new String(strPool, 0, off >>> 8, off & 0xff);  // ASCII
 150         return result;
 151     }
 152 
 153     public int getCodePoint(String name) {
 154         byte[] bname = name.getBytes(java.nio.charset.StandardCharsets.ISO_8859_1);
 155         int hsh = hashN(bname, 0, bname.length);
 156         int idx = hsIndices[(hsh & 0x7fffffff) % hsIndices.length];
 157         while (idx != -1) {
 158             if (getCpHash(idx) == hsh) {
 159                 int cp = getCp(idx);
 160                 int off = -1;
 161                 int bk = bkIndices[cp >> 8];
 162                 if (bk != -1 && (off = lookup[(bk << 8) + (cp & 0xff)]) != 0) {
 163                     int len = off & 0xff;
 164                     off = off >>> 8;
 165                     if (bname.length == len) {
 166                         int i = 0;
 167                         while (i < len && bname[i] == strPool[off++]) {
 168                             i++;
 169                         }
 170                         if (i == len) {
 171                             return cp;
 172                         }
 173                     }
 174                  }
 175             }
 176             idx = getCpNext(idx);
 177         }
 178         return -1;
 179     }
 180 }