]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/impl/UBiDiProps.java
icu4jsrc
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / impl / UBiDiProps.java
1 /*\r
2 *******************************************************************************\r
3 *\r
4 *   Copyright (C) 2004-2007, International Business Machines\r
5 *   Corporation and others.  All Rights Reserved.\r
6 *\r
7 *******************************************************************************\r
8 *   file name:  UBiDiProps.java\r
9 *   encoding:   US-ASCII\r
10 *   tab size:   8 (not used)\r
11 *   indentation:4\r
12 *\r
13 *   created on: 2005jan16\r
14 *   created by: Markus W. Scherer\r
15 *\r
16 *   Low-level Unicode bidi/shaping properties access.\r
17 *   Java port of ubidi_props.h/.c.\r
18 */\r
19 \r
20 package com.ibm.icu.impl;\r
21 \r
22 import java.io.InputStream;\r
23 import java.io.DataInputStream;\r
24 import java.io.BufferedInputStream;\r
25 import java.io.IOException;\r
26 \r
27 import com.ibm.icu.util.RangeValueIterator;\r
28 \r
29 import com.ibm.icu.text.UnicodeSet;\r
30 \r
31 import com.ibm.icu.lang.UCharacter;\r
32 import com.ibm.icu.lang.UProperty;\r
33 \r
34 public final class UBiDiProps {\r
35     // constructors etc. --------------------------------------------------- ***\r
36 \r
37     // port of ubidi_openProps()\r
38     public UBiDiProps() throws IOException{\r
39         InputStream is=ICUData.getStream(ICUResourceBundle.ICU_BUNDLE+"/"+DATA_FILE_NAME);\r
40         BufferedInputStream b=new BufferedInputStream(is, 4096 /* data buffer size */);\r
41         readData(b);\r
42         b.close();\r
43         is.close();\r
44 \r
45     }\r
46 \r
47     private void readData(InputStream is) throws IOException {\r
48         DataInputStream inputStream=new DataInputStream(is);\r
49 \r
50         // read the header\r
51         ICUBinary.readHeader(inputStream, FMT, new IsAcceptable());\r
52 \r
53         // read indexes[]\r
54         int i, count;\r
55         count=inputStream.readInt();\r
56         if(count<IX_INDEX_TOP) {\r
57             throw new IOException("indexes[0] too small in "+DATA_FILE_NAME);\r
58         }\r
59         indexes=new int[count];\r
60 \r
61         indexes[0]=count;\r
62         for(i=1; i<count; ++i) {\r
63             indexes[i]=inputStream.readInt();\r
64         }\r
65 \r
66         // read the trie\r
67         trie=new CharTrie(inputStream, null);\r
68 \r
69         // read mirrors[]\r
70         count=indexes[IX_MIRROR_LENGTH];\r
71         if(count>0) {\r
72             mirrors=new int[count];\r
73             for(i=0; i<count; ++i) {\r
74                 mirrors[i]=inputStream.readInt();\r
75             }\r
76         }\r
77 \r
78         // read jgArray[]\r
79         count=indexes[IX_JG_LIMIT]-indexes[IX_JG_START];\r
80         jgArray=new byte[count];\r
81         for(i=0; i<count; ++i) {\r
82             jgArray[i]=inputStream.readByte();\r
83         }\r
84     }\r
85 \r
86     // implement ICUBinary.Authenticate\r
87     private final class IsAcceptable implements ICUBinary.Authenticate {\r
88         public boolean isDataVersionAcceptable(byte version[]) {\r
89             return version[0]==1 &&\r
90                    version[2]==Trie.INDEX_STAGE_1_SHIFT_ && version[3]==Trie.INDEX_STAGE_2_SHIFT_;\r
91         }\r
92     }\r
93 \r
94     // UBiDiProps singleton\r
95     private static UBiDiProps gBdp=null;\r
96 \r
97     // port of ubidi_getSingleton()\r
98     public static final synchronized UBiDiProps getSingleton() throws IOException {\r
99         if(gBdp==null) {\r
100             gBdp=new UBiDiProps();\r
101         }\r
102         return gBdp;\r
103     }\r
104 \r
105     // UBiDiProps dummy singleton\r
106     private static UBiDiProps gBdpDummy=null;\r
107 \r
108     private UBiDiProps(boolean makeDummy) { // ignore makeDummy, only creates a unique signature\r
109         indexes=new int[IX_TOP];\r
110         indexes[0]=IX_TOP;\r
111         trie=new CharTrie(0, 0, null); // dummy trie, always returns 0\r
112     }\r
113 \r
114     /**\r
115      * Get a singleton dummy object, one that works with no real data.\r
116      * This can be used when the real data is not available.\r
117      * Using the dummy can reduce checks for available data after an initial failure.\r
118      * Port of ucase_getDummy().\r
119      */\r
120     public static final synchronized UBiDiProps getDummy() {\r
121         if(gBdpDummy==null) {\r
122             gBdpDummy=new UBiDiProps(true);\r
123         }\r
124         return gBdpDummy;\r
125     }\r
126 \r
127     // set of property starts for UnicodeSet ------------------------------- ***\r
128 \r
129     public final void addPropertyStarts(UnicodeSet set) {\r
130         int i, length;\r
131         int c, start, limit;\r
132 \r
133         byte prev, jg;\r
134 \r
135         /* add the start code point of each same-value range of the trie */\r
136         TrieIterator iter=new TrieIterator(trie);\r
137         RangeValueIterator.Element element=new RangeValueIterator.Element();\r
138 \r
139         while(iter.next(element)){\r
140             set.add(element.start);\r
141         }\r
142 \r
143         /* add the code points from the bidi mirroring table */\r
144         length=indexes[IX_MIRROR_LENGTH];\r
145         for(i=0; i<length; ++i) {\r
146             c=getMirrorCodePoint(mirrors[i]);\r
147             set.add(c, c+1);\r
148         }\r
149 \r
150         /* add the code points from the Joining_Group array where the value changes */\r
151         start=indexes[IX_JG_START];\r
152         limit=indexes[IX_JG_LIMIT];\r
153         length=limit-start;\r
154         prev=0;\r
155         for(i=0; i<length; ++i) {\r
156             jg=jgArray[i];\r
157             if(jg!=prev) {\r
158                 set.add(start);\r
159                 prev=jg;\r
160             }\r
161             ++start;\r
162         }\r
163         if(prev!=0) {\r
164             /* add the limit code point if the last value was not 0 (it is now start==limit) */\r
165             set.add(limit);\r
166         }\r
167 \r
168         /* add code points with hardcoded properties, plus the ones following them */\r
169 \r
170         /* (none right now) */\r
171     }\r
172 \r
173     // property access functions ------------------------------------------- ***\r
174 \r
175     public final int getMaxValue(int which) {\r
176         int max;\r
177 \r
178         max=indexes[IX_MAX_VALUES];\r
179         switch(which) {\r
180         case UProperty.BIDI_CLASS:\r
181             return (max&CLASS_MASK);\r
182         case UProperty.JOINING_GROUP:\r
183             return (max&MAX_JG_MASK)>>MAX_JG_SHIFT;\r
184         case UProperty.JOINING_TYPE:\r
185             return (max&JT_MASK)>>JT_SHIFT;\r
186         default:\r
187             return -1; /* undefined */\r
188         }\r
189     }\r
190 \r
191     public final int getClass(int c) {\r
192         return getClassFromProps(trie.getCodePointValue(c));\r
193     }\r
194 \r
195     public final boolean isMirrored(int c) {\r
196         return getFlagFromProps(trie.getCodePointValue(c), IS_MIRRORED_SHIFT);\r
197     }\r
198 \r
199     public final int getMirror(int c) {\r
200         int props;\r
201         int delta;\r
202 \r
203         props=trie.getCodePointValue(c);\r
204         delta=((short)props)>>MIRROR_DELTA_SHIFT;\r
205         if(delta!=ESC_MIRROR_DELTA) {\r
206             return c+delta;\r
207         } else {\r
208             /* look for mirror code point in the mirrors[] table */\r
209             int m;\r
210             int i, length;\r
211             int c2;\r
212 \r
213             length=indexes[IX_MIRROR_LENGTH];\r
214 \r
215             /* linear search */\r
216             for(i=0; i<length; ++i) {\r
217                 m=mirrors[i];\r
218                 c2=getMirrorCodePoint(m);\r
219                 if(c==c2) {\r
220                     /* found c, return its mirror code point using the index in m */\r
221                     return getMirrorCodePoint(mirrors[getMirrorIndex(m)]);\r
222                 } else if(c<c2) {\r
223                     break;\r
224                 }\r
225             }\r
226 \r
227             /* c not found, return it itself */\r
228             return c;\r
229         }\r
230     }\r
231 \r
232     public final boolean isBidiControl(int c) {\r
233         return getFlagFromProps(trie.getCodePointValue(c), BIDI_CONTROL_SHIFT);\r
234     }\r
235 \r
236     public final boolean isJoinControl(int c) {\r
237         return getFlagFromProps(trie.getCodePointValue(c), JOIN_CONTROL_SHIFT);\r
238     }\r
239 \r
240     public final int getJoiningType(int c) {\r
241         return (trie.getCodePointValue(c)&JT_MASK)>>JT_SHIFT;\r
242     }\r
243 \r
244     public final int getJoiningGroup(int c) {\r
245         int start, limit;\r
246 \r
247         start=indexes[IX_JG_START];\r
248         limit=indexes[IX_JG_LIMIT];\r
249         if(start<=c && c<limit) {\r
250             return (int)jgArray[c-start]&0xff;\r
251         } else {\r
252             return UCharacter.JoiningGroup.NO_JOINING_GROUP;\r
253         }\r
254     }\r
255 \r
256     // data members -------------------------------------------------------- ***\r
257     private int indexes[];\r
258     private int mirrors[];\r
259     private byte jgArray[];\r
260 \r
261     private CharTrie trie;\r
262 \r
263     // data format constants ----------------------------------------------- ***\r
264     private static final String DATA_NAME="ubidi";\r
265     private static final String DATA_TYPE="icu";\r
266     private static final String DATA_FILE_NAME=DATA_NAME+"."+DATA_TYPE;\r
267 \r
268     /* format "BiDi" */\r
269     private static final byte FMT[]={ 0x42, 0x69, 0x44, 0x69 };\r
270 \r
271     /* indexes into indexes[] */\r
272     private static final int IX_INDEX_TOP=0;\r
273     //private static final int IX_LENGTH=1;\r
274     //private static final int IX_TRIE_SIZE=2;\r
275     private static final int IX_MIRROR_LENGTH=3;\r
276 \r
277     private static final int IX_JG_START=4;\r
278     private static final int IX_JG_LIMIT=5;\r
279 \r
280     private static final int IX_MAX_VALUES=15;\r
281     private static final int IX_TOP=16;\r
282 \r
283     // definitions for 16-bit bidi/shaping properties word ----------------- ***\r
284 \r
285                           /* CLASS_SHIFT=0, */     /* bidi class: 5 bits (4..0) */\r
286     private static final int JT_SHIFT=5;           /* joining type: 3 bits (7..5) */\r
287 \r
288     /* private static final int _SHIFT=8, reserved: 2 bits (9..8) */\r
289 \r
290     private static final int JOIN_CONTROL_SHIFT=10;\r
291     private static final int BIDI_CONTROL_SHIFT=11;\r
292 \r
293     private static final int IS_MIRRORED_SHIFT=12;         /* 'is mirrored' */\r
294     private static final int MIRROR_DELTA_SHIFT=13;        /* bidi mirroring delta: 3 bits (15..13) */\r
295 \r
296     private static final int MAX_JG_SHIFT=16;              /* max JG value in indexes[MAX_VALUES_INDEX] bits 23..16 */\r
297 \r
298     private static final int CLASS_MASK=    0x0000001f;\r
299     private static final int JT_MASK=       0x000000e0;\r
300 \r
301     private static final int MAX_JG_MASK=   0x00ff0000;\r
302 \r
303     private static final int getClassFromProps(int props) {\r
304         return props&CLASS_MASK;\r
305     }\r
306     private static final boolean getFlagFromProps(int props, int shift) {\r
307         return ((props>>shift)&1)!=0;\r
308     }\r
309 \r
310     private static final int ESC_MIRROR_DELTA=-4;\r
311     //private static final int MIN_MIRROR_DELTA=-3;\r
312     //private static final int MAX_MIRROR_DELTA=3;\r
313 \r
314     // definitions for 32-bit mirror table entry --------------------------- ***\r
315 \r
316     /* the source Unicode code point takes 21 bits (20..0) */\r
317     private static final int MIRROR_INDEX_SHIFT=21;\r
318     //private static final int MAX_MIRROR_INDEX=0x7ff;\r
319 \r
320     private static final int getMirrorCodePoint(int m) {\r
321         return m&0x1fffff;\r
322     }\r
323     private static final int getMirrorIndex(int m) {\r
324         return m>>>MIRROR_INDEX_SHIFT;\r
325     }\r
326 }\r