/// <summary> /// Get the previous collation element in the string. <para>This iterator iterates /// over a sequence of collation elements that were built from the string. /// Because there isn't necessarily a one-to-one mapping from characters to /// collation elements, this doesn't mean the same thing as "return the /// collation element [or ordering priority] of the previous character in the /// string".</p> /// </para> /// <para>This function updates the iterator's internal pointer to point to the /// collation element preceding the one it's currently pointing to and then /// returns that element, while next() returns the current element and then /// updates the pointer. This means that when you change direction while /// iterating (i.e., call next() and then call previous(), or call previous() /// and then call next()), you'll get back the same element twice.</para> /// </summary> /// <returns> the previous collation element /// @since 1.2 </returns> public int Previous() { if (Text_Renamed == null) { return(NULLORDER); } NormalizerBase.Mode textMode = Text_Renamed.Mode; // convert the owner's mode to something the Normalizer understands NormalizerBase.Mode ownerMode = CollatorUtilities.toNormalizerMode(Owner.Decomposition); if (textMode != ownerMode) { Text_Renamed.Mode = ownerMode; } if (Buffer != null) { if (ExpIndex > 0) { return(StrengthOrder(Buffer[--ExpIndex])); } else { Buffer = null; ExpIndex = 0; } } else if (SwapOrder != 0) { if (Character.IsSupplementaryCodePoint(SwapOrder)) { char[] chars = Character.ToChars(SwapOrder); SwapOrder = chars[1]; return(chars[0] << 16); } int order = SwapOrder << 16; SwapOrder = 0; return(order); } int ch = Text_Renamed.previous(); if (ch == NormalizerBase.DONE) { return(NULLORDER); } int value = Ordering.GetUnicodeOrder(ch); if (value == RuleBasedCollator.UNMAPPED) { SwapOrder = UNMAPPEDCHARVALUE; return(ch); } else if (value >= RuleBasedCollator.CONTRACTCHARINDEX) { value = PrevContractChar(ch); } if (value >= RuleBasedCollator.EXPANDCHARINDEX) { Buffer = Ordering.GetExpandValueList(value); ExpIndex = Buffer.Length; value = Buffer[--ExpIndex]; } if (Ordering.SEAsianSwapping) { int vowel; if (IsThaiBaseConsonant(ch)) { vowel = Text_Renamed.previous(); if (IsThaiPreVowel(vowel)) { Buffer = MakeReorderedBuffer(vowel, value, Buffer, false); ExpIndex = Buffer.Length - 1; value = Buffer[ExpIndex]; } else { Text_Renamed.next(); } } if (IsLaoBaseConsonant(ch)) { vowel = Text_Renamed.previous(); if (IsLaoPreVowel(vowel)) { Buffer = MakeReorderedBuffer(vowel, value, Buffer, false); ExpIndex = Buffer.Length - 1; value = Buffer[ExpIndex]; } else { Text_Renamed.next(); } } } return(StrengthOrder(value)); }
/// <summary> /// Get the ordering priority of the next contracting character in the /// string. </summary> /// <param name="ch"> the starting character of a contracting character token </param> /// <returns> the next contracting character's ordering. Returns NULLORDER /// if the end of string is reached. </returns> private int NextContractChar(int ch) { // First get the ordering of this single character, // which is always the first element in the list List <EntryPair> list = Ordering.GetContractValues(ch); EntryPair pair = list[0]; int order = pair.Value; // find out the length of the longest contracting character sequence in the list. // There's logic in the builder code to make sure the longest sequence is always // the last. pair = list[list.Count - 1]; int maxLength = pair.EntryName.Length(); // (the Normalizer is cloned here so that the seeking we do in the next loop // won't affect our real position in the text) NormalizerBase tempText = (NormalizerBase)Text_Renamed.clone(); // extract the next maxLength characters in the string (we have to do this using the // Normalizer to ensure that our offsets correspond to those the rest of the // iterator is using) and store it in "fragment". tempText.previous(); Key.Length = 0; int c = tempText.next(); while (maxLength > 0 && c != NormalizerBase.DONE) { if (Character.IsSupplementaryCodePoint(c)) { Key.Append(Character.ToChars(c)); maxLength -= 2; } else { Key.Append((char)c); --maxLength; } c = tempText.next(); } String fragment = Key.ToString(); // now that we have that fragment, iterate through this list looking for the // longest sequence that matches the characters in the actual text. (maxLength // is used here to keep track of the length of the longest sequence) // Upon exit from this loop, maxLength will contain the length of the matching // sequence and order will contain the collation-element value corresponding // to this sequence maxLength = 1; for (int i = list.Count - 1; i > 0; i--) { pair = list[i]; if (!pair.Fwd) { continue; } if (fragment.StartsWith(pair.EntryName) && pair.EntryName.Length() > maxLength) { maxLength = pair.EntryName.Length(); order = pair.Value; } } // seek our current iteration position to the end of the matching sequence // and return the appropriate collation-element value (if there was no matching // sequence, we're already seeked to the right position and order already contains // the correct collation-element value for the single character) while (maxLength > 1) { c = Text_Renamed.next(); maxLength -= Character.CharCount(c); } return(order); }
/// <summary> /// Get the next collation element in the string. <para>This iterator iterates /// over a sequence of collation elements that were built from the string. /// Because there isn't necessarily a one-to-one mapping from characters to /// collation elements, this doesn't mean the same thing as "return the /// collation element [or ordering priority] of the next character in the /// string".</p> /// </para> /// <para>This function returns the collation element that the iterator is currently /// pointing to and then updates the internal pointer to point to the next element. /// previous() updates the pointer first and then returns the element. This /// means that when you change direction while iterating (i.e., call next() and /// then call previous(), or call previous() and then call next()), you'll get /// back the same element twice.</para> /// </summary> /// <returns> the next collation element </returns> public int Next() { if (Text_Renamed == null) { return(NULLORDER); } NormalizerBase.Mode textMode = Text_Renamed.Mode; // convert the owner's mode to something the Normalizer understands NormalizerBase.Mode ownerMode = CollatorUtilities.toNormalizerMode(Owner.Decomposition); if (textMode != ownerMode) { Text_Renamed.Mode = ownerMode; } // if buffer contains any decomposed char values // return their strength orders before continuing in // the Normalizer's CharacterIterator. if (Buffer != null) { if (ExpIndex < Buffer.Length) { return(StrengthOrder(Buffer[ExpIndex++])); } else { Buffer = null; ExpIndex = 0; } } else if (SwapOrder != 0) { if (Character.IsSupplementaryCodePoint(SwapOrder)) { char[] chars = Character.ToChars(SwapOrder); SwapOrder = chars[1]; return(chars[0] << 16); } int order = SwapOrder << 16; SwapOrder = 0; return(order); } int ch = Text_Renamed.next(); // are we at the end of Normalizer's text? if (ch == NormalizerBase.DONE) { return(NULLORDER); } int value = Ordering.GetUnicodeOrder(ch); if (value == RuleBasedCollator.UNMAPPED) { SwapOrder = ch; return(UNMAPPEDCHARVALUE); } else if (value >= RuleBasedCollator.CONTRACTCHARINDEX) { value = NextContractChar(ch); } if (value >= RuleBasedCollator.EXPANDCHARINDEX) { Buffer = Ordering.GetExpandValueList(value); ExpIndex = 0; value = Buffer[ExpIndex++]; } if (Ordering.SEAsianSwapping) { int consonant; if (IsThaiPreVowel(ch)) { consonant = Text_Renamed.next(); if (IsThaiBaseConsonant(consonant)) { Buffer = MakeReorderedBuffer(consonant, value, Buffer, true); value = Buffer[0]; ExpIndex = 1; } else if (consonant != NormalizerBase.DONE) { Text_Renamed.previous(); } } if (IsLaoPreVowel(ch)) { consonant = Text_Renamed.next(); if (IsLaoBaseConsonant(consonant)) { Buffer = MakeReorderedBuffer(consonant, value, Buffer, true); value = Buffer[0]; ExpIndex = 1; } else if (consonant != NormalizerBase.DONE) { Text_Renamed.previous(); } } } return(StrengthOrder(value)); }