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()
  57     private UBiDiProps() throws IOException{
  58         ByteBuffer bytes=ICUBinary.getRequiredData(DATA_FILE_NAME);
  59         readData(bytes);
  60     }
  61 
  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 {
 115         public boolean isDataVersionAcceptable(byte version[]) {
 116             return version[0]==2;
 117         }
 118     }
 119 
 120     // property access functions ------------------------------------------- ***
 121 
 122     public final int getClass(int c) {
 123         return getClassFromProps(trie.get(c));
 124     }
 125 
 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 
 155     public final int getMirror(int c) {
 156         int props=trie.get(c);
 157         return getMirror(c, props);
 158     }
 159 
 160     public final int getJoiningType(int c) {
 161         return (trie.get(c)&JT_MASK)>>JT_SHIFT;
 162     }
 163 
 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 
 180     public final int getPairedBracketType(int c) {
 181         return (trie.get(c)&BPT_MASK)>>BPT_SHIFT;
 182     }
 183 
 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 
 235     private static final int getClassFromProps(int props) {
 236         return props&CLASS_MASK;
 237     }
 238     private static final boolean getFlagFromProps(int props, int shift) {
 239         return ((props>>shift)&1)!=0;
 240     }
 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 
 252     private static final int getMirrorCodePoint(int m) {
 253         return m&0x1fffff;
 254     }
 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 }