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