2736 lines · 101.7 KB · Java
RawDownload
/* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *//* ******************************************************************************* * (C) Copyright IBM Corp. and others, 1996-2009 - All Rights Reserved         * *                                                                             * * The original version of this source code and documentation is copyrighted   * * and owned by IBM, These materials are provided under terms of a License     * * Agreement between IBM and Sun. This technology is protected by multiple     * * US and International patents. This notice and attribution to IBM may not    * * to removed.                                                                 * ******************************************************************************* */ package sun.text.normalizer; import java.io.BufferedInputStream;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.BufferedInputStream;import java.io.InputStream; /** * @author  Ram Viswanadha */public final class NormalizerImpl {    // Static block for the class to initialize its own self    static final NormalizerImpl IMPL;     static    {        try        {            IMPL = new NormalizerImpl();        }        catch (Exception e)        {            throw new RuntimeException(e.getMessage());        }    }     static final int UNSIGNED_BYTE_MASK =0xFF;    static final long UNSIGNED_INT_MASK = 0xffffffffL;    /*     * This new implementation of the normalization code loads its data from     * unorm.icu, which is generated with the gennorm tool.     * The format of that file is described at the end of this file.     */    private static final String DATA_FILE_NAME = "/sun/text/resources/unorm.icu";     // norm32 value constants     // quick check flags 0..3 set mean "no" for their forms    public static final int QC_NFC=0x11;          /* no|maybe */    public static final int QC_NFKC=0x22;         /* no|maybe */    public static final int QC_NFD=4;             /* no */    public static final int QC_NFKD=8;            /* no */     public static final int QC_ANY_NO=0xf;     /* quick check flags 4..5 mean "maybe" for their forms;     * test flags>=QC_MAYBE     */    public static final int QC_MAYBE=0x10;    public static final int QC_ANY_MAYBE=0x30;     public static final int QC_MASK=0x3f;     private static final int COMBINES_FWD=0x40;    private static final int COMBINES_BACK=0x80;    public  static final int COMBINES_ANY=0xc0;    // UnicodeData.txt combining class in bits 15.    private static final int CC_SHIFT=8;    public  static final int CC_MASK=0xff00;    // 16 bits for the index to UChars and other extra data    private static final int EXTRA_SHIFT=16;     /* norm32 value constants using >16 bits */    private static final long  MIN_SPECIAL    =  (long)(0xfc000000 & UNSIGNED_INT_MASK);    private static final long  SURROGATES_TOP =  (long)(0xfff00000 & UNSIGNED_INT_MASK);    private static final long  MIN_HANGUL     =  (long)(0xfff00000 & UNSIGNED_INT_MASK);//  private static final long  MIN_JAMO_V     =  (long)(0xfff20000 & UNSIGNED_INT_MASK);    private static final long  JAMO_V_TOP     =  (long)(0xfff30000 & UNSIGNED_INT_MASK);      /* indexes[] value names */    /* number of bytes in normalization trie */    static final int INDEX_TRIE_SIZE           = 0;    /* number of chars in extra data */    static final int INDEX_CHAR_COUNT           = 1;    /* number of uint16_t words for combining data */    static final int INDEX_COMBINE_DATA_COUNT = 2;    /* first code point with quick check NFC NO/MAYBE */    public static final int INDEX_MIN_NFC_NO_MAYBE   = 6;    /* first code point with quick check NFKC NO/MAYBE */    public static final int INDEX_MIN_NFKC_NO_MAYBE  = 7;    /* first code point with quick check NFD NO/MAYBE */    public static final int INDEX_MIN_NFD_NO_MAYBE   = 8;    /* first code point with quick check NFKD NO/MAYBE */    public static final int INDEX_MIN_NFKD_NO_MAYBE  = 9;    /* number of bytes in FCD trie */    static final int INDEX_FCD_TRIE_SIZE      = 10;    /* number of bytes in the auxiliary trie */    static final int INDEX_AUX_TRIE_SIZE      = 11;    /* changing this requires a new formatVersion */    static final int INDEX_TOP                = 32;      /* AUX constants */    /* value constants for auxTrie */    private static final int AUX_UNSAFE_SHIFT           = 11;    private static final int AUX_COMP_EX_SHIFT           = 10;    private static final int AUX_NFC_SKIPPABLE_F_SHIFT = 12;     private static final int AUX_MAX_FNC          =   ((int)1<<AUX_COMP_EX_SHIFT);    private static final int AUX_UNSAFE_MASK      =   (int)((1<<AUX_UNSAFE_SHIFT) & UNSIGNED_INT_MASK);    private static final int AUX_FNC_MASK         =   (int)((AUX_MAX_FNC-1) & UNSIGNED_INT_MASK);    private static final int AUX_COMP_EX_MASK     =   (int)((1<<AUX_COMP_EX_SHIFT) & UNSIGNED_INT_MASK);    private static final long AUX_NFC_SKIP_F_MASK =   ((UNSIGNED_INT_MASK&1)<<AUX_NFC_SKIPPABLE_F_SHIFT);     private static final int MAX_BUFFER_SIZE                    = 20;     /*******************************/     /* Wrappers for Trie implementations */    static final class NormTrieImpl implements Trie.DataManipulate{        static IntTrie normTrie= null;       /**        * Called by com.ibm.icu.util.Trie to extract from a lead surrogate's        * data the index array offset of the indexes for that lead surrogate.        * @param property data value for a surrogate from the trie, including        *         the folding offset        * @return data offset or 0 if there is no data for the lead surrogate        */        /* normTrie: 32-bit trie result may contain a special extraData index with the folding offset */        public int getFoldingOffset(int value){            return  BMP_INDEX_LENGTH+                    ((value>>(EXTRA_SHIFT-SURROGATE_BLOCK_BITS))&                    (0x3ff<<SURROGATE_BLOCK_BITS));        }     }    static final class FCDTrieImpl implements Trie.DataManipulate{        static CharTrie fcdTrie=null;       /**        * Called by com.ibm.icu.util.Trie to extract from a lead surrogate's        * data the index array offset of the indexes for that lead surrogate.        * @param property data value for a surrogate from the trie, including        *         the folding offset        * @return data offset or 0 if there is no data for the lead surrogate        */        /* fcdTrie: the folding offset is the lead FCD value itself */        public int getFoldingOffset(int value){            return value;        }    }     static final class AuxTrieImpl implements Trie.DataManipulate{        static CharTrie auxTrie = null;       /**        * Called by com.ibm.icu.util.Trie to extract from a lead surrogate's        * data the index array offset of the indexes for that lead surrogate.        * @param property data value for a surrogate from the trie, including        *        the folding offset        * @return data offset or 0 if there is no data for the lead surrogate        */        /* auxTrie: the folding offset is in bits 9..0 of the 16-bit trie result */        public int getFoldingOffset(int value){            return (int)(value &AUX_FNC_MASK)<<SURROGATE_BLOCK_BITS;        }    }     /****************************************************/      private static FCDTrieImpl fcdTrieImpl;    private static NormTrieImpl normTrieImpl;    private static AuxTrieImpl auxTrieImpl;    private static int[] indexes;    private static char[] combiningTable;    private static char[] extraData;     private static boolean isDataLoaded;    private static boolean isFormatVersion_2_1;    private static boolean isFormatVersion_2_2;    private static byte[] unicodeVersion;     /**     * Default buffer size of datafile     */    private static final int DATA_BUFFER_SIZE = 25000;     /**     * FCD check: everything below this code point is known to have a 0     * lead combining class     */    public static final int MIN_WITH_LEAD_CC=0x300;      /**     * Bit 7 of the length byte for a decomposition string in extra data is     * a flag indicating whether the decomposition string is     * preceded by a 16-bit word with the leading and trailing cc     * of the decomposition (like for A-umlaut);     * if not, then both cc's are zero (like for compatibility ideographs).     */    private static final int DECOMP_FLAG_LENGTH_HAS_CC=0x80;    /**     * Bits 6..0 of the length byte contain the actual length.     */    private static final int DECOMP_LENGTH_MASK=0x7f;     /** Length of the BMP portion of the index (stage 1) array. */    private static final int BMP_INDEX_LENGTH=0x10000>>Trie.INDEX_STAGE_1_SHIFT_;    /** Number of bits of a trail surrogate that are used in index table     * lookups.     */    private static final int SURROGATE_BLOCK_BITS=10-Trie.INDEX_STAGE_1_SHIFT_;     // public utility   public static int getFromIndexesArr(int index){        return indexes[index];   }    // protected constructor ---------------------------------------------     /**    * Constructor    * @exception thrown when data reading fails or data corrupted    */    private NormalizerImpl() throws IOException {        //data should be loaded only once        if(!isDataLoaded){             // jar access            InputStream i = ICUData.getRequiredStream(DATA_FILE_NAME);            BufferedInputStream b = new BufferedInputStream(i,DATA_BUFFER_SIZE);            NormalizerDataReader reader = new NormalizerDataReader(b);             // read the indexes            indexes = reader.readIndexes(NormalizerImpl.INDEX_TOP);             byte[] normBytes = new byte[indexes[NormalizerImpl.INDEX_TRIE_SIZE]];             int combiningTableTop = indexes[NormalizerImpl.INDEX_COMBINE_DATA_COUNT];            combiningTable = new char[combiningTableTop];             int extraDataTop = indexes[NormalizerImpl.INDEX_CHAR_COUNT];            extraData = new char[extraDataTop];             byte[] fcdBytes = new byte[indexes[NormalizerImpl.INDEX_FCD_TRIE_SIZE]];            byte[] auxBytes = new byte[indexes[NormalizerImpl.INDEX_AUX_TRIE_SIZE]];             fcdTrieImpl = new FCDTrieImpl();            normTrieImpl = new NormTrieImpl();            auxTrieImpl = new AuxTrieImpl();             // load the rest of the data data and initialize the data members            reader.read(normBytes, fcdBytes,auxBytes, extraData, combiningTable);             NormTrieImpl.normTrie = new IntTrie( new ByteArrayInputStream(normBytes),normTrieImpl );            FCDTrieImpl.fcdTrie   = new CharTrie( new ByteArrayInputStream(fcdBytes),fcdTrieImpl  );            AuxTrieImpl.auxTrie   = new CharTrie( new ByteArrayInputStream(auxBytes),auxTrieImpl  );             // we reached here without any exceptions so the data is fully            // loaded set the variable to true            isDataLoaded = true;             // get the data format version            byte[] formatVersion = reader.getDataFormatVersion();             isFormatVersion_2_1 =( formatVersion[0]>2                                    ||                                   (formatVersion[0]==2 && formatVersion[1]>=1)                                 );            isFormatVersion_2_2 =( formatVersion[0]>2                                    ||                                   (formatVersion[0]==2 && formatVersion[1]>=2)                                 );            unicodeVersion = reader.getUnicodeVersion();            b.close();        }    }     /* ---------------------------------------------------------------------- */     /* Korean Hangul and Jamo constants */     public static final int JAMO_L_BASE=0x1100;     /* "lead" jamo */    public static final int JAMO_V_BASE=0x1161;     /* "vowel" jamo */    public static final int JAMO_T_BASE=0x11a7;     /* "trail" jamo */     public static final int HANGUL_BASE=0xac00;     public static final int JAMO_L_COUNT=19;    public static final int JAMO_V_COUNT=21;    public static final int JAMO_T_COUNT=28;    public  static final int HANGUL_COUNT=JAMO_L_COUNT*JAMO_V_COUNT*JAMO_T_COUNT;     private static boolean isHangulWithoutJamoT(char c) {        c-=HANGUL_BASE;        return c<HANGUL_COUNT && c%JAMO_T_COUNT==0;    }     /* norm32 helpers */     /* is this a norm32 with a regular index? */    private static boolean isNorm32Regular(long norm32) {        return norm32<MIN_SPECIAL;    }     /* is this a norm32 with a special index for a lead surrogate? */    private static boolean isNorm32LeadSurrogate(long norm32) {        return MIN_SPECIAL<=norm32 && norm32<SURROGATES_TOP;    }     /* is this a norm32 with a special index for a Hangul syllable or a Jamo? */    private static boolean isNorm32HangulOrJamo(long norm32) {        return norm32>=MIN_HANGUL;    }     /*     * Given norm32 for Jamo V or T,     * is this a Jamo V?     */    private static boolean isJamoVTNorm32JamoV(long norm32) {        return norm32<JAMO_V_TOP;    }     /* data access primitives ----------------------------------------------- */     public static long/*unsigned*/ getNorm32(char c) {        return ((UNSIGNED_INT_MASK) & (NormTrieImpl.normTrie.getLeadValue(c)));    }     public static long/*unsigned*/ getNorm32FromSurrogatePair(long norm32,                                                               char c2) {        /*         * the surrogate index in norm32 stores only the number of the surrogate         * index block see gennorm/store.c/getFoldedNormValue()         */        return ((UNSIGNED_INT_MASK) &                    NormTrieImpl.normTrie.getTrailValue((int)norm32, c2));    }    ///CLOVER:OFF    private static long getNorm32(int c){        return (UNSIGNED_INT_MASK&(NormTrieImpl.normTrie.getCodePointValue(c)));    }     /*     * get a norm32 from text with complete code points     * (like from decompositions)     */    private static long/*unsigned*/ getNorm32(char[] p,int start,                                              int/*unsigned*/ mask) {        long/*unsigned*/ norm32= getNorm32(p[start]);        if(((norm32&mask)>0) && isNorm32LeadSurrogate(norm32)) {            /* *p is a lead surrogate, get the real norm32 */            norm32=getNorm32FromSurrogatePair(norm32, p[start+1]);        }        return norm32;    }     //// for StringPrep    public static VersionInfo getUnicodeVersion(){        return VersionInfo.getInstance(unicodeVersion[0], unicodeVersion[1],                                       unicodeVersion[2], unicodeVersion[3]);    }     public static char    getFCD16(char c) {        return  FCDTrieImpl.fcdTrie.getLeadValue(c);    }     public static char getFCD16FromSurrogatePair(char fcd16, char c2) {        /* the surrogate index in fcd16 is an absolute offset over the         * start of stage 1         * */        return FCDTrieImpl.fcdTrie.getTrailValue(fcd16, c2);    }    public static int getFCD16(int c) {        return  FCDTrieImpl.fcdTrie.getCodePointValue(c);    }     private static int getExtraDataIndex(long norm32) {        return (int)(norm32>>EXTRA_SHIFT);    }     private static final class DecomposeArgs{        int /*unsigned byte*/ cc;        int /*unsigned byte*/ trailCC;        int length;    }    /**     *     * get the canonical or compatibility decomposition for one character     *     * @return index into the extraData array     */    private static int/*index*/ decompose(long/*unsigned*/ norm32,                                          int/*unsigned*/ qcMask,                                          DecomposeArgs args) {        int p= getExtraDataIndex(norm32);        args.length=extraData[p++];         if((norm32&qcMask&QC_NFKD)!=0 && args.length>=0x100) {            /* use compatibility decomposition, skip canonical data */            p+=((args.length>>7)&1)+(args.length&DECOMP_LENGTH_MASK);            args.length>>=8;        }         if((args.length&DECOMP_FLAG_LENGTH_HAS_CC)>0) {            /* get the lead and trail cc's */            char bothCCs=extraData[p++];            args.cc=(UNSIGNED_BYTE_MASK) & (bothCCs>>8);            args.trailCC=(UNSIGNED_BYTE_MASK) & bothCCs;        } else {            /* lead and trail cc's are both 0 */            args.cc=args.trailCC=0;        }         args.length&=DECOMP_LENGTH_MASK;        return p;    }      /**     * get the canonical decomposition for one character     * @return index into the extraData array     */    private static int decompose(long/*unsigned*/ norm32,                                 DecomposeArgs args) {         int p= getExtraDataIndex(norm32);        args.length=extraData[p++];         if((args.length&DECOMP_FLAG_LENGTH_HAS_CC)>0) {            /* get the lead and trail cc's */            char bothCCs=extraData[p++];            args.cc=(UNSIGNED_BYTE_MASK) & (bothCCs>>8);            args.trailCC=(UNSIGNED_BYTE_MASK) & bothCCs;        } else {            /* lead and trail cc's are both 0 */            args.cc=args.trailCC=0;        }         args.length&=DECOMP_LENGTH_MASK;        return p;    }      private static final class NextCCArgs{        char[] source;        int next;        int limit;        char c;        char c2;    }     /*     * get the combining class of (c, c2)= args.source[args.next++]     * before: args.next<args.limit  after: args.next<=args.limit     * if only one code unit is used, then c2==0     */    private static int /*unsigned byte*/ getNextCC(NextCCArgs args) {        long /*unsigned*/ norm32;         args.c=args.source[args.next++];         norm32= getNorm32(args.c);        if((norm32 & CC_MASK)==0) {            args.c2=0;            return 0;        } else {            if(!isNorm32LeadSurrogate(norm32)) {                args.c2=0;            } else {                /* c is a lead surrogate, get the real norm32 */

Lines 1–500 of 2736.