2 *******************************************************************************
4 * Copyright (C) 2004-2010, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * file name: UBiDiProps.java
10 * tab size: 8 (not used)
13 * created on: 2005jan16
14 * created by: Markus W. Scherer
16 * Low-level Unicode bidi/shaping properties access.
17 * Java port of ubidi_props.h/.c.
20 package com.ibm.icu.impl;
22 import java.io.BufferedInputStream;
23 import java.io.DataInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.util.Iterator;
28 import com.ibm.icu.lang.UCharacter;
29 import com.ibm.icu.lang.UProperty;
30 import com.ibm.icu.text.UnicodeSet;
32 public final class UBiDiProps {
33 // constructors etc. --------------------------------------------------- ***
35 // port of ubidi_openProps()
36 private UBiDiProps() throws IOException{
37 InputStream is=ICUData.getStream(ICUResourceBundle.ICU_BUNDLE+"/"+DATA_FILE_NAME);
38 BufferedInputStream b=new BufferedInputStream(is, 4096 /* data buffer size */);
44 private void readData(InputStream is) throws IOException {
45 DataInputStream inputStream=new DataInputStream(is);
48 ICUBinary.readHeader(inputStream, FMT, new IsAcceptable());
52 count=inputStream.readInt();
54 throw new IOException("indexes[0] too small in "+DATA_FILE_NAME);
56 indexes=new int[count];
59 for(i=1; i<count; ++i) {
60 indexes[i]=inputStream.readInt();
64 trie=Trie2_16.createFromSerialized(inputStream);
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");
70 // skip padding after trie bytes
71 inputStream.skipBytes(expectedTrieLength-trieLength);
74 count=indexes[IX_MIRROR_LENGTH];
76 mirrors=new int[count];
77 for(i=0; i<count; ++i) {
78 mirrors[i]=inputStream.readInt();
83 count=indexes[IX_JG_LIMIT]-indexes[IX_JG_START];
84 jgArray=new byte[count];
85 for(i=0; i<count; ++i) {
86 jgArray[i]=inputStream.readByte();
90 // implement ICUBinary.Authenticate
91 private final class IsAcceptable implements ICUBinary.Authenticate {
92 public boolean isDataVersionAcceptable(byte version[]) {
97 // set of property starts for UnicodeSet ------------------------------- ***
99 public final void addPropertyStarts(UnicodeSet set) {
105 /* add the start code point of each same-value range of the trie */
106 Iterator<Trie2.Range> trieIterator=trie.iterator();
108 while(trieIterator.hasNext() && !(range=trieIterator.next()).leadSurrogate) {
109 set.add(range.startCodePoint);
112 /* add the code points from the bidi mirroring table */
113 length=indexes[IX_MIRROR_LENGTH];
114 for(i=0; i<length; ++i) {
115 c=getMirrorCodePoint(mirrors[i]);
119 /* add the code points from the Joining_Group array where the value changes */
120 start=indexes[IX_JG_START];
121 limit=indexes[IX_JG_LIMIT];
124 for(i=0; i<length; ++i) {
133 /* add the limit code point if the last value was not 0 (it is now start==limit) */
137 /* add code points with hardcoded properties, plus the ones following them */
139 /* (none right now) */
142 // property access functions ------------------------------------------- ***
144 public final int getMaxValue(int which) {
147 max=indexes[IX_MAX_VALUES];
149 case UProperty.BIDI_CLASS:
150 return (max&CLASS_MASK);
151 case UProperty.JOINING_GROUP:
152 return (max&MAX_JG_MASK)>>MAX_JG_SHIFT;
153 case UProperty.JOINING_TYPE:
154 return (max&JT_MASK)>>JT_SHIFT;
156 return -1; /* undefined */
160 public final int getClass(int c) {
161 return getClassFromProps(trie.get(c));
164 public final boolean isMirrored(int c) {
165 return getFlagFromProps(trie.get(c), IS_MIRRORED_SHIFT);
168 public final int getMirror(int c) {
173 delta=((short)props)>>MIRROR_DELTA_SHIFT;
174 if(delta!=ESC_MIRROR_DELTA) {
177 /* look for mirror code point in the mirrors[] table */
182 length=indexes[IX_MIRROR_LENGTH];
185 for(i=0; i<length; ++i) {
187 c2=getMirrorCodePoint(m);
189 /* found c, return its mirror code point using the index in m */
190 return getMirrorCodePoint(mirrors[getMirrorIndex(m)]);
196 /* c not found, return it itself */
201 public final boolean isBidiControl(int c) {
202 return getFlagFromProps(trie.get(c), BIDI_CONTROL_SHIFT);
205 public final boolean isJoinControl(int c) {
206 return getFlagFromProps(trie.get(c), JOIN_CONTROL_SHIFT);
209 public final int getJoiningType(int c) {
210 return (trie.get(c)&JT_MASK)>>JT_SHIFT;
213 public final int getJoiningGroup(int c) {
216 start=indexes[IX_JG_START];
217 limit=indexes[IX_JG_LIMIT];
218 if(start<=c && c<limit) {
219 return (int)jgArray[c-start]&0xff;
221 return UCharacter.JoiningGroup.NO_JOINING_GROUP;
225 // data members -------------------------------------------------------- ***
226 private int indexes[];
227 private int mirrors[];
228 private byte jgArray[];
230 private Trie2_16 trie;
232 // data format constants ----------------------------------------------- ***
233 private static final String DATA_NAME="ubidi";
234 private static final String DATA_TYPE="icu";
235 private static final String DATA_FILE_NAME=DATA_NAME+"."+DATA_TYPE;
238 private static final byte FMT[]={ 0x42, 0x69, 0x44, 0x69 };
240 /* indexes into indexes[] */
241 //private static final int IX_INDEX_TOP=0;
242 //private static final int IX_LENGTH=1;
243 private static final int IX_TRIE_SIZE=2;
244 private static final int IX_MIRROR_LENGTH=3;
246 private static final int IX_JG_START=4;
247 private static final int IX_JG_LIMIT=5;
249 private static final int IX_MAX_VALUES=15;
250 private static final int IX_TOP=16;
252 // definitions for 16-bit bidi/shaping properties word ----------------- ***
254 /* CLASS_SHIFT=0, */ /* bidi class: 5 bits (4..0) */
255 private static final int JT_SHIFT=5; /* joining type: 3 bits (7..5) */
257 /* private static final int _SHIFT=8, reserved: 2 bits (9..8) */
259 private static final int JOIN_CONTROL_SHIFT=10;
260 private static final int BIDI_CONTROL_SHIFT=11;
262 private static final int IS_MIRRORED_SHIFT=12; /* 'is mirrored' */
263 private static final int MIRROR_DELTA_SHIFT=13; /* bidi mirroring delta: 3 bits (15..13) */
265 private static final int MAX_JG_SHIFT=16; /* max JG value in indexes[MAX_VALUES_INDEX] bits 23..16 */
267 private static final int CLASS_MASK= 0x0000001f;
268 private static final int JT_MASK= 0x000000e0;
270 private static final int MAX_JG_MASK= 0x00ff0000;
272 private static final int getClassFromProps(int props) {
273 return props&CLASS_MASK;
275 private static final boolean getFlagFromProps(int props, int shift) {
276 return ((props>>shift)&1)!=0;
279 private static final int ESC_MIRROR_DELTA=-4;
280 //private static final int MIN_MIRROR_DELTA=-3;
281 //private static final int MAX_MIRROR_DELTA=3;
283 // definitions for 32-bit mirror table entry --------------------------- ***
285 /* the source Unicode code point takes 21 bits (20..0) */
286 private static final int MIRROR_INDEX_SHIFT=21;
287 //private static final int MAX_MIRROR_INDEX=0x7ff;
289 private static final int getMirrorCodePoint(int m) {
292 private static final int getMirrorIndex(int m) {
293 return m>>>MIRROR_INDEX_SHIFT;
298 * public singleton instance
300 public static final UBiDiProps INSTANCE;
302 // This static initializer block must be placed after
303 // other static member initialization
306 INSTANCE = new UBiDiProps();
307 } catch (IOException e) {
308 throw new RuntimeException(e);