1 /*
2  * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 /*
26  *******************************************************************************
27  *
28  *   Copyright (C) 2004-2014, International Business Machines
29  *   Corporation and others.  All Rights Reserved.
30  *
31  *******************************************************************************
32  *   file name:  UBiDiProps.java
33  *   encoding:   US-ASCII
34  *   tab size:   8 (not used)
35  *   indentation:4
36  *
37  *   created on: 2005jan16
38  *   created by: Markus W. Scherer
39  *
40  *   Low-level Unicode bidi/shaping properties access.
41  *   Java port of ubidi_props.h/.c.
42  */
43 
44 package jdk.internal.icu.impl;
45 
46 import jdk.internal.icu.lang.UCharacter;
47 import jdk.internal.icu.util.VersionInfo;
48 
49 import java.io.IOException;
50 import java.nio.ByteBuffer;
51 import java.util.MissingResourceException;
52 
53 public final class UBiDiProps {
54     // constructors etc. --------------------------------------------------- ***
55 
56     // port of ubidi_openProps()
UBiDiProps()57     private UBiDiProps() throws IOException{
58         ByteBuffer bytes=ICUBinary.getRequiredData(DATA_FILE_NAME);
59         readData(bytes);
60     }
61 
readData(ByteBuffer bytes)62     private void readData(ByteBuffer bytes) throws IOException {
63         // read the header
64         ICUBinary.readHeader(bytes, FMT, new IsAcceptable());
65 
66         // read indexes[]
67         int i, count;
68         count=bytes.getInt();
69         if(count<IX_TOP) {
70             throw new IOException("indexes[0] too small in "+DATA_FILE_NAME);
71         }
72         indexes=new int[count];
73 
74         indexes[0]=count;
75         for(i=1; i<count; ++i) {
76             indexes[i]=bytes.getInt();
77         }
78 
79         // read the trie
80         trie=Trie2_16.createFromSerialized(bytes);
81         int expectedTrieLength=indexes[IX_TRIE_SIZE];
82         int trieLength=trie.getSerializedLength();
83         if(trieLength>expectedTrieLength) {
84             throw new IOException(DATA_FILE_NAME+": not enough bytes for the trie");
85         }
86         // skip padding after trie bytes
87         ICUBinary.skipBytes(bytes, expectedTrieLength-trieLength);
88 
89         // read mirrors[]
90         count=indexes[IX_MIRROR_LENGTH];
91         if(count>0) {
92             mirrors=new int[count];
93             for(i=0; i<count; ++i) {
94                 mirrors[i]=bytes.getInt();
95             }
96         }
97 
98         // read jgArray[]
99         count=indexes[IX_JG_LIMIT]-indexes[IX_JG_START];
100         jgArray=new byte[count];
101         for(i=0; i<count; ++i) {
102             jgArray[i]=bytes.get();
103         }
104 
105         // read jgArray2[]
106         count=indexes[IX_JG_LIMIT2]-indexes[IX_JG_START2];
107         jgArray2=new byte[count];
108         for(i=0; i<count; ++i) {
109             jgArray2[i]=bytes.get();
110         }
111     }
112 
113     // implement ICUBinary.Authenticate
114     private static final class IsAcceptable implements ICUBinary.Authenticate {
isDataVersionAcceptable(byte version[])115         public boolean isDataVersionAcceptable(byte version[]) {
116             return version[0]==2;
117         }
118     }
119 
120     // property access functions ------------------------------------------- ***
121 
getClass(int c)122     public final int getClass(int c) {
123         return getClassFromProps(trie.get(c));
124     }
125 
getMirror(int c, int props)126     private final int getMirror(int c, int props) {
127         int delta=getMirrorDeltaFromProps(props);
128         if(delta!=ESC_MIRROR_DELTA) {
129             return c+delta;
130         } else {
131             /* look for mirror code point in the mirrors[] table */
132             int m;
133             int i, length;
134             int c2;
135 
136             length=indexes[IX_MIRROR_LENGTH];
137 
138             /* linear search */
139             for(i=0; i<length; ++i) {
140                 m=mirrors[i];
141                 c2=getMirrorCodePoint(m);
142                 if(c==c2) {
143                     /* found c, return its mirror code point using the index in m */
144                     return getMirrorCodePoint(mirrors[getMirrorIndex(m)]);
145                 } else if(c<c2) {
146                     break;
147                 }
148             }
149 
150             /* c not found, return it itself */
151             return c;
152         }
153     }
154 
getMirror(int c)155     public final int getMirror(int c) {
156         int props=trie.get(c);
157         return getMirror(c, props);
158     }
159 
getJoiningType(int c)160     public final int getJoiningType(int c) {
161         return (trie.get(c)&JT_MASK)>>JT_SHIFT;
162     }
163 
getJoiningGroup(int c)164     public final int getJoiningGroup(int c) {
165         int start, limit;
166 
167         start=indexes[IX_JG_START];
168         limit=indexes[IX_JG_LIMIT];
169         if(start<=c && c<limit) {
170             return (int)jgArray[c-start]&0xff;
171         }
172         start=indexes[IX_JG_START2];
173         limit=indexes[IX_JG_LIMIT2];
174         if(start<=c && c<limit) {
175             return (int)jgArray2[c-start]&0xff;
176         }
177         return UCharacter.JoiningGroup.NO_JOINING_GROUP;
178     }
179 
getPairedBracketType(int c)180     public final int getPairedBracketType(int c) {
181         return (trie.get(c)&BPT_MASK)>>BPT_SHIFT;
182     }
183 
getPairedBracket(int c)184     public final int getPairedBracket(int c) {
185         int props=trie.get(c);
186         if((props&BPT_MASK)==0) {
187             return c;
188         } else {
189             return getMirror(c, props);
190         }
191     }
192 
193     // data members -------------------------------------------------------- ***
194     private int indexes[];
195     private int mirrors[];
196     private byte jgArray[];
197     private byte jgArray2[];
198 
199     private Trie2_16 trie;
200 
201     // data format constants ----------------------------------------------- ***
202     @SuppressWarnings("deprecation")
203     private static final String DATA_FILE_NAME =
204             "/jdk/internal/icu/impl/data/icudt" +
205             VersionInfo.ICU_DATA_VERSION_PATH +
206             "/ubidi.icu";
207 
208     /* format "BiDi" */
209     private static final int FMT=0x42694469;
210 
211     /* indexes into indexes[] */
212     private static final int IX_TRIE_SIZE=2;
213     private static final int IX_MIRROR_LENGTH=3;
214 
215     private static final int IX_JG_START=4;
216     private static final int IX_JG_LIMIT=5;
217     private static final int IX_JG_START2=6;  /* new in format version 2.2, ICU 54 */
218     private static final int IX_JG_LIMIT2=7;
219 
220     private static final int IX_TOP=16;
221 
222     // definitions for 16-bit bidi/shaping properties word ----------------- ***
223 
224                           /* CLASS_SHIFT=0, */     /* bidi class: 5 bits (4..0) */
225     private static final int JT_SHIFT=5;           /* joining type: 3 bits (7..5) */
226 
227     private static final int BPT_SHIFT=8;          /* Bidi_Paired_Bracket_Type(bpt): 2 bits (9..8) */
228 
229     private static final int MIRROR_DELTA_SHIFT=13;        /* bidi mirroring delta: 3 bits (15..13) */
230 
231     private static final int CLASS_MASK=    0x0000001f;
232     private static final int JT_MASK=       0x000000e0;
233     private static final int BPT_MASK=      0x00000300;
234 
getClassFromProps(int props)235     private static final int getClassFromProps(int props) {
236         return props&CLASS_MASK;
237     }
getFlagFromProps(int props, int shift)238     private static final boolean getFlagFromProps(int props, int shift) {
239         return ((props>>shift)&1)!=0;
240     }
getMirrorDeltaFromProps(int props)241     private static final int getMirrorDeltaFromProps(int props) {
242         return (short)props>>MIRROR_DELTA_SHIFT;
243     }
244 
245     private static final int ESC_MIRROR_DELTA=-4;
246 
247     // definitions for 32-bit mirror table entry --------------------------- ***
248 
249     /* the source Unicode code point takes 21 bits (20..0) */
250     private static final int MIRROR_INDEX_SHIFT=21;
251 
getMirrorCodePoint(int m)252     private static final int getMirrorCodePoint(int m) {
253         return m&0x1fffff;
254     }
getMirrorIndex(int m)255     private static final int getMirrorIndex(int m) {
256         return m>>>MIRROR_INDEX_SHIFT;
257     }
258 
259 
260     /*
261      * public singleton instance
262      */
263     public static final UBiDiProps INSTANCE;
264 
265     // This static initializer block must be placed after
266     // other static member initialization
267     static {
268         try {
269             INSTANCE = new UBiDiProps();
270         } catch (IOException e) {
271             throw new MissingResourceException(e.getMessage(),DATA_FILE_NAME,"");
272         }
273     }
274 }
275