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