]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_8_1_1/main/classes/core/src/com/ibm/icu/impl/UBiDiProps.java
Added flags.
[Dictionary.git] / jars / icu4j-4_8_1_1 / main / classes / core / src / com / ibm / icu / impl / UBiDiProps.java
1 /*
2 *******************************************************************************
3 *
4 *   Copyright (C) 2004-2010, International Business Machines
5 *   Corporation and others.  All Rights Reserved.
6 *
7 *******************************************************************************
8 *   file name:  UBiDiProps.java
9 *   encoding:   US-ASCII
10 *   tab size:   8 (not used)
11 *   indentation:4
12 *
13 *   created on: 2005jan16
14 *   created by: Markus W. Scherer
15 *
16 *   Low-level Unicode bidi/shaping properties access.
17 *   Java port of ubidi_props.h/.c.
18 */
19
20 package com.ibm.icu.impl;
21
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;
27
28 import com.ibm.icu.lang.UCharacter;
29 import com.ibm.icu.lang.UProperty;
30 import com.ibm.icu.text.UnicodeSet;
31
32 public final class UBiDiProps {
33     // constructors etc. --------------------------------------------------- ***
34
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 */);
39         readData(b);
40         b.close();
41         is.close();
42     }
43
44     private void readData(InputStream is) throws IOException {
45         DataInputStream inputStream=new DataInputStream(is);
46
47         // read the header
48         ICUBinary.readHeader(inputStream, FMT, new IsAcceptable());
49
50         // read indexes[]
51         int i, count;
52         count=inputStream.readInt();
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]=inputStream.readInt();
61         }
62
63         // read the trie
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");
69         }
70         // skip padding after trie bytes
71         inputStream.skipBytes(expectedTrieLength-trieLength);
72
73         // read mirrors[]
74         count=indexes[IX_MIRROR_LENGTH];
75         if(count>0) {
76             mirrors=new int[count];
77             for(i=0; i<count; ++i) {
78                 mirrors[i]=inputStream.readInt();
79             }
80         }
81
82         // read jgArray[]
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();
87         }
88     }
89
90     // implement ICUBinary.Authenticate
91     private final class IsAcceptable implements ICUBinary.Authenticate {
92         public boolean isDataVersionAcceptable(byte version[]) {
93             return version[0]==2;
94         }
95     }
96
97     // set of property starts for UnicodeSet ------------------------------- ***
98
99     public final void addPropertyStarts(UnicodeSet set) {
100         int i, length;
101         int c, start, limit;
102
103         byte prev, jg;
104
105         /* add the start code point of each same-value range of the trie */
106         Iterator<Trie2.Range> trieIterator=trie.iterator();
107         Trie2.Range range;
108         while(trieIterator.hasNext() && !(range=trieIterator.next()).leadSurrogate) {
109             set.add(range.startCodePoint);
110         }
111
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]);
116             set.add(c, c+1);
117         }
118
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];
122         length=limit-start;
123         prev=0;
124         for(i=0; i<length; ++i) {
125             jg=jgArray[i];
126             if(jg!=prev) {
127                 set.add(start);
128                 prev=jg;
129             }
130             ++start;
131         }
132         if(prev!=0) {
133             /* add the limit code point if the last value was not 0 (it is now start==limit) */
134             set.add(limit);
135         }
136
137         /* add code points with hardcoded properties, plus the ones following them */
138
139         /* (none right now) */
140     }
141
142     // property access functions ------------------------------------------- ***
143
144     public final int getMaxValue(int which) {
145         int max;
146
147         max=indexes[IX_MAX_VALUES];
148         switch(which) {
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;
155         default:
156             return -1; /* undefined */
157         }
158     }
159
160     public final int getClass(int c) {
161         return getClassFromProps(trie.get(c));
162     }
163
164     public final boolean isMirrored(int c) {
165         return getFlagFromProps(trie.get(c), IS_MIRRORED_SHIFT);
166     }
167
168     public final int getMirror(int c) {
169         int props;
170         int delta;
171
172         props=trie.get(c);
173         delta=((short)props)>>MIRROR_DELTA_SHIFT;
174         if(delta!=ESC_MIRROR_DELTA) {
175             return c+delta;
176         } else {
177             /* look for mirror code point in the mirrors[] table */
178             int m;
179             int i, length;
180             int c2;
181
182             length=indexes[IX_MIRROR_LENGTH];
183
184             /* linear search */
185             for(i=0; i<length; ++i) {
186                 m=mirrors[i];
187                 c2=getMirrorCodePoint(m);
188                 if(c==c2) {
189                     /* found c, return its mirror code point using the index in m */
190                     return getMirrorCodePoint(mirrors[getMirrorIndex(m)]);
191                 } else if(c<c2) {
192                     break;
193                 }
194             }
195
196             /* c not found, return it itself */
197             return c;
198         }
199     }
200
201     public final boolean isBidiControl(int c) {
202         return getFlagFromProps(trie.get(c), BIDI_CONTROL_SHIFT);
203     }
204
205     public final boolean isJoinControl(int c) {
206         return getFlagFromProps(trie.get(c), JOIN_CONTROL_SHIFT);
207     }
208
209     public final int getJoiningType(int c) {
210         return (trie.get(c)&JT_MASK)>>JT_SHIFT;
211     }
212
213     public final int getJoiningGroup(int c) {
214         int start, limit;
215
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;
220         } else {
221             return UCharacter.JoiningGroup.NO_JOINING_GROUP;
222         }
223     }
224
225     // data members -------------------------------------------------------- ***
226     private int indexes[];
227     private int mirrors[];
228     private byte jgArray[];
229
230     private Trie2_16 trie;
231
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;
236
237     /* format "BiDi" */
238     private static final byte FMT[]={ 0x42, 0x69, 0x44, 0x69 };
239
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;
245
246     private static final int IX_JG_START=4;
247     private static final int IX_JG_LIMIT=5;
248
249     private static final int IX_MAX_VALUES=15;
250     private static final int IX_TOP=16;
251
252     // definitions for 16-bit bidi/shaping properties word ----------------- ***
253
254                           /* CLASS_SHIFT=0, */     /* bidi class: 5 bits (4..0) */
255     private static final int JT_SHIFT=5;           /* joining type: 3 bits (7..5) */
256
257     /* private static final int _SHIFT=8, reserved: 2 bits (9..8) */
258
259     private static final int JOIN_CONTROL_SHIFT=10;
260     private static final int BIDI_CONTROL_SHIFT=11;
261
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) */
264
265     private static final int MAX_JG_SHIFT=16;              /* max JG value in indexes[MAX_VALUES_INDEX] bits 23..16 */
266
267     private static final int CLASS_MASK=    0x0000001f;
268     private static final int JT_MASK=       0x000000e0;
269
270     private static final int MAX_JG_MASK=   0x00ff0000;
271
272     private static final int getClassFromProps(int props) {
273         return props&CLASS_MASK;
274     }
275     private static final boolean getFlagFromProps(int props, int shift) {
276         return ((props>>shift)&1)!=0;
277     }
278
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;
282
283     // definitions for 32-bit mirror table entry --------------------------- ***
284
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;
288
289     private static final int getMirrorCodePoint(int m) {
290         return m&0x1fffff;
291     }
292     private static final int getMirrorIndex(int m) {
293         return m>>>MIRROR_INDEX_SHIFT;
294     }
295
296
297     /*
298      * public singleton instance
299      */
300     public static final UBiDiProps INSTANCE;
301
302     // This static initializer block must be placed after
303     // other static member initialization
304     static {
305         try {
306             INSTANCE = new UBiDiProps();
307         } catch (IOException e) {
308             throw new RuntimeException(e);
309         }
310     }
311 }