/**
*******************************************************************************
* Copyright (C) 1996-2004, International Business Machines Corporation and    *
* others. All Rights Reserved.                                                *
*******************************************************************************
*/
package com.ibm.icu.impl;

import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.IOException;

import com.ibm.icu.text.UTF16;
import com.ibm.icu.text.UnicodeSet;
import com.ibm.icu.util.UResourceBundle;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.lang.UCharacterCategory;

/**
* Internal class to manage character names.
* Since data for names are stored
* in an array of char, by default indexes used in this class is refering to
* a 2 byte count, unless otherwise stated. Cases where the index is refering
* to a byte count, the index is halved and depending on whether the index is
* even or odd, the MSB or LSB of the result char at the halved index is
* returned. For indexes to an array of int, the index is multiplied by 2,
* result char at the multiplied index and its following char is returned as an
* int.
* <a href=../lang/UCharacter.html>UCharacter</a> acts as a public facade for this class
* Note : 0 - 0x1F are control characters without names in Unicode 3.0
* @author Syn Wee Quek
* @since nov0700
*/

public final class UCharacterName
{
    // public data members ----------------------------------------------

    /**
    * Number of lines per group
    * 1 << GROUP_SHIFT_
    */
    public static final int LINES_PER_GROUP_ = 1 << 5;
    /**
     * Maximum number of groups
     */
    public int m_groupcount_ = 0;

    // public methods ---------------------------------------------------

    /**
     * Gets the only instance of UCharacterName
     * @return only instance of UCharacterName
     * @exception RuntimeException thrown when reading of name data fails
     */
    public static UCharacterName getInstance() throws RuntimeException
    {
        if (INSTANCE_ == null) {
            try {
                INSTANCE_ = new UCharacterName();
            }catch(IOException e){
                throw new InternalError("Could not construct UCharacterName. Missing unames.icu?");
            }
            catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        }
        return INSTANCE_;
    }

    /**
    * Retrieve the name of a Unicode code point.
    * Depending on <code>choice</code>, the character name written into the
    * buffer is the "modern" name or the name that was defined in Unicode
    * version 1.0.
    * The name contains only "invariant" characters
    * like A-Z, 0-9, space, and '-'.
    *
    * @param ch the code point for which to get the name.
    * @param choice Selector for which name to get.
    * @return if code point is above 0x1fff, null is returned
    */
    public String getName(int ch, int choice)
    {
        if (ch < UCharacter.MIN_VALUE || ch > UCharacter.MAX_VALUE ||
            choice > UCharacterNameChoice.CHAR_NAME_CHOICE_COUNT) {
            return null;
        }

        String result = null;

        result = getAlgName(ch, choice);

        // getting normal character name
        if (result == null || result.length() == 0) {
            if (choice == UCharacterNameChoice.EXTENDED_CHAR_NAME) {
                result = getExtendedName(ch);
            } else {
                result = getGroupName(ch, choice);
            }
        }

        return result;
    }

    /**
    * Find a character by its name and return its code point value
    * @param character name
    * @param choice selector to indicate if argument name is a Unicode 1.0
    *        or the most current version
    * @return code point
    */
    public int getCharFromName(int choice, String name)
    {
        // checks for illegal arguments
        if (choice >= UCharacterNameChoice.CHAR_NAME_CHOICE_COUNT ||
            name == null || name.length() == 0) {
            return -1;
        }

        // try extended names first
        int result = getExtendedChar(name.toLowerCase(), choice);
        if (result >= -1) {
            return result;
        }

        String upperCaseName = name.toUpperCase();
        // try algorithmic names first, if fails then try group names
        // int result = getAlgorithmChar(choice, uppercasename);

        if (choice != UCharacterNameChoice.UNICODE_10_CHAR_NAME) {
            int count = 0;
            if (m_algorithm_ != null) {
                count = m_algorithm_.length;
            }
            for (count --; count >= 0; count --) {
                result = m_algorithm_[count].getChar(upperCaseName);
                if (result >= 0) {
                    return result;
                }
            }
        }

        if (choice == UCharacterNameChoice.EXTENDED_CHAR_NAME) {
            result = getGroupChar(upperCaseName,
                                  UCharacterNameChoice.UNICODE_CHAR_NAME);
            if (result == -1) {
                result = getGroupChar(upperCaseName,
                                  UCharacterNameChoice.UNICODE_10_CHAR_NAME);
            }
        }
        else {
            result = getGroupChar(upperCaseName, choice);
        }
        return result;
    }

    // these are all UCharacterNameIterator use methods -------------------

    /**
    * Reads a block of compressed lengths of 32 strings and expands them into
    * offsets and lengths for each string. Lengths are stored with a
    * variable-width encoding in consecutive nibbles:
    * If a nibble<0xc, then it is the length itself (0 = empty string).
    * If a nibble>=0xc, then it forms a length value with the following
    * nibble.
    * The offsets and lengths arrays must be at least 33 (one more) long
    * because there is no check here at the end if the last nibble is still
    * used.
    * @param index of group string object in array
    * @param offsets array to store the value of the string offsets
    * @param lengths array to store the value of the string length
    * @return next index of the data string immediately after the lengths
    *         in terms of byte address
    */
    public int getGroupLengths(int index, char offsets[], char lengths[])
    {
        char length = 0xffff;
        byte b = 0,
            n = 0;
        int shift;
        index = index * m_groupsize_; // byte count offsets of group strings
        int stringoffset = UCharacterUtility.toInt(
                                 m_groupinfo_[index + OFFSET_HIGH_OFFSET_],
                                 m_groupinfo_[index + OFFSET_LOW_OFFSET_]);

        offsets[0] = 0;

        // all 32 lengths must be read to get the offset of the first group
        // string
        for (int i = 0; i < LINES_PER_GROUP_; stringoffset ++) {
            b = m_groupstring_[stringoffset];
            shift = 4;

            while (shift >= 0) {
                // getting nibble
                n = (byte)((b >> shift) & 0x0F);
                if (length == 0xffff && n > SINGLE_NIBBLE_MAX_) {
                    length = (char)((n - 12) << 4);
                }
                else {
                    if (length != 0xffff) {
                       lengths[i] = (char)((length | n) + 12);
                    }
                    else {
                       lengths[i] = (char)n;
                    }

                    if (i < LINES_PER_GROUP_) {
                       offsets[i + 1] = (char)(offsets[i] + lengths[i]);
                    }

                    length = 0xffff;
                    i ++;
                }

                shift -= 4;
            }
        }
        return stringoffset;
    }

    /**
    * Gets the name of the argument group index.
    * UnicodeData.txt uses ';' as a field separator, so no field can contain
    * ';' as part of its contents. In unames.icu, it is marked as
    * token[';'] == -1 only if the semicolon is used in the data file - which
    * is iff we have Unicode 1.0 names or ISO comments.
    * So, it will be token[';'] == -1 if we store U1.0 names/ISO comments
    * although we know that it will never be part of a name.
    * Equivalent to ICU4C's expandName.
    * @param index of the group name string in byte count
    * @param length of the group name string
    * @param choice of Unicode 1.0 name or the most current name
    * @return name of the group
    */
    public String getGroupName(int index, int length, int choice)
    {
        if (choice == UCharacterNameChoice.UNICODE_10_CHAR_NAME
            || choice == UCharacterNameChoice.ISO_COMMENT_) {
            if (';' >= m_tokentable_.length || m_tokentable_[';'] == 0xFFFF) {
                // skip the modern name
                int oldindex = index;
                index += UCharacterUtility.skipByteSubString(m_groupstring_,
                                                   index, length, (byte)';');
                length -= (index - oldindex);
                if (choice == UCharacterNameChoice.ISO_COMMENT_) {
                    // skips the 1.0 Name to the iso comment part
                    oldindex = index;
                    index += UCharacterUtility.skipByteSubString(m_groupstring_,
                                                    index, length, (byte)';');
                    length -= (index - oldindex);
                }
            }
            else {
                // the semicolon byte is a token number, therefore only modern
                // names are stored in unames.dat and there is no such
                // requested Unicode 1.0 name here
                length = 0;
            }
        }

        synchronized (m_utilStringBuffer_) {
            m_utilStringBuffer_.delete(0, m_utilStringBuffer_.length());
            byte b;
            char token;
            for (int i = 0; i < length;) {
                b = m_groupstring_[index + i];
                i ++;

                if (b >= m_tokentable_.length) {
                    if (b == ';') {
                        break;
                    }
                    m_utilStringBuffer_.append(b); // implicit letter
                }
                else {
                    token = m_tokentable_[b & 0x00ff];
                    if (token == 0xFFFE) {
                        // this is a lead byte for a double-byte token
                        token = m_tokentable_[b << 8 |
                                          (m_groupstring_[index + i] & 0x00ff)];
                        i ++;
                    }
                    if (token == 0xFFFF) {
                        if (b == ';') {
                            // skip the semicolon if we are seeking extended
                            // names and there was no 2.0 name but there
                            // is a 1.0 name.
                            if (m_utilStringBuffer_.length() == 0 && choice ==
                                   UCharacterNameChoice.EXTENDED_CHAR_NAME) {
                                continue;
                            }
                            break;
                        }
                        // explicit letter
                        m_utilStringBuffer_.append((char)(b & 0x00ff));
                    }
                    else { // write token word
                        UCharacterUtility.getNullTermByteSubString(
                                m_utilStringBuffer_, m_tokenstring_, token);
                    }
                }
            }

            if (m_utilStringBuffer_.length() > 0) {
                return m_utilStringBuffer_.toString();
            }
        }
        return null;
    }

    /**
    * Retrieves the extended name
    */
    public String getExtendedName(int ch)
    {
        String result = getName(ch, UCharacterNameChoice.UNICODE_CHAR_NAME);
        if (result == null) {
            if (getType(ch) == UCharacterCategory.CONTROL) {
                result = getName(ch,
                                 UCharacterNameChoice.UNICODE_10_CHAR_NAME);
            }
            if (result == null) {
                result = getExtendedOr10Name(ch);
            }
        }
        return result;
    }

    /**
     * Gets the group index for the codepoint, or the group before it.
     * @param codepoint
     * @return group index containing codepoint or the group before it.
     */
    public int getGroup(int codepoint)
    {
        int endGroup = m_groupcount_;
        int msb      = getCodepointMSB(codepoint);
        int result   = 0;
        // binary search for the group of names that contains the one for
        // code
        // find the group that contains codepoint, or the highest before it
        while (result < endGroup - 1) {
            int gindex = (result + endGroup) >> 1;
            if (msb < getGroupMSB(gindex)) {
                endGroup = gindex;
            }
            else {
                result = gindex;
            }
        }
        return result;
    }

    /**
     * Gets the extended and 1.0 name when the most current unicode names
     * fail
     * @param ch codepoint
     * @return name of codepoint extended or 1.0
     */
    public String getExtendedOr10Name(int ch)
    {
        String result = null;
        if (getType(ch) == UCharacterCategory.CONTROL) {
            result = getName(ch,
                             UCharacterNameChoice.UNICODE_10_CHAR_NAME);
        }
        if (result == null) {
            int type = getType(ch);
            // Return unknown if the table of names above is not up to
            // date.
            if (type >= TYPE_NAMES_.length) {
                result = UNKNOWN_TYPE_NAME_;
            }
            else {
                result = TYPE_NAMES_[type];
            }
            synchronized (m_utilStringBuffer_) {
                m_utilStringBuffer_.delete(0, m_utilStringBuffer_.length());
                m_utilStringBuffer_.append('<');
                m_utilStringBuffer_.append(result);
                m_utilStringBuffer_.append('-');
                String chStr = Integer.toHexString(ch).toUpperCase();
                int zeros = 4 - chStr.length();
                while (zeros > 0) {
                    m_utilStringBuffer_.append('0');
                    zeros --;
                }
                m_utilStringBuffer_.append(chStr);
                m_utilStringBuffer_.append('>');
                result = m_utilStringBuffer_.toString();
            }
        }
        return result;
    }

    /**
     * Gets the MSB from the group index
     * @param gindex group index
     * @return the MSB of the group if gindex is valid, -1 otherwise
     */
    public int getGroupMSB(int gindex)
    {
        if (gindex >= m_groupcount_) {
            return -1;
        }
        return m_groupinfo_[gindex * m_groupsize_];
    }

    /**
     * Gets the MSB of the codepoint
     * @param codepoint
     * @return the MSB of the codepoint
     */
    public static int getCodepointMSB(int codepoint)
    {
        return codepoint >> GROUP_SHIFT_;
    }

    /**
     * Gets the maximum codepoint + 1 of the group
     * @param msb most significant byte of the group
     * @return limit codepoint of the group
     */
    public static int getGroupLimit(int msb)
    {
        return (msb << GROUP_SHIFT_) + LINES_PER_GROUP_;
    }

    /**
     * Gets the minimum codepoint of the group
     * @param msb most significant byte of the group
     * @return minimum codepoint of the group
     */
    public static int getGroupMin(int msb)
    {
        return msb << GROUP_SHIFT_;
    }

    /**
     * Gets the offset to a group
     * @param codepoint
     * @return offset to a group
     */
    public static int getGroupOffset(int codepoint)
    {
        return codepoint & GROUP_MASK_;
    }

    /**
     * Gets the minimum codepoint of a group
     * @param codepoint
     * @return minimum codepoint in the group which codepoint belongs to
     */
    ///CLOVER:OFF
    public static int getGroupMinFromCodepoint(int codepoint)
    {
        return codepoint & ~GROUP_MASK_;
    }
    ///CLOVER:ON

    /**
     * Get the Algorithm range length
     * @return Algorithm range length
     */
    public int getAlgorithmLength()
    {
        return m_algorithm_.length;
    }

    /**
     * Gets the start of the range
     * @param index algorithm index
     * @return algorithm range start
     */
    public int getAlgorithmStart(int index)
    {
        return m_algorithm_[index].m_rangestart_;
    }

    /**
     * Gets the end of the range
     * @param index algorithm index
     * @return algorithm range end
     */
    public int getAlgorithmEnd(int index)
    {
        return m_algorithm_[index].m_rangeend_;
    }

    /**
     * Gets the Algorithmic name of the codepoint
     * @param index algorithmic range index
     * @param codepoint
     * @return algorithmic name of codepoint
     */
    public String getAlgorithmName(int index, int codepoint)
    {
        String result = null;
        synchronized (m_utilStringBuffer_) {
            m_utilStringBuffer_.delete(0, m_utilStringBuffer_.length());
            m_algorithm_[index].appendName(codepoint, m_utilStringBuffer_);
            result = m_utilStringBuffer_.toString();
        }
        return result;
    }

    /**
    * Gets the group name of the character
    * @param ch character to get the group name
    * @param choice name choice selector to choose a unicode 1.0 or newer name
    */
    public String getGroupName(int ch, int choice)
    {
        // gets the msb
        int msb   = getCodepointMSB(ch);
        int group = getGroup(ch);

        // return this if it is an exact match
        if (msb == m_groupinfo_[group * m_groupsize_]) {
            int index = getGroupLengths(group, m_groupoffsets_,
                                        m_grouplengths_);
            int offset = ch & GROUP_MASK_;
            return getGroupName(index + m_groupoffsets_[offset],
                                m_grouplengths_[offset], choice);
        }

        return null;
    }

    // these are transliterator use methods ---------------------------------

    /**
     * Gets the maximum length of any codepoint name.
     * Equivalent to uprv_getMaxCharNameLength.
     * @return the maximum length of any codepoint name
     */
    public int getMaxCharNameLength()
    {
        if (initNameSetsLengths()) {
            return m_maxNameLength_;
        }
        else {
            return 0;
        }
    }

    /**
     * Gets the maximum length of any iso comments.
     * Equivalent to uprv_getMaxISOCommentLength.
     * @return the maximum length of any codepoint name
     */
    ///CLOVER:OFF
    public int getMaxISOCommentLength()
    {
        if (initNameSetsLengths()) {
            return m_maxISOCommentLength_;
        }
        else {
            return 0;
        }
    }
    ///CLOVER:ON

    /**
     * Fills set with characters that are used in Unicode character names.
     * Equivalent to uprv_getCharNameCharacters.
     * @param set USet to receive characters. Existing contents are deleted.
     */
    public void getCharNameCharacters(UnicodeSet set)
    {
        convert(m_nameSet_, set);
    }

    /**
     * Fills set with characters that are used in Unicode character names.
     * Equivalent to uprv_getISOCommentCharacters.
     * @param set USet to receive characters. Existing contents are deleted.
     */
    ///CLOVER:OFF
    public void getISOCommentCharacters(UnicodeSet set)
    {
        convert(m_ISOCommentSet_, set);
    }
    ///CLOVER:ON

    // package private inner class --------------------------------------

    /**
    * Algorithmic name class
    */
    static final class AlgorithmName
    {
        // package private data members ----------------------------------

        /**
        * Constant type value of the different AlgorithmName
        */
        static final int TYPE_0_ = 0;
        static final int TYPE_1_ = 1;

        // package private constructors ----------------------------------

        /**
        * Constructor
        */
        AlgorithmName()
        {
        }

        // package private methods ---------------------------------------

        /**
        * Sets the information for accessing the algorithmic names
        * @param rangestart starting code point that lies within this name group
        * @param rangeend end code point that lies within this name group
        * @param type algorithm type. There's 2 kinds of algorithmic type. First
        *        which uses code point as part of its name and the other uses
        *        variant postfix strings
        * @param variant algorithmic variant
        * @return true if values are valid
        */
        boolean setInfo(int rangestart, int rangeend, byte type, byte variant)
        {
            if (rangestart >= UCharacter.MIN_VALUE && rangestart <= rangeend
                && rangeend <= UCharacter.MAX_VALUE &&
                (type == TYPE_0_ || type == TYPE_1_)) {
                m_rangestart_ = rangestart;
                m_rangeend_ = rangeend;
                m_type_ = type;
                m_variant_ = variant;
                return true;
            }
            return false;
        }

        /**
        * Sets the factor data
        * @param array of factor
        * @return true if factors are valid
        */
        boolean setFactor(char factor[])
        {
            if (factor.length == m_variant_) {
                m_factor_ = factor;
                return true;
            }
            return false;
        }

        /**
        * Sets the name prefix
        * @param prefix
        * @return true if prefix is set
        */
        boolean setPrefix(String prefix)
        {
            if (prefix != null && prefix.length() > 0) {
                m_prefix_ = prefix;
                return true;
            }
            return false;
        }

        /**
        * Sets the variant factorized name data
        * @param string variant factorized name data
        * @return true if values are set
        */
        boolean setFactorString(byte string[])
        {
            // factor and variant string can be empty for things like
            // hanggul code points
            m_factorstring_ = string;
            return true;
        }

        /**
        * Checks if code point lies in Algorithm object at index
        * @param ch code point
        */
        boolean contains(int ch)
        {
            return m_rangestart_ <= ch && ch <= m_rangeend_;
        }

        /**
        * Appends algorithm name of code point into StringBuffer.
        * Note this method does not check for validity of code point in Algorithm,
        * result is undefined if code point does not belong in Algorithm.
        * @param ch code point
        * @param str StringBuffer to append to
        */
        void appendName(int ch, StringBuffer str)
        {
            str.append(m_prefix_);
            switch (m_type_)
            {
                case TYPE_0_:
                    // prefix followed by hex digits indicating variants
                    Utility.hex(ch, m_variant_, str);
                    break;
                case TYPE_1_:
                    // prefix followed by factorized-elements
                    int offset = ch - m_rangestart_;
                    int indexes[] = m_utilIntBuffer_;
                    int factor;

                    // write elements according to the factors
                    // the factorized elements are determined by modulo
                    // arithmetic
                    synchronized (m_utilIntBuffer_) {
                        for (int i = m_variant_ - 1; i > 0; i --)
                        {
                            factor = m_factor_[i] & 0x00FF;
                            indexes[i] = offset % factor;
                            offset /= factor;
                        }

                        // we don't need to calculate the last modulus because
                        // start <= code <= end guarantees here that
                        // code <= factors[0]
                        indexes[0] = offset;

                        // joining up the factorized strings
                        str.append(getFactorString(indexes, m_variant_));
                    }
                    break;
            }
        }

        /**
        * Gets the character for the argument algorithmic name
        * @return the algorithmic char or -1 otherwise.
        */
        int getChar(String name)
        {
            int prefixlen = m_prefix_.length();
            if (name.length() < prefixlen ||
                !m_prefix_.equals(name.substring(0, prefixlen))) {
                return -1;
            }

            switch (m_type_)
            {
                case TYPE_0_ :
                try
                {
                    int result = Integer.parseInt(name.substring(prefixlen),
                                                  16);
                    // does it fit into the range?
                    if (m_rangestart_ <= result && result <= m_rangeend_) {
                        return result;
                    }
                }
                catch (NumberFormatException e)
                {
                    return -1;
                }
                break;
                case TYPE_1_ :
                    // repetitative suffix name comparison done here
                    // offset is the character code - start
                    for (int ch = m_rangestart_; ch <= m_rangeend_; ch ++)
                    {
                        int offset = ch - m_rangestart_;
                        int indexes[] = m_utilIntBuffer_;
                        int factor;

                        // write elements according to the factors
                        // the factorized elements are determined by modulo
                        // arithmetic
                        synchronized (m_utilIntBuffer_) {
                            for (int i = m_variant_ - 1; i > 0; i --)
                            {
                                factor = m_factor_[i] & 0x00FF;
                                indexes[i] = offset % factor;
                                offset /= factor;
                            }

                            // we don't need to calculate the last modulus
                            // because start <= code <= end guarantees here that
                            // code <= factors[0]
                            indexes[0] = offset;

                            // joining up the factorized strings
                            if (compareFactorString(indexes, m_variant_, name,
                                                    prefixlen)) {
                                return ch;
                            }
                        }
                    }
            }

            return -1;
        }

        /**
         * Adds all chars in the set of algorithmic names into the set.
         * Equivalent to part of calcAlgNameSetsLengths.
         * @param set int set to add the chars of the algorithm names into
         * @param maxlength maximum length to compare to
         * @return the length that is either maxlength of the length of this
         *         algorithm name if it is longer than maxlength
         */
        int add(int set[], int maxlength)
        {
            // prefix length
            int length = UCharacterName.add(set, m_prefix_);
            switch (m_type_) {
                case TYPE_0_ : {
                    // name = prefix + (range->variant times) hex-digits
                    // prefix
                    length += m_variant_;
                    /* synwee to check
                     * addString(set, (const char *)(range + 1))
                                       + range->variant;*/
                    break;
                }
                case TYPE_1_ : {
                    // name = prefix factorized-elements
                    // get the set and maximum factor suffix length for each
                    // factor
                    for (int i = m_variant_ - 1; i > 0; i --)
                    {
                        int maxfactorlength = 0;
                        int count = 0;
                        for (int factor = m_factor_[i]; factor > 0; -- factor) {
                            synchronized (m_utilStringBuffer_) {
                                m_utilStringBuffer_.delete(0,
                                                m_utilStringBuffer_.length());
                                count
                                  = UCharacterUtility.getNullTermByteSubString(
                                                m_utilStringBuffer_,
                                                m_factorstring_, count);
                                UCharacterName.add(set, m_utilStringBuffer_);
                                if (m_utilStringBuffer_.length()
                                                            > maxfactorlength)
                                {
                                    maxfactorlength
                                                = m_utilStringBuffer_.length();
                                }
                            }
                        }
                        length += maxfactorlength;
                    }
                }
            }
            if (length > maxlength) {
                return length;
            }
            return maxlength;
        }

        // private data members ------------------------------------------

        /**
        * Algorithmic data information
        */
        private int m_rangestart_;
        private int m_rangeend_;
        private byte m_type_;
        private byte m_variant_;
        private char m_factor_[];
        private String m_prefix_;
        private byte m_factorstring_[];
        /**
         * Utility StringBuffer
         */
        private StringBuffer m_utilStringBuffer_ = new StringBuffer();
        /**
         * Utility int buffer
         */
        private int m_utilIntBuffer_[] = new int[256];

        // private methods -----------------------------------------------

        /**
        * Gets the indexth string in each of the argument factor block
        * @param index array with each index corresponding to each factor block
        * @param length length of the array index
        * @return the combined string of the array of indexth factor string in
        *         factor block
        */
        private String getFactorString(int index[], int length)
        {
            int size = m_factor_.length;
            if (index == null || length != size) {
                return null;
            }

            synchronized (m_utilStringBuffer_) {
                m_utilStringBuffer_.delete(0, m_utilStringBuffer_.length());
                int count = 0;
                int factor;
                size --;
                for (int i = 0; i <= size; i ++) {
                    factor = m_factor_[i];
                    count = UCharacterUtility.skipNullTermByteSubString(
                                             m_factorstring_, count, index[i]);
                    count = UCharacterUtility.getNullTermByteSubString(
                                          m_utilStringBuffer_, m_factorstring_,
                                          count);
                    if (i != size) {
                        count = UCharacterUtility.skipNullTermByteSubString(
                                                       m_factorstring_, count,
                                                       factor - index[i] - 1);
                    }
                }
                return m_utilStringBuffer_.toString();
            }
        }

        /**
        * Compares the indexth string in each of the argument factor block with
        * the argument string
        * @param index array with each index corresponding to each factor block
        * @param length index array length
        * @param str string to compare with
        * @param offset of str to start comparison
        * @return true if string matches
        */
        private boolean compareFactorString(int index[], int length, String str,
                                            int offset)
        {
            int size = m_factor_.length;
            if (index == null || length != size)
                return false;

            int count = 0;
            int strcount = offset;
            int factor;
            size --;
            for (int i = 0; i <= size; i ++)
            {
                factor = m_factor_[i];
                count = UCharacterUtility.skipNullTermByteSubString(
                                          m_factorstring_, count, index[i]);
                strcount = UCharacterUtility.compareNullTermByteSubString(str,
                                          m_factorstring_, strcount, count);
                if (strcount < 0) {
                    return false;
                }

                if (i != size) {
                    count = UCharacterUtility.skipNullTermByteSubString(
                                  m_factorstring_, count, factor - index[i]);
                }
            }
            if (strcount != str.length()) {
                return false;
            }
            return true;
        }
    }

    // package private data members --------------------------------------

    /**
     * Size of each groups
     */
    int m_groupsize_ = 0;

    // package private methods --------------------------------------------

    /**
    * Sets the token data
    * @param token array of tokens
    * @param tokenstring array of string values of the tokens
    * @return false if there is a data error
    */
    boolean setToken(char token[], byte tokenstring[])
    {
        if (token != null && tokenstring != null && token.length > 0 &&
            tokenstring.length > 0) {
            m_tokentable_ = token;
            m_tokenstring_ = tokenstring;
            return true;
        }
        return false;
    }

    /**
    * Set the algorithm name information array
    * @param algorithm information array
    * @return true if the group string offset has been set correctly
    */
    boolean setAlgorithm(AlgorithmName alg[])
    {
        if (alg != null && alg.length != 0) {
            m_algorithm_ = alg;
            return true;
        }
        return false;
    }

    /**
    * Sets the number of group and size of each group in number of char
    * @param count number of groups
    * @param size size of group in char
    * @return true if group size is set correctly
    */
    boolean setGroupCountSize(int count, int size)
    {
        if (count <= 0 || size <= 0) {
            return false;
        }
        m_groupcount_ = count;
        m_groupsize_ = size;
        return true;
    }

    /**
    * Sets the group name data
    * @param group index information array
    * @param groupstring name information array
    * @return false if there is a data error
    */
    boolean setGroup(char group[], byte groupstring[])
    {
        if (group != null && groupstring != null && group.length > 0 &&
            groupstring.length > 0) {
            m_groupinfo_ = group;
            m_groupstring_ = groupstring;
            return true;
        }
        return false;
    }

    // private data members ----------------------------------------------

    /**
    * Data used in unames.icu
    */
    private char m_tokentable_[];
    private byte m_tokenstring_[];
    private char m_groupinfo_[];
    private byte m_groupstring_[];
    private AlgorithmName m_algorithm_[];

    /**
    * Group use
    */
    private char m_groupoffsets_[] = new char[LINES_PER_GROUP_ + 1];
    private char m_grouplengths_[] = new char[LINES_PER_GROUP_ + 1];

    /**
    * Default name of the name datafile
    */
    private static final String NAME_FILE_NAME_ = ICUResourceBundle.ICU_BUNDLE+"/unames.icu";
    /**
    * Shift count to retrieve group information
    */
    private static final int GROUP_SHIFT_ = 5;
    /**
    * Mask to retrieve the offset for a particular character within a group
    */
    private static final int GROUP_MASK_ = LINES_PER_GROUP_ - 1;
    /**
    * Default buffer size of datafile
    */
    private static final int NAME_BUFFER_SIZE_ = 100000;

    /**
    * Position of offsethigh in group information array
    */
    private static final int OFFSET_HIGH_OFFSET_ = 1;

    /**
    * Position of offsetlow in group information array
    */
    private static final int OFFSET_LOW_OFFSET_ = 2;
    /**
    * Double nibble indicator, any nibble > this number has to be combined
    * with its following nibble
    */
    private static final int SINGLE_NIBBLE_MAX_ = 11;

    /**
     * Maximum length of character names (regular & 1.0).
     */
    private static int MAX_NAME_LENGTH_ = 0;
    /**
     * Maximum length of ISO comments.
     */
    private static int MAX_ISO_COMMENT_LENGTH_ = 0;

    /**
     * Set of chars used in character names (regular & 1.0).
     * Chars are platform-dependent (can be EBCDIC).
     */
    private int m_nameSet_[] = new int[8];
    /**
     * Set of chars used in ISO comments. (regular & 1.0).
     * Chars are platform-dependent (can be EBCDIC).
     */
    private int m_ISOCommentSet_[] = new int[8];
    /**
     * Utility StringBuffer
     */
    private StringBuffer m_utilStringBuffer_ = new StringBuffer();
    /**
     * Utility int buffer
     */
    private int m_utilIntBuffer_[] = new int[2];
    /**
     * Maximum ISO comment length
     */
    private int m_maxISOCommentLength_;
    /**
     * Maximum name length
     */
    private int m_maxNameLength_;
    /**
     * Singleton instance
     */
    private static UCharacterName INSTANCE_ = null;
    /**
     * Type names used for extended names
     */
    private static final String TYPE_NAMES_[] = {"unassigned",
                                                 "uppercase letter",
                                                 "lowercase letter",
                                                 "titlecase letter",
                                                 "modifier letter",
                                                 "other letter",
                                                 "non spacing mark",
                                                 "enclosing mark",
                                                 "combining spacing mark",
                                                 "decimal digit number",
                                                 "letter number",
                                                 "other number",
                                                 "space separator",
                                                 "line separator",
                                                 "paragraph separator",
                                                 "control",
                                                 "format",
                                                 "private use area",
                                                 "surrogate",
                                                 "dash punctuation",
                                                 "start punctuation",
                                                 "end punctuation",
                                                 "connector punctuation",
                                                 "other punctuation",
                                                 "math symbol",
                                                 "currency symbol",
                                                 "modifier symbol",
                                                 "other symbol",
                                                 "initial punctuation",
                                                 "final punctuation",
                                                 "noncharacter",
                                                 "lead surrogate",
                                                 "trail surrogate"};
    /**
     * Unknown type name
     */
    private static final String UNKNOWN_TYPE_NAME_ = "unknown";
    /**
     * Not a character type
     */
    private static final int NON_CHARACTER_
                                    = UCharacterCategory.CHAR_CATEGORY_COUNT;
    /**
    * Lead surrogate type
    */
    private static final int LEAD_SURROGATE_
                                  = UCharacterCategory.CHAR_CATEGORY_COUNT + 1;
    /**
    * Trail surrogate type
    */
    private static final int TRAIL_SURROGATE_
                                  = UCharacterCategory.CHAR_CATEGORY_COUNT + 2;
    /**
    * Extended category count
    */
    static final int EXTENDED_CATEGORY_
                                  = UCharacterCategory.CHAR_CATEGORY_COUNT + 3;

    // private constructor ------------------------------------------------

    /**
    * <p>Protected constructor for use in UCharacter.</p>
    * @exception IOException thrown when data reading fails
    */
    private UCharacterName() throws IOException
    {
		InputStream is = ICUData.getRequiredStream(NAME_FILE_NAME_);
        BufferedInputStream b = new BufferedInputStream(is, NAME_BUFFER_SIZE_);
        UCharacterNameReader reader = new UCharacterNameReader(b);
        reader.read(this);
        b.close();
    }

    // private methods ---------------------------------------------------

    /**
    * Gets the algorithmic name for the argument character
    * @param ch character to determine name for
    * @param choice name choice
    * @return the algorithmic name or null if not found
    */
    private String getAlgName(int ch, int choice)
    {
        // Do not write algorithmic Unicode 1.0 names because Unihan names are
        // the same as the modern ones, extension A was only introduced with
        // Unicode 3.0, and the Hangul syllable block was moved and changed
        // around Unicode 1.1.5.
        if (choice != UCharacterNameChoice.UNICODE_10_CHAR_NAME) {
            // index in terms integer index
            synchronized (m_utilStringBuffer_) {
                m_utilStringBuffer_.delete(0, m_utilStringBuffer_.length());

                for (int index = m_algorithm_.length - 1; index >= 0; index --)
                {
                   if (m_algorithm_[index].contains(ch)) {
                      m_algorithm_[index].appendName(ch, m_utilStringBuffer_);
                      return m_utilStringBuffer_.toString();
                   }
                }
            }
        }
        return null;
    }

    /**
    * Getting the character with the tokenized argument name
    * @param name of the character
    * @return character with the tokenized argument name or -1 if character
    *         is not found
    */
    private synchronized int getGroupChar(String name, int choice)
    {
        for (int i = 0; i < m_groupcount_; i ++) {
            // populating the data set of grouptable

            int startgpstrindex = getGroupLengths(i, m_groupoffsets_,
                                                  m_grouplengths_);

            // shift out to function
            int result = getGroupChar(startgpstrindex, m_grouplengths_, name,
                                      choice);
            if (result != -1) {
                return (m_groupinfo_[i * m_groupsize_] << GROUP_SHIFT_)
                         | result;
            }
        }
        return -1;
    }

    /**
    * Compares and retrieve character if name is found within the argument
    * group
    * @param index index where the set of names reside in the group block
    * @param length list of lengths of the strings
    * @param name character name to search for
    * @param choice of either 1.0 or the most current unicode name
    * @return relative character in the group which matches name, otherwise if
    *         not found, -1 will be returned
    */
    private int getGroupChar(int index, char length[], String name,
                             int choice)
    {
        byte b = 0;
        char token;
        int len;
        int namelen = name.length();
        int nindex;
        int count;

        for (int result = 0; result <= LINES_PER_GROUP_; result ++) {
            nindex = 0;
            len = length[result];

            if (choice == UCharacterNameChoice.UNICODE_10_CHAR_NAME) {
                int oldindex = index;
                index += UCharacterUtility.skipByteSubString(m_groupstring_,
                                                     index, len, (byte)';');
                len -= (index - oldindex);
            }

            // number of tokens is > the length of the name
            // write each letter directly, and write a token word per token
            for (count = 0; count < len && nindex != -1 && nindex < namelen;
                ) {
                b = m_groupstring_[index + count];
                count ++;

                if (b >= m_tokentable_.length) {
                    if (name.charAt(nindex ++) != (b & 0xFF)) {
                        nindex = -1;
                    }
                }
                else {
                    token = m_tokentable_[b & 0xFF];
                    if (token == 0xFFFE) {
                        // this is a lead byte for a double-byte token
                        token = m_tokentable_[b << 8 |
                                   (m_groupstring_[index + count] & 0x00ff)];
                        count ++;
                    }
                    if (token == 0xFFFF) {
                        if (name.charAt(nindex ++) != (b & 0xFF)) {
                            nindex = -1;
                        }
                    }
                    else {
                        // compare token with name
                        nindex = UCharacterUtility.compareNullTermByteSubString(
                                        name, m_tokenstring_, nindex, token);
                    }
                }
            }

            if (namelen == nindex &&
                (count == len || m_groupstring_[index + count] == ';')) {
                return result;
            }

            index += len;
        }
        return -1;
    }

    /**
    * Binary search for the group strings set that contains the argument Unicode
    * code point's most significant bits.
    * The return value is always a valid group string set that contain msb.
    * If group string set is not found, -1 is returned
    * @param ch the code point to look for
    * @return group string set index in datatable otherwise -1 is returned if
    *         group string set is not found
    */
    ///CLOVER:OFF
    private int getGroupStringIndex(int ch)
    {
        // gets the msb
        int msb = ch >> GROUP_SHIFT_,
            end = m_groupcount_,
            start,
            gindex = 0;

        // binary search for the group of names that contains the one for code
        for (start = 0; start < end - 1;) {
            gindex = (start + end) >> 1;
            if (msb < m_groupinfo_[gindex * m_groupsize_]) {
                end = gindex;
            }
            else {
                start = gindex;
            }
        }

        // return this if it is an exact match
        if (msb == m_groupinfo_[start * m_groupsize_]) {
            start = start * m_groupsize_;
            return UCharacterUtility.toInt(
                                m_groupinfo_[start + OFFSET_HIGH_OFFSET_],
                                m_groupinfo_[start + OFFSET_LOW_OFFSET_]);
        }
        return -1;
    }
    ///CLOVER:ON

    /**
    * Gets the character extended type
    * @param ch character to be tested
    * @return extended type it is associated with
    */
    private static int getType(int ch)
    {
        if (UCharacterUtility.isNonCharacter(ch)) {
            // not a character we return a invalid category count
            return NON_CHARACTER_;
        }
        int result = UCharacter.getType(ch);
        if (result == UCharacterCategory.SURROGATE) {
            if (ch <= UTF16.LEAD_SURROGATE_MAX_VALUE) {
                result = LEAD_SURROGATE_;
            }
            else {
                result = TRAIL_SURROGATE_;
            }
        }
        return result;
    }

    /**
    * Getting the character with extended name of the form <....>.
    * @param name of the character to be found
    * @param choice name choice
    * @return character associated with the name, -1 if such character is not
    *                   found and -2 if we should continue with the search.
    */
    private static int getExtendedChar(String name, int choice)
    {
        if (name.charAt(0) == '<') {
            if (choice == UCharacterNameChoice.EXTENDED_CHAR_NAME) {
                int endIndex = name.length() - 1;
                if (name.charAt(endIndex) == '>') {
                    int startIndex = name.lastIndexOf('-');
                    if (startIndex >= 0) { // We've got a category.
                        startIndex ++;
                        int result = -1;
                        try {
                            result = Integer.parseInt(
                                        name.substring(startIndex, endIndex),
                                        16);
                        }
                        catch (NumberFormatException e) {
                            return -1;
                        }
                        // Now validate the category name. We could use a
                        // binary search, or a trie, if we really wanted to.
                        String type = name.substring(1, startIndex - 1);
                        int length = TYPE_NAMES_.length;
                        for (int i = 0; i < length; ++ i) {
                            if (type.compareTo(TYPE_NAMES_[i]) == 0) {
                                if (getType(result) == i) {
                                    return result;
                                }
                                break;
                            }
                        }
                    }
                }
            }
            return -1;
        }
        return -2;
    }

    // sets of name characters, maximum name lengths -----------------------

    /**
     * Adds a codepoint into a set of ints.
     * Equivalent to SET_ADD.
     * @param set set to add to
     * @param ch 16 bit char to add
     */
    private static void add(int set[], char ch)
    {
        set[ch >>> 5] |= 1 << (ch & 0x1f);
    }

    /**
     * Checks if a codepoint is a part of a set of ints.
     * Equivalent to SET_CONTAINS.
     * @param set set to check in
     * @param ch 16 bit char to check
     * @return true if codepoint is part of the set, false otherwise
     */
    private static boolean contains(int set[], char ch)
    {
        return (set[ch >>> 5] & (1 << (ch & 0x1f))) != 0;
    }

    /**
     * Adds all characters of the argument str and gets the length
     * Equivalent to calcStringSetLength.
     * @param set set to add all chars of str to
     * @param str string to add
     */
    private static int add(int set[], String str)
    {
        int result = str.length();

        for (int i = result - 1; i >= 0; i --) {
            add(set, str.charAt(i));
        }
        return result;
    }

    /**
     * Adds all characters of the argument str and gets the length
     * Equivalent to calcStringSetLength.
     * @param set set to add all chars of str to
     * @param str string to add
     */
    private static int add(int set[], StringBuffer str)
    {
        int result = str.length();

        for (int i = result - 1; i >= 0; i --) {
            add(set, str.charAt(i));
        }
        return result;
    }

    /**
     * Adds all algorithmic names into the name set.
     * Equivalent to part of calcAlgNameSetsLengths.
     * @param maxlength length to compare to
     * @return the maximum length of any possible algorithmic name if it is >
     *         maxlength, otherwise maxlength is returned.
     */
    private int addAlgorithmName(int maxlength)
    {
        int result = 0;
        for (int i = m_algorithm_.length - 1; i >= 0; i --) {
            result = m_algorithm_[i].add(m_nameSet_, maxlength);
            if (result > maxlength) {
                maxlength = result;
            }
        }
        return maxlength;
    }

    /**
     * Adds all extended names into the name set.
     * Equivalent to part of calcExtNameSetsLengths.
     * @param maxlength length to compare to
     * @return the maxlength of any possible extended name.
     */
    private int addExtendedName(int maxlength)
    {
        for (int i = TYPE_NAMES_.length - 1; i >= 0; i --) {
            // for each category, count the length of the category name
            // plus 9 =
            // 2 for <>
            // 1 for -
            // 6 for most hex digits per code point
            int length = 9 + add(m_nameSet_, TYPE_NAMES_[i]);
            if (length > maxlength) {
                maxlength = length;
            }
        }
        return maxlength;
    }

    /**
     * Adds names of a group to the argument set.
     * Equivalent to calcNameSetLength.
     * @param offset of the group name string in byte count
     * @param length of the group name string
     * @param tokenlength array to store the length of each token
     * @param set to add to
     * @return the length of the name string and the length of the group
     *         string parsed
     */
    private int[] addGroupName(int offset, int length, byte tokenlength[],
                               int set[])
    {
        int resultnlength = 0;
        int resultplength = 0;
        while (resultplength < length) {
            char b = (char)(m_groupstring_[offset + resultplength] & 0xff);
            resultplength ++;
            if (b == ';') {
                break;
            }

            if (b >= m_tokentable_.length) {
                add(set, b); // implicit letter
                resultnlength ++;
            }
            else {
                char token = m_tokentable_[b & 0x00ff];
                if (token == 0xFFFE) {
                    // this is a lead byte for a double-byte token
                    b = (char)(b << 8 | (m_groupstring_[offset + resultplength]
                                         & 0x00ff));
                    token = m_tokentable_[b];
                    resultplength ++;
                }
                if (token == 0xFFFF) {
                    add(set, b);
                    resultnlength ++;
                }
                else {
                    // count token word
                    // use cached token length
                    byte tlength = tokenlength[b];
                    if (tlength == 0) {
                        synchronized (m_utilStringBuffer_) {
                            m_utilStringBuffer_.delete(0,
                                                 m_utilStringBuffer_.length());
                            UCharacterUtility.getNullTermByteSubString(
                                           m_utilStringBuffer_, m_tokenstring_,
                                           token);
                            tlength = (byte)add(set, m_utilStringBuffer_);
                        }
                        tokenlength[b] = tlength;
                    }
                    resultnlength += tlength;
                }
            }
        }
        m_utilIntBuffer_[0] = resultnlength;
        m_utilIntBuffer_[1] = resultplength;
        return m_utilIntBuffer_;
    }

    /**
     * Adds names of all group to the argument set.
     * Sets the data member m_max*Length_.
     * Method called only once.
     * Equivalent to calcGroupNameSetsLength.
     * @param maxlength length to compare to
     */
    private void addGroupName(int maxlength)
    {
        int maxisolength = 0;
        char offsets[] = new char[LINES_PER_GROUP_ + 2];
        char lengths[] = new char[LINES_PER_GROUP_ + 2];
        byte tokenlengths[] = new byte[m_tokentable_.length];

        // enumerate all groups
        // for (int i = m_groupcount_ - 1; i >= 0; i --) {
        for (int i = 0; i < m_groupcount_ ; i ++) {
            int offset = getGroupLengths(i, offsets, lengths);
            // enumerate all lines in each group
            // for (int linenumber = LINES_PER_GROUP_ - 1; linenumber >= 0;
            //    linenumber --) {
            for (int linenumber = 0; linenumber < LINES_PER_GROUP_;
                linenumber ++) {
                int lineoffset = offset + offsets[linenumber];
                int length = lengths[linenumber];
                if (length == 0) {
                    continue;
                }

                // read regular name
                int parsed[] = addGroupName(lineoffset, length, tokenlengths,
                                            m_nameSet_);
                if (parsed[0] > maxlength) {
                    // 0 for name length
                    maxlength = parsed[0];
                }
                lineoffset += parsed[1];
                if (parsed[1] >= length) {
                    // 1 for parsed group string length
                    continue;
                }
                length -= parsed[1];
                // read Unicode 1.0 name
                parsed = addGroupName(lineoffset, length, tokenlengths,
                                      m_nameSet_);
                if (parsed[0] > maxlength) {
                    // 0 for name length
                    maxlength = parsed[0];
                }
                lineoffset += parsed[1];
                if (parsed[1] >= length) {
                    // 1 for parsed group string length
                    continue;
                }
                length -= parsed[1];
                // read ISO comment
                parsed = addGroupName(lineoffset, length, tokenlengths,
                                      m_ISOCommentSet_);
                if (parsed[1] > maxisolength) {
                    maxisolength = length;
                }
            }
        }

        // set gMax... - name length last for threading
        m_maxISOCommentLength_ = maxisolength;
        m_maxNameLength_ = maxlength;
    }

    /**
     * Sets up the name sets and the calculation of the maximum lengths.
     * Equivalent to calcNameSetsLengths.
     */
    private boolean initNameSetsLengths()
    {
        if (m_maxNameLength_ > 0) {
            return true;
        }

        String extra = "0123456789ABCDEF<>-";
        // set hex digits, used in various names, and <>-, used in extended
        // names
        for (int i = extra.length() - 1; i >= 0; i --) {
            add(m_nameSet_, extra.charAt(i));
        }

        // set sets and lengths from algorithmic names
        m_maxNameLength_ = addAlgorithmName(0);
        // set sets and lengths from extended names
        m_maxNameLength_ = addExtendedName(m_maxNameLength_);
        // set sets and lengths from group names, set global maximum values
        addGroupName(m_maxNameLength_);
        return true;
    }

    /**
     * Converts the char set cset into a Unicode set uset.
     * Equivalent to charSetToUSet.
     * @param set Set of 256 bit flags corresponding to a set of chars.
     * @param uset USet to receive characters. Existing contents are deleted.
     */
    private void convert(int set[], UnicodeSet uset)
    {
        uset.clear();
        if (!initNameSetsLengths()) {
            return;
        }

        // build a char string with all chars that are used in character names
        for (char c = 255; c > 0; c --) {
            if (contains(set, c)) {
                uset.add(c);
            }
        }
    }
}
