1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // © 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 /* 5 ******************************************************************************* 6 * 7 * Copyright (C) 2004-2015, International Business Machines 8 * Corporation and others. All Rights Reserved. 9 * 10 ******************************************************************************* 11 * file name: UBiDiProps.java 12 * encoding: US-ASCII 13 * tab size: 8 (not used) 14 * indentation:4 15 * 16 * created on: 2005jan16 17 * created by: Markus W. Scherer 18 * 19 * Low-level Unicode bidi/shaping properties access. 20 * Java port of ubidi_props.h/.c. 21 */ 22 23 package android.icu.impl; 24 25 import java.io.IOException; 26 import java.nio.ByteBuffer; 27 import java.util.Iterator; 28 29 import android.icu.lang.UCharacter; 30 import android.icu.lang.UProperty; 31 import android.icu.text.UnicodeSet; 32 import android.icu.util.ICUUncheckedIOException; 33 34 /** 35 * @hide Only a subset of ICU is exposed in Android 36 */ 37 public final class UBiDiProps { 38 // constructors etc. --------------------------------------------------- *** 39 40 // port of ubidi_openProps() UBiDiProps()41 private UBiDiProps() throws IOException{ 42 ByteBuffer bytes=ICUBinary.getData(DATA_FILE_NAME); 43 readData(bytes); 44 } 45 readData(ByteBuffer bytes)46 private void readData(ByteBuffer bytes) throws IOException { 47 // read the header 48 ICUBinary.readHeader(bytes, FMT, new IsAcceptable()); 49 50 // read indexes[] 51 int i, count; 52 count=bytes.getInt(); 53 if(count<IX_TOP) { 54 throw new IOException("indexes[0] too small in "+DATA_FILE_NAME); 55 } 56 indexes=new int[count]; 57 58 indexes[0]=count; 59 for(i=1; i<count; ++i) { 60 indexes[i]=bytes.getInt(); 61 } 62 63 // read the trie 64 trie=Trie2_16.createFromSerialized(bytes); 65 int expectedTrieLength=indexes[IX_TRIE_SIZE]; 66 int trieLength=trie.getSerializedLength(); 67 if(trieLength>expectedTrieLength) { 68 throw new IOException(DATA_FILE_NAME+": not enough bytes for the trie"); 69 } 70 // skip padding after trie bytes 71 ICUBinary.skipBytes(bytes, expectedTrieLength-trieLength); 72 73 // read mirrors[] 74 count=indexes[IX_MIRROR_LENGTH]; 75 if(count>0) { 76 mirrors=ICUBinary.getInts(bytes, count, 0); 77 } 78 79 // read jgArray[] 80 count=indexes[IX_JG_LIMIT]-indexes[IX_JG_START]; 81 jgArray=new byte[count]; 82 bytes.get(jgArray); 83 84 // read jgArray2[] 85 count=indexes[IX_JG_LIMIT2]-indexes[IX_JG_START2]; 86 jgArray2=new byte[count]; 87 bytes.get(jgArray2); 88 } 89 90 // implement ICUBinary.Authenticate 91 private final static class IsAcceptable implements ICUBinary.Authenticate { 92 @Override isDataVersionAcceptable(byte version[])93 public boolean isDataVersionAcceptable(byte version[]) { 94 return version[0]==2; 95 } 96 } 97 98 // set of property starts for UnicodeSet ------------------------------- *** 99 addPropertyStarts(UnicodeSet set)100 public final void addPropertyStarts(UnicodeSet set) { 101 int i, length; 102 int c, start, limit; 103 104 byte prev, jg; 105 106 /* add the start code point of each same-value range of the trie */ 107 Iterator<Trie2.Range> trieIterator=trie.iterator(); 108 Trie2.Range range; 109 while(trieIterator.hasNext() && !(range=trieIterator.next()).leadSurrogate) { 110 set.add(range.startCodePoint); 111 } 112 113 /* add the code points from the bidi mirroring table */ 114 length=indexes[IX_MIRROR_LENGTH]; 115 for(i=0; i<length; ++i) { 116 c=getMirrorCodePoint(mirrors[i]); 117 set.add(c, c+1); 118 } 119 120 /* add the code points from the Joining_Group array where the value changes */ 121 start=indexes[IX_JG_START]; 122 limit=indexes[IX_JG_LIMIT]; 123 byte[] jga=jgArray; 124 for(;;) { 125 length=limit-start; 126 prev=0; 127 for(i=0; i<length; ++i) { 128 jg=jga[i]; 129 if(jg!=prev) { 130 set.add(start); 131 prev=jg; 132 } 133 ++start; 134 } 135 if(prev!=0) { 136 /* add the limit code point if the last value was not 0 (it is now start==limit) */ 137 set.add(limit); 138 } 139 if(limit==indexes[IX_JG_LIMIT]) { 140 /* switch to the second Joining_Group range */ 141 start=indexes[IX_JG_START2]; 142 limit=indexes[IX_JG_LIMIT2]; 143 jga=jgArray2; 144 } else { 145 break; 146 } 147 } 148 149 /* add code points with hardcoded properties, plus the ones following them */ 150 151 /* (none right now) */ 152 } 153 154 // property access functions ------------------------------------------- *** 155 getMaxValue(int which)156 public final int getMaxValue(int which) { 157 int max; 158 159 max=indexes[IX_MAX_VALUES]; 160 switch(which) { 161 case UProperty.BIDI_CLASS: 162 return (max&CLASS_MASK); 163 case UProperty.JOINING_GROUP: 164 return (max&MAX_JG_MASK)>>MAX_JG_SHIFT; 165 case UProperty.JOINING_TYPE: 166 return (max&JT_MASK)>>JT_SHIFT; 167 case UProperty.BIDI_PAIRED_BRACKET_TYPE: 168 return (max&BPT_MASK)>>BPT_SHIFT; 169 default: 170 return -1; /* undefined */ 171 } 172 } 173 getClass(int c)174 public final int getClass(int c) { 175 return getClassFromProps(trie.get(c)); 176 } 177 isMirrored(int c)178 public final boolean isMirrored(int c) { 179 return getFlagFromProps(trie.get(c), IS_MIRRORED_SHIFT); 180 } 181 getMirror(int c, int props)182 private final int getMirror(int c, int props) { 183 int delta=getMirrorDeltaFromProps(props); 184 if(delta!=ESC_MIRROR_DELTA) { 185 return c+delta; 186 } else { 187 /* look for mirror code point in the mirrors[] table */ 188 int m; 189 int i, length; 190 int c2; 191 192 length=indexes[IX_MIRROR_LENGTH]; 193 194 /* linear search */ 195 for(i=0; i<length; ++i) { 196 m=mirrors[i]; 197 c2=getMirrorCodePoint(m); 198 if(c==c2) { 199 /* found c, return its mirror code point using the index in m */ 200 return getMirrorCodePoint(mirrors[getMirrorIndex(m)]); 201 } else if(c<c2) { 202 break; 203 } 204 } 205 206 /* c not found, return it itself */ 207 return c; 208 } 209 } 210 getMirror(int c)211 public final int getMirror(int c) { 212 int props=trie.get(c); 213 return getMirror(c, props); 214 } 215 isBidiControl(int c)216 public final boolean isBidiControl(int c) { 217 return getFlagFromProps(trie.get(c), BIDI_CONTROL_SHIFT); 218 } 219 isJoinControl(int c)220 public final boolean isJoinControl(int c) { 221 return getFlagFromProps(trie.get(c), JOIN_CONTROL_SHIFT); 222 } 223 getJoiningType(int c)224 public final int getJoiningType(int c) { 225 return (trie.get(c)&JT_MASK)>>JT_SHIFT; 226 } 227 getJoiningGroup(int c)228 public final int getJoiningGroup(int c) { 229 int start, limit; 230 231 start=indexes[IX_JG_START]; 232 limit=indexes[IX_JG_LIMIT]; 233 if(start<=c && c<limit) { 234 return jgArray[c-start]&0xff; 235 } 236 start=indexes[IX_JG_START2]; 237 limit=indexes[IX_JG_LIMIT2]; 238 if(start<=c && c<limit) { 239 return jgArray2[c-start]&0xff; 240 } 241 return UCharacter.JoiningGroup.NO_JOINING_GROUP; 242 } 243 getPairedBracketType(int c)244 public final int getPairedBracketType(int c) { 245 return (trie.get(c)&BPT_MASK)>>BPT_SHIFT; 246 } 247 getPairedBracket(int c)248 public final int getPairedBracket(int c) { 249 int props=trie.get(c); 250 if((props&BPT_MASK)==0) { 251 return c; 252 } else { 253 return getMirror(c, props); 254 } 255 } 256 257 // data members -------------------------------------------------------- *** 258 private int indexes[]; 259 private int mirrors[]; 260 private byte jgArray[]; 261 private byte jgArray2[]; 262 263 private Trie2_16 trie; 264 265 // data format constants ----------------------------------------------- *** 266 private static final String DATA_NAME="ubidi"; 267 private static final String DATA_TYPE="icu"; 268 private static final String DATA_FILE_NAME=DATA_NAME+"."+DATA_TYPE; 269 270 /* format "BiDi" */ 271 private static final int FMT=0x42694469; 272 273 /* indexes into indexes[] */ 274 //private static final int IX_INDEX_TOP=0; 275 //private static final int IX_LENGTH=1; 276 private static final int IX_TRIE_SIZE=2; 277 private static final int IX_MIRROR_LENGTH=3; 278 279 private static final int IX_JG_START=4; 280 private static final int IX_JG_LIMIT=5; 281 private static final int IX_JG_START2=6; /* new in format version 2.2, ICU 54 */ 282 private static final int IX_JG_LIMIT2=7; 283 284 private static final int IX_MAX_VALUES=15; 285 private static final int IX_TOP=16; 286 287 // definitions for 16-bit bidi/shaping properties word ----------------- *** 288 289 /* CLASS_SHIFT=0, */ /* bidi class: 5 bits (4..0) */ 290 private static final int JT_SHIFT=5; /* joining type: 3 bits (7..5) */ 291 292 private static final int BPT_SHIFT=8; /* Bidi_Paired_Bracket_Type(bpt): 2 bits (9..8) */ 293 294 private static final int JOIN_CONTROL_SHIFT=10; 295 private static final int BIDI_CONTROL_SHIFT=11; 296 297 private static final int IS_MIRRORED_SHIFT=12; /* 'is mirrored' */ 298 private static final int MIRROR_DELTA_SHIFT=13; /* bidi mirroring delta: 3 bits (15..13) */ 299 300 private static final int MAX_JG_SHIFT=16; /* max JG value in indexes[MAX_VALUES_INDEX] bits 23..16 */ 301 302 private static final int CLASS_MASK= 0x0000001f; 303 private static final int JT_MASK= 0x000000e0; 304 private static final int BPT_MASK= 0x00000300; 305 306 private static final int MAX_JG_MASK= 0x00ff0000; 307 getClassFromProps(int props)308 private static final int getClassFromProps(int props) { 309 return props&CLASS_MASK; 310 } getFlagFromProps(int props, int shift)311 private static final boolean getFlagFromProps(int props, int shift) { 312 return ((props>>shift)&1)!=0; 313 } getMirrorDeltaFromProps(int props)314 private static final int getMirrorDeltaFromProps(int props) { 315 return (short)props>>MIRROR_DELTA_SHIFT; 316 } 317 318 private static final int ESC_MIRROR_DELTA=-4; 319 //private static final int MIN_MIRROR_DELTA=-3; 320 //private static final int MAX_MIRROR_DELTA=3; 321 322 // definitions for 32-bit mirror table entry --------------------------- *** 323 324 /* the source Unicode code point takes 21 bits (20..0) */ 325 private static final int MIRROR_INDEX_SHIFT=21; 326 //private static final int MAX_MIRROR_INDEX=0x7ff; 327 getMirrorCodePoint(int m)328 private static final int getMirrorCodePoint(int m) { 329 return m&0x1fffff; 330 } getMirrorIndex(int m)331 private static final int getMirrorIndex(int m) { 332 return m>>>MIRROR_INDEX_SHIFT; 333 } 334 335 336 /* 337 * public singleton instance 338 */ 339 public static final UBiDiProps INSTANCE; 340 341 // This static initializer block must be placed after 342 // other static member initialization 343 static { 344 try { 345 INSTANCE = new UBiDiProps(); 346 } catch (IOException e) { 347 throw new ICUUncheckedIOException(e); 348 } 349 } 350 } 351