/// <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; } } }