Exemplo n.º 1
0
        /// <summary>
        /// Finds the next (string, value) pair if there is one.
        /// </summary>
        /// <remarks>
        /// If the string is truncated to the maximum length and does not
        /// have a real value, then the value is set to -1.
        /// In this case, this "not a real value" is indistinguishable from
        /// a real value of -1.
        /// </remarks>
        /// <returns>An <see cref="CharsTrieEntry"/> with the string and value of the next element.</returns>
        /// <stable>ICU 4.8</stable>
        private CharsTrieEntry Next()
        {
            int pos = pos_;

            if (pos < 0)
            {
                //if (stack_.isEmpty())
                //{
                //    throw new NoSuchElementException();
                //}
                // Pop the state off the stack and continue with the next outbound edge of
                // the branch node.
                long top = stack_[stack_.Count - 1];
                stack_.Remove(top);
                int length = (int)top;
                pos         = (int)(top >> 32);
                str_.Length = (length & 0xffff);
                length      = length.TripleShift(16);
                if (length > 1)
                {
                    pos = BranchNext(pos, length);
                    if (pos < 0)
                    {
                        return(entry_);  // Reached a final value.
                    }
                }
                else
                {
                    str_.Append(chars_[pos++]);
                }
            }
            if (remainingMatchLength_ >= 0)
            {
                // We only get here if we started in a pending linear-match node
                // with more than maxLength remaining units.
                return(TruncateAndStop());
            }
            for (; ;)
            {
                int node = chars_[pos++];
                if (node >= CharsTrie.kMinValueLead)
                {
                    if (skipValue_)
                    {
                        pos        = CharsTrie.SkipNodeValue(pos, node);
                        node      &= CharsTrie.kNodeTypeMask;
                        skipValue_ = false;
                    }
                    else
                    {
                        // Deliver value for the string so far.
                        bool isFinal = (node & CharsTrie.kValueIsFinal) != 0;
                        if (isFinal)
                        {
                            entry_.Value = CharsTrie.ReadValue(chars_, pos, node & 0x7fff);
                        }
                        else
                        {
                            entry_.Value = CharsTrie.ReadNodeValue(chars_, pos, node);
                        }
                        if (isFinal || (maxLength_ > 0 && str_.Length == maxLength_))
                        {
                            pos_ = -1;
                        }
                        else
                        {
                            // We cannot skip the value right here because it shares its
                            // lead unit with a match node which we have to evaluate
                            // next time.
                            // Instead, keep pos_ on the node lead unit itself.
                            pos_       = pos - 1;
                            skipValue_ = true;
                        }
                        entry_.Chars = str_.AsCharSequence();
                        return(entry_);
                    }
                }
                if (maxLength_ > 0 && str_.Length == maxLength_)
                {
                    return(TruncateAndStop());
                }
                if (node < CharsTrie.kMinLinearMatch)
                {
                    if (node == 0)
                    {
                        node = chars_[pos++];
                    }
                    pos = BranchNext(pos, node + 1);
                    if (pos < 0)
                    {
                        return(entry_);  // Reached a final value.
                    }
                }
                else
                {
                    // Linear-match node, append length units to str_.
                    int length = node - CharsTrie.kMinLinearMatch + 1;
                    if (maxLength_ > 0 && str_.Length + length > maxLength_)
                    {
                        str_.Append(chars_, pos, maxLength_ - str_.Length); // ICU4N: (pos + maxLength_ - str_.Length) - pos == (maxLength_ - str_.Length)
                        return(TruncateAndStop());
                    }
                    str_.Append(chars_, pos, length); // ICU4N: (pos + length) - pos == length
                    pos += length;
                }
            }
        }