private void checkIterator(CharsTrieEnumerator iter, StringAndValue[] data, int dataLength) { for (int i = 0; i < dataLength; ++i) { if (!iter.MoveNext()) { Errln("trie iterator hasNext()=false for item " + i + ": " + data[i].s); break; } CharsTrieEntry entry = iter.Current; String expectedString = data[i].s; if (!expectedString.ContentEquals(entry.Chars)) { Errln(String.Format("trie iterator next().getString()={0} but expected {1} for item {2}", entry.Chars, data[i].s, i)); } if (entry.Value != data[i].value) { Errln(String.Format("trie iterator next().getValue()={0}=0x{1:x} but expected {2}=0x{3:x} for item {4}: {5}", entry.Value, entry.Value, data[i].value, data[i].value, i, data[i].s)); } } if (iter.MoveNext()) { Errln("trie iterator hasNext()=true after all items"); } //try // ICU4N specific - not applicable in .NET //{ // iter.Next(); // Errln("trie iterator next() did not throw NoSuchElementException after all items"); //} //catch (NoSuchElementException e) //{ // // good //} }
private bool GetCEsFromContractionCE32(CollationData data, int ce32) { int trieIndex = Collation.IndexFromCE32(ce32); ce32 = data.GetCE32FromContexts(trieIndex); // Default if no suffix match. // Since the original ce32 is not a prefix mapping, // the default ce32 must not be another contraction. Debug.Assert(!Collation.IsContractionCE32(ce32)); int contractionIndex = contractionCEs.Count; if (GetCEsFromCE32(data, Collation.SentinelCodePoint, ce32)) { AddContractionEntry(CollationFastLatin.CONTR_CHAR_MASK, ce0, ce1); } else { // Bail out for c-without-contraction. AddContractionEntry(CollationFastLatin.CONTR_CHAR_MASK, Collation.NoCE, 0); } // Handle an encodable contraction unless the next contraction is too long // and starts with the same character. int prevX = -1; bool addContraction = false; using (CharsTrieEnumerator suffixes = CharsTrie.GetEnumerator(data.contexts, trieIndex + 2, 0)) { while (suffixes.MoveNext()) { CharsTrieEntry entry = suffixes.Current; ICharSequence suffix = entry.Chars; int x = CollationFastLatin.GetCharIndex(suffix[0]); if (x < 0) { continue; } // ignore anything but fast Latin text if (x == prevX) { if (addContraction) { // Bail out for all contractions starting with this character. AddContractionEntry(x, Collation.NoCE, 0); addContraction = false; } continue; } if (addContraction) { AddContractionEntry(prevX, ce0, ce1); } ce32 = entry.Value; if (suffix.Length == 1 && GetCEsFromCE32(data, Collation.SentinelCodePoint, ce32)) { addContraction = true; } else { AddContractionEntry(x, Collation.NoCE, 0); addContraction = false; } prevX = x; } } if (addContraction) { AddContractionEntry(prevX, ce0, ce1); } // Note: There might not be any fast Latin contractions, but // we need to enter contraction handling anyway so that we can bail out // when there is a non-fast-Latin character following. // For example: Danish &Y<<u+umlaut, when we compare Y vs. u\u0308 we need to see the // following umlaut and bail out, rather than return the difference of Y vs. u. ce0 = (Collation.NO_CE_PRIMARY << 32) | CONTRACTION_FLAG | (uint)contractionIndex; ce1 = 0; return(true); }
private void CompareContractions(int c, string p, int pidx, string q, int qidx) // ICU4N specific - changed p and q from ICharSequence to string { // Parallel iteration over suffixes of both tables. using (CharsTrieEnumerator suffixes = new CharsTrie(p, pidx).GetEnumerator()) using (CharsTrieEnumerator baseSuffixes = new CharsTrie(q, qidx).GetEnumerator()) { string ts = null; // Tailoring suffix. string bs = null; // Base suffix. // Use a string with two U+FFFF as the limit sentinel. // U+FFFF is untailorable and will not occur in contractions except maybe // as a single suffix character for a root-collator boundary contraction. string none = "\uffff\uffff"; CharsTrieEntry te = null, be = null; for (; ;) { if (ts == null) { if (suffixes.MoveNext()) { te = suffixes.Current; ts = te.Chars.ToString(); } else { te = null; ts = none; } } if (bs == null) { if (baseSuffixes.MoveNext()) { be = baseSuffixes.Current; bs = be.Chars.ToString(); } else { be = null; bs = none; } } if (Utility.SameObjects(ts, none) && Utility.SameObjects(bs, none)) { break; } int cmp = ts.CompareToOrdinal(bs); if (cmp < 0) { // ts occurs in the tailoring but not in the base. AddSuffix(c, ts); te = null; ts = null; } else if (cmp > 0) { // bs occurs in the base but not in the tailoring. AddSuffix(c, bs); be = null; bs = null; } else { suffix = ts; Compare(c, te.Value, be.Value); suffix = null; te = be = null; ts = bs = null; } } } }
private void ComparePrefixes(int c, string p, int pidx, string q, int qidx) // ICU4N specific - changed p and q from ICharSequence to string { // Parallel iteration over prefixes of both tables. using (CharsTrieEnumerator prefixes = new CharsTrie(p, pidx).GetEnumerator()) using (CharsTrieEnumerator basePrefixes = new CharsTrie(q, qidx).GetEnumerator()) { string tp = null; // Tailoring prefix. string bp = null; // Base prefix. // Use a string with a U+FFFF as the limit sentinel. // U+FFFF is untailorable and will not occur in prefixes. string none = "\uffff"; CharsTrieEntry te = null, be = null; for (; ;) { if (tp == null) { if (prefixes.MoveNext()) { te = prefixes.Current; tp = te.Chars.ToString(); } else { te = null; tp = none; } } if (bp == null) { if (basePrefixes.MoveNext()) { be = basePrefixes.Current; bp = be.Chars.ToString(); } else { be = null; bp = none; } } if (Utility.SameObjects(tp, none) && Utility.SameObjects(bp, none)) { break; } int cmp = tp.CompareToOrdinal(bp); if (cmp < 0) { // tp occurs in the tailoring but not in the base. Debug.Assert(te != null); AddPrefix(data, tp, c, te.Value); te = null; tp = null; } else if (cmp > 0) { // bp occurs in the base but not in the tailoring. Debug.Assert(be != null); AddPrefix(baseData, bp, c, be.Value); be = null; bp = null; } else { SetPrefix(tp); Debug.Assert(te != null && be != null); Compare(c, te.Value, be.Value); ResetPrefix(); te = be = null; tp = bp = null; } } } }