17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert******************************************************************************
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* Copyright (C) 1996-2011, International Business Machines Corporation and   *
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* others. All Rights Reserved.                                               *
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert******************************************************************************
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*/
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.lang;
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.UCharacterName;
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.UCharacterNameChoice;
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ValueIterator;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Class enabling iteration of the codepoints and their names.</p>
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Result of each iteration contains a valid codepoint that has valid
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * name.</p>
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>See UCharacter.getNameIterator() for an example of use.</p>
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author synwee
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @since release 2.1, March 5 2002
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertclass UCharacterNameIterator implements ValueIterator
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert{
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // public methods ----------------------------------------------------
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * <p>Gets the next result for this iteration and returns
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * true if we are not at the end of the iteration, false otherwise.</p>
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * <p>If the return boolean is a false, the contents of elements will not
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * be updated.</p>
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @param element for storing the result codepoint and name
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @return true if we are not at the end of the iteration, false otherwise.
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @see com.ibm.icu.util.ValueIterator.Element
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean next(ValueIterator.Element element)
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (m_current_ >= m_limit_) {
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return false;
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (m_choice_ == UCharacterNameChoice.UNICODE_CHAR_NAME ||
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            m_choice_ == UCharacterNameChoice.EXTENDED_CHAR_NAME
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ) {
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int length = m_name_.getAlgorithmLength();
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (m_algorithmIndex_ < length) {
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                while (m_algorithmIndex_ < length) {
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // find the algorithm range that could contain m_current_
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (m_algorithmIndex_ < 0 ||
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        m_name_.getAlgorithmEnd(m_algorithmIndex_) <
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        m_current_) {
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        m_algorithmIndex_ ++;
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    else {
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (m_algorithmIndex_ < length) {
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // interleave the data-driven ones with the algorithmic ones
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // iterate over all algorithmic ranges; assume that they are
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // in ascending order
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    int start = m_name_.getAlgorithmStart(m_algorithmIndex_);
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (m_current_ < start) {
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // this should get rid of those codepoints that are not
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // in the algorithmic range
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        int end = start;
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (m_limit_ <= start) {
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            end = m_limit_;
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (!iterateGroup(element, end)) {
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            m_current_ ++;
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            return true;
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /*
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // "if (m_current_ >= m_limit_)" would not return true
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // because it can never be reached due to:
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // 1) It has already been checked earlier
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // 2) When m_current_ is updated earlier, it returns true
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // 3) No updates on m_limit_*/
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (m_current_ >= m_limit_) {
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // after iterateGroup fails, current codepoint may be
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        // greater than limit
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        return false;
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    element.integer = m_current_;
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    element.value   = m_name_.getAlgorithmName(m_algorithmIndex_,
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                                                   m_current_);
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // reset the group index if we are in the algorithmic names
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    m_groupIndex_ = -1;
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    m_current_ ++;
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return true;
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // enumerate the character names after the last algorithmic range
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!iterateGroup(element, m_limit_)) {
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            m_current_ ++;
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return true;
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        else if (m_choice_ == UCharacterNameChoice.EXTENDED_CHAR_NAME) {
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!iterateExtended(element, m_limit_)) {
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                m_current_ ++;
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return true;
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return false;
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * <p>Resets the iterator to start iterating from the integer index
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * UCharacter.MIN_VALUE or X if a setRange(X, Y) has been called previously.
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * </p>
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void reset()
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_current_        = m_start_;
1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_groupIndex_     = -1;
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_algorithmIndex_ = -1;
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>Restricts the range of integers to iterate and resets the iteration
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * to begin at the index argument start.</p>
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>If setRange(start, end) is not performed before next(element) is
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * called, the iteration will start from the integer index
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * UCharacter.MIN_VALUE and end at UCharacter.MAX_VALUE.</p>
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <p>
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * If this range is set outside the range of UCharacter.MIN_VALUE and
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * UCharacter.MAX_VALUE, next(element) will always return false.
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * </p>
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param start first integer in range to iterate
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param limit 1 integer after the last integer in range
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @exception IllegalArgumentException thrown when attempting to set an
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *            illegal range. E.g limit <= start
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public void setRange(int start, int limit)
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (start >= limit) {
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalArgumentException(
1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                "start or limit has to be valid Unicode codepoints and start < limit");
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (start < UCharacter.MIN_VALUE) {
1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            m_start_ = UCharacter.MIN_VALUE;
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        else {
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            m_start_ = start;
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (limit > UCharacter.MAX_VALUE + 1) {
1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            m_limit_ = UCharacter.MAX_VALUE + 1;
1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        else {
1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            m_limit_ = limit;
1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_current_ = m_start_;
1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // protected constructor ---------------------------------------------
1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * Constructor
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @param name name data
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * @param choice name choice from the class
1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    *               com.ibm.icu.lang.UCharacterNameChoice
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected UCharacterNameIterator(UCharacterName name, int choice)
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if(name==null){
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new IllegalArgumentException("UCharacterName name argument cannot be null. Missing unames.icu?");
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_name_    = name;
1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // no explicit choice in UCharacter so no checks on choice
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_choice_  = choice;
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_start_   = UCharacter.MIN_VALUE;
1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_limit_   = UCharacter.MAX_VALUE + 1;
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        m_current_ = m_start_;
1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // private data members ---------------------------------------------
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Name data
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private UCharacterName m_name_;
1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Name choice
1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int m_choice_;
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     /**
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Start iteration range
1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int m_start_;
1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * End + 1 iteration range
1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int m_limit_;
2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Current codepoint
2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int m_current_;
2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Group index
2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int m_groupIndex_ = -1;
2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Algorithm index
2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int m_algorithmIndex_ = -1;
2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    * Group use
2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    */
2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static char GROUP_OFFSETS_[] =
2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                new char[UCharacterName.LINES_PER_GROUP_ + 1];
2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static char GROUP_LENGTHS_[] =
2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                new char[UCharacterName.LINES_PER_GROUP_ + 1];
2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // private methods --------------------------------------------------
2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Group name iteration, iterate all the names in the current 32-group and
2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * returns the first codepoint that has a valid name.
2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param result stores the result codepoint and name
2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param limit last codepoint + 1 in range to search
2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return false if a codepoint with a name is found in group and we can
2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *         bail from further iteration, true to continue on with the
2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *         iteration
2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private boolean iterateSingleGroup(ValueIterator.Element result, int limit)
2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        synchronized(GROUP_OFFSETS_) {
2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        synchronized(GROUP_LENGTHS_) {
2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int index = m_name_.getGroupLengths(m_groupIndex_, GROUP_OFFSETS_,
2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                                GROUP_LENGTHS_);
2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            while (m_current_ < limit) {
2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int    offset = UCharacterName.getGroupOffset(m_current_);
2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                String name   = m_name_.getGroupName(
2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                          index + GROUP_OFFSETS_[offset],
2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                          GROUP_LENGTHS_[offset], m_choice_);
2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if ((name == null || name.length() == 0) &&
2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    m_choice_ == UCharacterNameChoice.EXTENDED_CHAR_NAME) {
2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    name = m_name_.getExtendedName(m_current_);
2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (name != null && name.length() > 0) {
2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.integer = m_current_;
2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    result.value   = name;
2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return false;
2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ++ m_current_;
2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return true;
2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Group name iteration, iterate all the names in the current 32-group and
2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * returns the first codepoint that has a valid name.
2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param result stores the result codepoint and name
2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param limit last codepoint + 1 in range to search
2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return false if a codepoint with a name is found in group and we can
2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *         bail from further iteration, true to continue on with the
2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *         iteration
2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private boolean iterateGroup(ValueIterator.Element result, int limit)
2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (m_groupIndex_ < 0) {
2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            m_groupIndex_ = m_name_.getGroup(m_current_);
2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (m_groupIndex_ < m_name_.m_groupcount_ &&
2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert               m_current_ < limit) {
2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            // iterate till the last group or the last codepoint
2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int startMSB = UCharacterName.getCodepointMSB(m_current_);
2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int gMSB     = m_name_.getGroupMSB(m_groupIndex_); // can be -1
2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (startMSB == gMSB) {
2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (startMSB == UCharacterName.getCodepointMSB(limit - 1)) {
2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // if start and limit - 1 are in the same group, then enumerate
2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // only in that one
2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return iterateSingleGroup(result, limit);
2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // enumerate characters in the partial start group
2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // if (m_name_.getGroupOffset(m_current_) != 0) {
2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (!iterateSingleGroup(result,
2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        UCharacterName.getGroupLimit(gMSB))) {
2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return false;
2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ++ m_groupIndex_; // continue with the next group
2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            else if (startMSB > gMSB) {
2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // make sure that we start enumerating with the first group
2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    // after start
2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    m_groupIndex_ ++;
2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            else {
2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int gMIN = UCharacterName.getGroupMin(gMSB);
2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (gMIN > limit) {
3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    gMIN = limit;
3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (m_choice_ == UCharacterNameChoice.EXTENDED_CHAR_NAME) {
3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (!iterateExtended(result, gMIN)) {
3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        return false;
3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                m_current_ = gMIN;
3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return true;
3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Iterate extended names.
3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param result stores the result codepoint and name
3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param limit last codepoint + 1 in range to search
3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return false if a codepoint with a name is found and we can
3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *         bail from further iteration, true to continue on with the
3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *         iteration (this will always be false for valid codepoints)
3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private boolean iterateExtended(ValueIterator.Element result,
3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    int limit)
3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    {
3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (m_current_ < limit) {
3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            String name = m_name_.getExtendedOr10Name(m_current_);
3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (name != null && name.length() > 0) {
3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.integer = m_current_;
3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                result.value   = name;
3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return false;
3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ++ m_current_;
3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return true;
3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
337