1 /* 2 * Copyright (c) 2005, 2015, 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 ******************************************************************************* 27 * 28 * Copyright (C) 2004-2014, International Business Machines 29 * Corporation and others. All Rights Reserved. 30 * 31 ******************************************************************************* 32 * file name: UBiDiProps.java 33 * encoding: US-ASCII 34 * tab size: 8 (not used) 35 * indentation:4 36 * 37 * created on: 2005jan16 38 * created by: Markus W. Scherer 39 * 40 * Low-level Unicode bidi/shaping properties access. 41 * Java port of ubidi_props.h/.c. 42 */ 43 44 package sun.text.normalizer; 45 46 import java.io.IOException; 47 import java.nio.ByteBuffer; 48 import java.util.MissingResourceException; 49 50 public final class UBiDiProps { 51 // constructors etc. --------------------------------------------------- *** 52 53 // port of ubidi_openProps() 54 private UBiDiProps() throws IOException{ 55 ByteBuffer bytes=ICUBinary.getRequiredData(DATA_FILE_NAME); 56 readData(bytes); 57 } 58 59 private void readData(ByteBuffer bytes) throws IOException { 60 // read the header 61 ICUBinary.readHeader(bytes, FMT, new IsAcceptable()); 62 63 // read indexes[] 64 int i, count; 65 count=bytes.getInt(); 66 if(count<IX_TOP) { 67 throw new IOException("indexes[0] too small in "+DATA_FILE_NAME); 68 } 69 indexes=new int[count]; 70 71 indexes[0]=count; 72 for(i=1; i<count; ++i) { 73 indexes[i]=bytes.getInt(); 74 } 75 76 // read the trie 77 trie=Trie2_16.createFromSerialized(bytes); 78 int expectedTrieLength=indexes[IX_TRIE_SIZE]; 79 int trieLength=trie.getSerializedLength(); 80 if(trieLength>expectedTrieLength) { 81 throw new IOException(DATA_FILE_NAME+": not enough bytes for the trie"); 82 } 83 // skip padding after trie bytes 84 ICUBinary.skipBytes(bytes, expectedTrieLength-trieLength); 85 86 // read mirrors[] 87 count=indexes[IX_MIRROR_LENGTH]; 88 if(count>0) { 89 mirrors=new int[count]; 90 for(i=0; i<count; ++i) { 91 mirrors[i]=bytes.getInt(); 92 } 93 } 94 95 // read jgArray[] 96 count=indexes[IX_JG_LIMIT]-indexes[IX_JG_START]; 97 jgArray=new byte[count]; 98 for(i=0; i<count; ++i) { 99 jgArray[i]=bytes.get(); 100 } 101 102 // read jgArray2[] 103 count=indexes[IX_JG_LIMIT2]-indexes[IX_JG_START2]; 104 jgArray2=new byte[count]; 105 for(i=0; i<count; ++i) { 106 jgArray2[i]=bytes.get(); 107 } 108 } 109 110 // implement ICUBinary.Authenticate 111 private static final class IsAcceptable implements ICUBinary.Authenticate { 112 public boolean isDataVersionAcceptable(byte[] version) { 113 return version[0]==2; 114 } 115 } 116 117 // property access functions ------------------------------------------- *** 118 119 public final int getClass(int c) { 120 return getClassFromProps(trie.get(c)); 121 } 122 123 private final int getMirror(int c, int props) { 124 int delta=getMirrorDeltaFromProps(props); 125 if(delta!=ESC_MIRROR_DELTA) { 126 return c+delta; 127 } else { 128 /* look for mirror code point in the mirrors[] table */ 129 int m; 130 int i, length; 131 int c2; 132 133 length=indexes[IX_MIRROR_LENGTH]; 134 135 /* linear search */ 136 for(i=0; i<length; ++i) { 137 m=mirrors[i]; 138 c2=getMirrorCodePoint(m); 139 if(c==c2) { 140 /* found c, return its mirror code point using the index in m */ 141 return getMirrorCodePoint(mirrors[getMirrorIndex(m)]); 142 } else if(c<c2) { 143 break; 144 } 145 } 146 147 /* c not found, return it itself */ 148 return c; 149 } 150 } 151 152 public final int getMirror(int c) { 153 int props=trie.get(c); 154 return getMirror(c, props); 155 } 156 157 public final int getJoiningType(int c) { 158 return (trie.get(c)&JT_MASK)>>JT_SHIFT; 159 } 160 161 public final int getJoiningGroup(int c) { 162 int start, limit; 163 164 start=indexes[IX_JG_START]; 165 limit=indexes[IX_JG_LIMIT]; 166 if(start<=c && c<limit) { 167 return (int)jgArray[c-start]&0xff; 168 } 169 start=indexes[IX_JG_START2]; 170 limit=indexes[IX_JG_LIMIT2]; 171 if(start<=c && c<limit) { 172 return (int)jgArray2[c-start]&0xff; 173 } 174 return UCharacter.JoiningGroup.NO_JOINING_GROUP; 175 } 176 177 public final int getPairedBracketType(int c) { 178 return (trie.get(c)&BPT_MASK)>>BPT_SHIFT; 179 } 180 181 public final int getPairedBracket(int c) { 182 int props=trie.get(c); 183 if((props&BPT_MASK)==0) { 184 return c; 185 } else { 186 return getMirror(c, props); 187 } 188 } 189 190 // data members -------------------------------------------------------- *** 191 private int[] indexes; 192 private int[] mirrors; 193 private byte[] jgArray; 194 private byte[] jgArray2; 195 196 private Trie2_16 trie; 197 198 // data format constants ----------------------------------------------- *** 199 private static final String DATA_FILE_NAME = "/sun/text/resources/ubidi.icu"; 200 201 /* format "BiDi" */ 202 private static final int FMT=0x42694469; 203 204 /* indexes into indexes[] */ 205 private static final int IX_TRIE_SIZE=2; 206 private static final int IX_MIRROR_LENGTH=3; 207 208 private static final int IX_JG_START=4; 209 private static final int IX_JG_LIMIT=5; 210 private static final int IX_JG_START2=6; /* new in format version 2.2, ICU 54 */ 211 private static final int IX_JG_LIMIT2=7; 212 213 private static final int IX_TOP=16; 214 215 // definitions for 16-bit bidi/shaping properties word ----------------- *** 216 217 /* CLASS_SHIFT=0, */ /* bidi class: 5 bits (4..0) */ 218 private static final int JT_SHIFT=5; /* joining type: 3 bits (7..5) */ 219 220 private static final int BPT_SHIFT=8; /* Bidi_Paired_Bracket_Type(bpt): 2 bits (9..8) */ 221 222 private static final int MIRROR_DELTA_SHIFT=13; /* bidi mirroring delta: 3 bits (15..13) */ 223 224 private static final int CLASS_MASK= 0x0000001f; 225 private static final int JT_MASK= 0x000000e0; 226 private static final int BPT_MASK= 0x00000300; 227 228 private static final int getClassFromProps(int props) { 229 return props&CLASS_MASK; 230 } 231 private static final boolean getFlagFromProps(int props, int shift) { 232 return ((props>>shift)&1)!=0; 233 } 234 private static final int getMirrorDeltaFromProps(int props) { 235 return (short)props>>MIRROR_DELTA_SHIFT; 236 } 237 238 private static final int ESC_MIRROR_DELTA=-4; 239 240 // definitions for 32-bit mirror table entry --------------------------- *** 241 242 /* the source Unicode code point takes 21 bits (20..0) */ 243 private static final int MIRROR_INDEX_SHIFT=21; 244 245 private static final int getMirrorCodePoint(int m) { 246 return m&0x1fffff; 247 } 248 private static final int getMirrorIndex(int m) { 249 return m>>>MIRROR_INDEX_SHIFT; 250 } 251 252 253 /* 254 * public singleton instance 255 */ 256 public static final UBiDiProps INSTANCE; 257 258 // This static initializer block must be placed after 259 // other static member initialization 260 static { 261 try { 262 INSTANCE = new UBiDiProps(); 263 } catch (IOException e) { 264 throw new MissingResourceException(e.getMessage(),DATA_FILE_NAME,""); 265 } 266 } 267 }