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