/// <summary> /// Returns the single CE that c maps to. /// Throws <see cref="NotSupportedException"/> if <paramref name="c"/> does not map to a single CE. /// </summary> internal long GetSingleCE(int c) { CollationData d; int ce32 = GetCE32(c); if (ce32 == Collation.FALLBACK_CE32) { d = base_; ce32 = base_.GetCE32(c); } else { d = this; } while (Collation.IsSpecialCE32(ce32)) { switch (Collation.TagFromCE32(ce32)) { case Collation.LATIN_EXPANSION_TAG: case Collation.BUILDER_DATA_TAG: case Collation.PREFIX_TAG: case Collation.CONTRACTION_TAG: case Collation.HANGUL_TAG: case Collation.LEAD_SURROGATE_TAG: throw new NotSupportedException(string.Format( "there is not exactly one collation element for U+{0:X4} (CE32 0x{1:x8})", c, ce32)); case Collation.FALLBACK_TAG: case Collation.RESERVED_TAG_3: throw new InvalidOperationException(string.Format( "unexpected CE32 tag for U+{0:X4} (CE32 0x{1:x8})", c, ce32)); case Collation.LONG_PRIMARY_TAG: return(Collation.CeFromLongPrimaryCE32(ce32)); case Collation.LONG_SECONDARY_TAG: return(Collation.CeFromLongSecondaryCE32(ce32)); case Collation.EXPANSION32_TAG: if (Collation.LengthFromCE32(ce32) == 1) { ce32 = d.ce32s[Collation.IndexFromCE32(ce32)]; break; } else { throw new NotSupportedException(string.Format( "there is not exactly one collation element for U+{0:X4} (CE32 0x{1:x8})", c, ce32)); } case Collation.EXPANSION_TAG: { if (Collation.LengthFromCE32(ce32) == 1) { return(d.ces[Collation.IndexFromCE32(ce32)]); } else { throw new NotSupportedException(string.Format( "there is not exactly one collation element for U+{0:X4} (CE32 0x{1:x8})", c, ce32)); } } case Collation.DIGIT_TAG: // Fetch the non-numeric-collation CE32 and continue. ce32 = d.ce32s[Collation.IndexFromCE32(ce32)]; break; case Collation.U0000_TAG: Debug.Assert(c == 0); // Fetch the normal ce32 for U+0000 and continue. ce32 = d.ce32s[0]; break; case Collation.OFFSET_TAG: return(d.GetCEFromOffsetCE32(c, ce32)); case Collation.IMPLICIT_TAG: return(Collation.UnassignedCEFromCodePoint(c)); } } return(Collation.CeFromSimpleCE32(ce32)); }
private void HandleCE32(int start, int end, int ce32) { for (; ;) { if ((ce32 & 0xff) < Collation.SPECIAL_CE32_LOW_BYTE) { // !isSpecialCE32() if (sink != null) { sink.HandleCE(Collation.CeFromSimpleCE32(ce32)); } return; } switch (Collation.TagFromCE32(ce32)) { case Collation.FALLBACK_TAG: return; case Collation.RESERVED_TAG_3: case Collation.BUILDER_DATA_TAG: case Collation.LEAD_SURROGATE_TAG: // Java porting note: U_INTERNAL_PROGRAM_ERROR is set to errorCode in ICU4C. throw new InvalidOperationException( string.Format("Unexpected CE32 tag type {0} for ce32=0x{1:x8}", Collation.TagFromCE32(ce32), ce32)); case Collation.LONG_PRIMARY_TAG: if (sink != null) { sink.HandleCE(Collation.CeFromLongPrimaryCE32(ce32)); } return; case Collation.LONG_SECONDARY_TAG: if (sink != null) { sink.HandleCE(Collation.CeFromLongSecondaryCE32(ce32)); } return; case Collation.LATIN_EXPANSION_TAG: if (sink != null) { ces[0] = Collation.LatinCE0FromCE32(ce32); ces[1] = Collation.LatinCE1FromCE32(ce32); sink.HandleExpansion(ces, 0, 2); } // Optimization: If we have a prefix, // then the relevant strings have been added already. if (unreversedPrefix.Length == 0) { AddExpansions(start, end); } return; case Collation.EXPANSION32_TAG: if (sink != null) { int idx = Collation.IndexFromCE32(ce32); int length = Collation.LengthFromCE32(ce32); for (int i = 0; i < length; ++i) { ces[i] = Collation.CeFromCE32(data.ce32s[idx + i]); } sink.HandleExpansion(ces, 0, length); } // Optimization: If we have a prefix, // then the relevant strings have been added already. if (unreversedPrefix.Length == 0) { AddExpansions(start, end); } return; case Collation.EXPANSION_TAG: if (sink != null) { int idx = Collation.IndexFromCE32(ce32); int length = Collation.LengthFromCE32(ce32); sink.HandleExpansion(data.ces, idx, length); } // Optimization: If we have a prefix, // then the relevant strings have been added already. if (unreversedPrefix.Length == 0) { AddExpansions(start, end); } return; case Collation.PREFIX_TAG: HandlePrefixes(start, end, ce32); return; case Collation.CONTRACTION_TAG: HandleContractions(start, end, ce32); return; case Collation.DIGIT_TAG: // Fetch the non-numeric-collation CE32 and continue. ce32 = data.ce32s[Collation.IndexFromCE32(ce32)]; break; case Collation.U0000_TAG: Debug.Assert(start == 0 && end == 0); // Fetch the normal ce32 for U+0000 and continue. ce32 = data.ce32s[0]; break; case Collation.HANGUL_TAG: if (sink != null) { // TODO: This should be optimized, // especially if [start..end] is the complete Hangul range. (assert that) UTF16CollationIterator iter = new UTF16CollationIterator(data); StringBuilderCharSequence hangul = new StringBuilderCharSequence(new StringBuilder(1)); for (int c = start; c <= end; ++c) { hangul.StringBuilder.Length = 0; hangul.StringBuilder.AppendCodePoint(c); iter.SetText(false, hangul, 0); int length = iter.FetchCEs(); // Ignore the terminating non-CE. Debug.Assert(length >= 2 && iter.GetCE(length - 1) == Collation.NO_CE); sink.HandleExpansion(iter.GetCEs(), 0, length - 1); } } // Optimization: If we have a prefix, // then the relevant strings have been added already. if (unreversedPrefix.Length == 0) { AddExpansions(start, end); } return; case Collation.OFFSET_TAG: // Currently no need to send offset CEs to the sink. return; case Collation.IMPLICIT_TAG: // Currently no need to send implicit CEs to the sink. return; } } }