// Copyright (C) 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
* Copyright (C) 2010-2014, International Business Machines
* Corporation and others.  All Rights Reserved.
*******************************************************************************
* collationiterator.cpp
*
* created on: 2010oct27
* created by: Markus W. Scherer
*/

#include "utypeinfo.h"  // for 'typeid' to work

#include "unicode/utypes.h"

#if !UCONFIG_NO_COLLATION

#include "unicode/ucharstrie.h"
#include "unicode/ustringtrie.h"
#include "charstr.h"
#include "cmemory.h"
#include "collation.h"
#include "collationdata.h"
#include "collationfcd.h"
#include "collationiterator.h"
#include "normalizer2impl.h"
#include "uassert.h"
#include "uvectr32.h"

U_NAMESPACE_BEGIN

CollationIterator::CEBuffer::~CEBuffer() {}

UBool
CollationIterator::CEBuffer::ensureAppendCapacity(int32_t appCap, UErrorCode &errorCode) {
    int32_t capacity = buffer.getCapacity();
    if((length + appCap) <= capacity) { return TRUE; }
    if(U_FAILURE(errorCode)) { return FALSE; }
    do {
        if(capacity < 1000) {
            capacity *= 4;
        } else {
            capacity *= 2;
        }
    } while(capacity < (length + appCap));
    int64_t *p = buffer.resize(capacity, length);
    if(p == NULL) {
        errorCode = U_MEMORY_ALLOCATION_ERROR;
        return FALSE;
    }
    return TRUE;
}

// State of combining marks skipped in discontiguous contraction.
// We create a state object on first use and keep it around deactivated between uses.
class SkippedState : public UMemory {
public:
    // Born active but empty.
    SkippedState() : pos(0), skipLengthAtMatch(0) {}
    void clear() {
        oldBuffer.remove();
        pos = 0;
        // The newBuffer is reset by setFirstSkipped().
    }

    UBool isEmpty() const { return oldBuffer.isEmpty(); }

    UBool hasNext() const { return pos < oldBuffer.length(); }

    // Requires hasNext().
    UChar32 next() {
        UChar32 c = oldBuffer.char32At(pos);
        pos += U16_LENGTH(c);
        return c;
    }

    // Accounts for one more input code point read beyond the end of the marks buffer.
    void incBeyond() {
        U_ASSERT(!hasNext());
        ++pos;
    }

    // Goes backward through the skipped-marks buffer.
    // Returns the number of code points read beyond the skipped marks
    // that need to be backtracked through normal input.
    int32_t backwardNumCodePoints(int32_t n) {
        int32_t length = oldBuffer.length();
        int32_t beyond = pos - length;
        if(beyond > 0) {
            if(beyond >= n) {
                // Not back far enough to re-enter the oldBuffer.
                pos -= n;
                return n;
            } else {
                // Back out all beyond-oldBuffer code points and re-enter the buffer.
                pos = oldBuffer.moveIndex32(length, beyond - n);
                return beyond;
            }
        } else {
            // Go backwards from inside the oldBuffer.
            pos = oldBuffer.moveIndex32(pos, -n);
            return 0;
        }
    }

    void setFirstSkipped(UChar32 c) {
        skipLengthAtMatch = 0;
        newBuffer.setTo(c);
    }

    void skip(UChar32 c) {
        newBuffer.append(c);
    }

    void recordMatch() { skipLengthAtMatch = newBuffer.length(); }

    // Replaces the characters we consumed with the newly skipped ones.
    void replaceMatch() {
        // Note: UnicodeString.replace() pins pos to at most length().
        oldBuffer.replace(0, pos, newBuffer, 0, skipLengthAtMatch);
        pos = 0;
    }

    void saveTrieState(const UCharsTrie &trie) { trie.saveState(state); }
    void resetToTrieState(UCharsTrie &trie) const { trie.resetToState(state); }

private:
    // Combining marks skipped in previous discontiguous-contraction matching.
    // After that discontiguous contraction was completed, we start reading them from here.
    UnicodeString oldBuffer;
    // Combining marks newly skipped in current discontiguous-contraction matching.
    // These might have been read from the normal text or from the oldBuffer.
    UnicodeString newBuffer;
    // Reading index in oldBuffer,
    // or counter for how many code points have been read beyond oldBuffer (pos-oldBuffer.length()).
    int32_t pos;
    // newBuffer.length() at the time of the last matching character.
    // When a partial match fails, we back out skipped and partial-matching input characters.
    int32_t skipLengthAtMatch;
    // We save the trie state before we attempt to match a character,
    // so that we can skip it and try the next one.
    UCharsTrie::State state;
};

CollationIterator::CollationIterator(const CollationIterator &other)
        : UObject(other),
          trie(other.trie),
          data(other.data),
          cesIndex(other.cesIndex),
          skipped(NULL),
          numCpFwd(other.numCpFwd),
          isNumeric(other.isNumeric) {
    UErrorCode errorCode = U_ZERO_ERROR;
    int32_t length = other.ceBuffer.length;
    if(length > 0 && ceBuffer.ensureAppendCapacity(length, errorCode)) {
        for(int32_t i = 0; i < length; ++i) {
            ceBuffer.set(i, other.ceBuffer.get(i));
        }
        ceBuffer.length = length;
    } else {
        cesIndex = 0;
    }
}

CollationIterator::~CollationIterator() {
    delete skipped;
}

UBool
CollationIterator::operator==(const CollationIterator &other) const {
    // Subclasses: Call this method and then add more specific checks.
    // Compare the iterator state but not the collation data (trie & data fields):
    // Assume that the caller compares the data.
    // Ignore skipped since that should be unused between calls to nextCE().
    // (It only stays around to avoid another memory allocation.)
    if(!(typeid(*this) == typeid(other) &&
            ceBuffer.length == other.ceBuffer.length &&
            cesIndex == other.cesIndex &&
            numCpFwd == other.numCpFwd &&
            isNumeric == other.isNumeric)) {
        return FALSE;
    }
    for(int32_t i = 0; i < ceBuffer.length; ++i) {
        if(ceBuffer.get(i) != other.ceBuffer.get(i)) { return FALSE; }
    }
    return TRUE;
}

void
CollationIterator::reset() {
    cesIndex = ceBuffer.length = 0;
    if(skipped != NULL) { skipped->clear(); }
}

int32_t
CollationIterator::fetchCEs(UErrorCode &errorCode) {
    while(U_SUCCESS(errorCode) && nextCE(errorCode) != Collation::NO_CE) {
        // No need to loop for each expansion CE.
        cesIndex = ceBuffer.length;
    }
    return ceBuffer.length;
}

uint32_t
CollationIterator::handleNextCE32(UChar32 &c, UErrorCode &errorCode) {
    c = nextCodePoint(errorCode);
    return (c < 0) ? Collation::FALLBACK_CE32 : data->getCE32(c);
}

UChar
CollationIterator::handleGetTrailSurrogate() {
    return 0;
}

UBool
CollationIterator::foundNULTerminator() {
    return FALSE;
}

UBool
CollationIterator::forbidSurrogateCodePoints() const {
    return FALSE;
}

uint32_t
CollationIterator::getDataCE32(UChar32 c) const {
    return data->getCE32(c);
}

uint32_t
CollationIterator::getCE32FromBuilderData(uint32_t /*ce32*/, UErrorCode &errorCode) {
    if(U_SUCCESS(errorCode)) { errorCode = U_INTERNAL_PROGRAM_ERROR; }
    return 0;
}

int64_t
CollationIterator::nextCEFromCE32(const CollationData *d, UChar32 c, uint32_t ce32,
                                  UErrorCode &errorCode) {
    --ceBuffer.length;  // Undo ceBuffer.incLength().
    appendCEsFromCE32(d, c, ce32, TRUE, errorCode);
    if(U_SUCCESS(errorCode)) {
        return ceBuffer.get(cesIndex++);
    } else {
        return Collation::NO_CE_PRIMARY;
    }
}

void
CollationIterator::appendCEsFromCE32(const CollationData *d, UChar32 c, uint32_t ce32,
                                     UBool forward, UErrorCode &errorCode) {
    while(Collation::isSpecialCE32(ce32)) {
        switch(Collation::tagFromCE32(ce32)) {
        case Collation::FALLBACK_TAG:
        case Collation::RESERVED_TAG_3:
            if(U_SUCCESS(errorCode)) { errorCode = U_INTERNAL_PROGRAM_ERROR; }
            return;
        case Collation::LONG_PRIMARY_TAG:
            ceBuffer.append(Collation::ceFromLongPrimaryCE32(ce32), errorCode);
            return;
        case Collation::LONG_SECONDARY_TAG:
            ceBuffer.append(Collation::ceFromLongSecondaryCE32(ce32), errorCode);
            return;
        case Collation::LATIN_EXPANSION_TAG:
            if(ceBuffer.ensureAppendCapacity(2, errorCode)) {
                ceBuffer.set(ceBuffer.length, Collation::latinCE0FromCE32(ce32));
                ceBuffer.set(ceBuffer.length + 1, Collation::latinCE1FromCE32(ce32));
                ceBuffer.length += 2;
            }
            return;
        case Collation::EXPANSION32_TAG: {
            const uint32_t *ce32s = d->ce32s + Collation::indexFromCE32(ce32);
            int32_t length = Collation::lengthFromCE32(ce32);
            if(ceBuffer.ensureAppendCapacity(length, errorCode)) {
                do {
                    ceBuffer.appendUnsafe(Collation::ceFromCE32(*ce32s++));
                } while(--length > 0);
            }
            return;
        }
        case Collation::EXPANSION_TAG: {
            const int64_t *ces = d->ces + Collation::indexFromCE32(ce32);
            int32_t length = Collation::lengthFromCE32(ce32);
            if(ceBuffer.ensureAppendCapacity(length, errorCode)) {
                do {
                    ceBuffer.appendUnsafe(*ces++);
                } while(--length > 0);
            }
            return;
        }
        case Collation::BUILDER_DATA_TAG:
            ce32 = getCE32FromBuilderData(ce32, errorCode);
            if(U_FAILURE(errorCode)) { return; }
            if(ce32 == Collation::FALLBACK_CE32) {
                d = data->base;
                ce32 = d->getCE32(c);
            }
            break;
        case Collation::PREFIX_TAG:
            if(forward) { backwardNumCodePoints(1, errorCode); }
            ce32 = getCE32FromPrefix(d, ce32, errorCode);
            if(forward) { forwardNumCodePoints(1, errorCode); }
            break;
        case Collation::CONTRACTION_TAG: {
            const UChar *p = d->contexts + Collation::indexFromCE32(ce32);
            uint32_t defaultCE32 = CollationData::readCE32(p);  // Default if no suffix match.
            if(!forward) {
                // Backward contractions are handled by previousCEUnsafe().
                // c has contractions but they were not found.
                ce32 = defaultCE32;
                break;
            }
            UChar32 nextCp;
            if(skipped == NULL && numCpFwd < 0) {
                // Some portion of nextCE32FromContraction() pulled out here as an ASCII fast path,
                // avoiding the function call and the nextSkippedCodePoint() overhead.
                nextCp = nextCodePoint(errorCode);
                if(nextCp < 0) {
                    // No more text.
                    ce32 = defaultCE32;
                    break;
                } else if((ce32 & Collation::CONTRACT_NEXT_CCC) != 0 &&
                        !CollationFCD::mayHaveLccc(nextCp)) {
                    // All contraction suffixes start with characters with lccc!=0
                    // but the next code point has lccc==0.
                    backwardNumCodePoints(1, errorCode);
                    ce32 = defaultCE32;
                    break;
                }
            } else {
                nextCp = nextSkippedCodePoint(errorCode);
                if(nextCp < 0) {
                    // No more text.
                    ce32 = defaultCE32;
                    break;
                } else if((ce32 & Collation::CONTRACT_NEXT_CCC) != 0 &&
                        !CollationFCD::mayHaveLccc(nextCp)) {
                    // All contraction suffixes start with characters with lccc!=0
                    // but the next code point has lccc==0.
                    backwardNumSkipped(1, errorCode);
                    ce32 = defaultCE32;
                    break;
                }
            }
            ce32 = nextCE32FromContraction(d, ce32, p + 2, defaultCE32, nextCp, errorCode);
            if(ce32 == Collation::NO_CE32) {
                // CEs from a discontiguous contraction plus the skipped combining marks
                // have been appended already.
                return;
            }
            break;
        }
        case Collation::DIGIT_TAG:
            if(isNumeric) {
                appendNumericCEs(ce32, forward, errorCode);
                return;
            } else {
                // Fetch the non-numeric-collation CE32 and continue.
                ce32 = d->ce32s[Collation::indexFromCE32(ce32)];
                break;
            }
        case Collation::U0000_TAG:
            U_ASSERT(c == 0);
            if(forward && foundNULTerminator()) {
                // Handle NUL-termination. (Not needed in Java.)
                ceBuffer.append(Collation::NO_CE, errorCode);
                return;
            } else {
                // Fetch the normal ce32 for U+0000 and continue.
                ce32 = d->ce32s[0];
                break;
            }
        case Collation::HANGUL_TAG: {
            const uint32_t *jamoCE32s = d->jamoCE32s;
            c -= Hangul::HANGUL_BASE;
            UChar32 t = c % Hangul::JAMO_T_COUNT;
            c /= Hangul::JAMO_T_COUNT;
            UChar32 v = c % Hangul::JAMO_V_COUNT;
            c /= Hangul::JAMO_V_COUNT;
            if((ce32 & Collation::HANGUL_NO_SPECIAL_JAMO) != 0) {
                // None of the Jamo CE32s are isSpecialCE32().
                // Avoid recursive function calls and per-Jamo tests.
                if(ceBuffer.ensureAppendCapacity(t == 0 ? 2 : 3, errorCode)) {
                    ceBuffer.set(ceBuffer.length, Collation::ceFromCE32(jamoCE32s[c]));
                    ceBuffer.set(ceBuffer.length + 1, Collation::ceFromCE32(jamoCE32s[19 + v]));
                    ceBuffer.length += 2;
                    if(t != 0) {
                        ceBuffer.appendUnsafe(Collation::ceFromCE32(jamoCE32s[39 + t]));
                    }
                }
                return;
            } else {
                // We should not need to compute each Jamo code point.
                // In particular, there should be no offset or implicit ce32.
                appendCEsFromCE32(d, U_SENTINEL, jamoCE32s[c], forward, errorCode);
                appendCEsFromCE32(d, U_SENTINEL, jamoCE32s[19 + v], forward, errorCode);
                if(t == 0) { return; }
                // offset 39 = 19 + 21 - 1:
                // 19 = JAMO_L_COUNT
                // 21 = JAMO_T_COUNT
                // -1 = omit t==0
                ce32 = jamoCE32s[39 + t];
                c = U_SENTINEL;
                break;
            }
        }
        case Collation::LEAD_SURROGATE_TAG: {
            U_ASSERT(forward);  // Backward iteration should never see lead surrogate code _unit_ data.
            U_ASSERT(U16_IS_LEAD(c));
            UChar trail;
            if(U16_IS_TRAIL(trail = handleGetTrailSurrogate())) {
                c = U16_GET_SUPPLEMENTARY(c, trail);
                ce32 &= Collation::LEAD_TYPE_MASK;
                if(ce32 == Collation::LEAD_ALL_UNASSIGNED) {
                    ce32 = Collation::UNASSIGNED_CE32;  // unassigned-implicit
                } else if(ce32 == Collation::LEAD_ALL_FALLBACK ||
                        (ce32 = d->getCE32FromSupplementary(c)) == Collation::FALLBACK_CE32) {
                    // fall back to the base data
                    d = d->base;
                    ce32 = d->getCE32FromSupplementary(c);
                }
            } else {
                // c is an unpaired surrogate.
                ce32 = Collation::UNASSIGNED_CE32;
            }
            break;
        }
        case Collation::OFFSET_TAG:
            U_ASSERT(c >= 0);
            ceBuffer.append(d->getCEFromOffsetCE32(c, ce32), errorCode);
            return;
        case Collation::IMPLICIT_TAG:
            U_ASSERT(c >= 0);
            if(U_IS_SURROGATE(c) && forbidSurrogateCodePoints()) {
                ce32 = Collation::FFFD_CE32;
                break;
            } else {
                ceBuffer.append(Collation::unassignedCEFromCodePoint(c), errorCode);
                return;
            }
        }
    }
    ceBuffer.append(Collation::ceFromSimpleCE32(ce32), errorCode);
}

uint32_t
CollationIterator::getCE32FromPrefix(const CollationData *d, uint32_t ce32,
                                     UErrorCode &errorCode) {
    const UChar *p = d->contexts + Collation::indexFromCE32(ce32);
    ce32 = CollationData::readCE32(p);  // Default if no prefix match.
    p += 2;
    // Number of code points read before the original code point.
    int32_t lookBehind = 0;
    UCharsTrie prefixes(p);
    for(;;) {
        UChar32 c = previousCodePoint(errorCode);
        if(c < 0) { break; }
        ++lookBehind;
        UStringTrieResult match = prefixes.nextForCodePoint(c);
        if(USTRINGTRIE_HAS_VALUE(match)) {
            ce32 = (uint32_t)prefixes.getValue();
        }
        if(!USTRINGTRIE_HAS_NEXT(match)) { break; }
    }
    forwardNumCodePoints(lookBehind, errorCode);
    return ce32;
}

UChar32
CollationIterator::nextSkippedCodePoint(UErrorCode &errorCode) {
    if(skipped != NULL && skipped->hasNext()) { return skipped->next(); }
    if(numCpFwd == 0) { return U_SENTINEL; }
    UChar32 c = nextCodePoint(errorCode);
    if(skipped != NULL && !skipped->isEmpty() && c >= 0) { skipped->incBeyond(); }
    if(numCpFwd > 0 && c >= 0) { --numCpFwd; }
    return c;
}

void
CollationIterator::backwardNumSkipped(int32_t n, UErrorCode &errorCode) {
    if(skipped != NULL && !skipped->isEmpty()) {
        n = skipped->backwardNumCodePoints(n);
    }
    backwardNumCodePoints(n, errorCode);
    if(numCpFwd >= 0) { numCpFwd += n; }
}

uint32_t
CollationIterator::nextCE32FromContraction(const CollationData *d, uint32_t contractionCE32,
                                           const UChar *p, uint32_t ce32, UChar32 c,
                                           UErrorCode &errorCode) {
    // c: next code point after the original one

    // Number of code points read beyond the original code point.
    // Needed for discontiguous contraction matching.
    int32_t lookAhead = 1;
    // Number of code points read since the last match (initially only c).
    int32_t sinceMatch = 1;
    // Normally we only need a contiguous match,
    // and therefore need not remember the suffixes state from before a mismatch for retrying.
    // If we are already processing skipped combining marks, then we do track the state.
    UCharsTrie suffixes(p);
    if(skipped != NULL && !skipped->isEmpty()) { skipped->saveTrieState(suffixes); }
    UStringTrieResult match = suffixes.firstForCodePoint(c);
    for(;;) {
        UChar32 nextCp;
        if(USTRINGTRIE_HAS_VALUE(match)) {
            ce32 = (uint32_t)suffixes.getValue();
            if(!USTRINGTRIE_HAS_NEXT(match) || (c = nextSkippedCodePoint(errorCode)) < 0) {
                return ce32;
            }
            if(skipped != NULL && !skipped->isEmpty()) { skipped->saveTrieState(suffixes); }
            sinceMatch = 1;
        } else if(match == USTRINGTRIE_NO_MATCH || (nextCp = nextSkippedCodePoint(errorCode)) < 0) {
            // No match for c, or partial match (USTRINGTRIE_NO_VALUE) and no further text.
            // Back up if necessary, and try a discontiguous contraction.
            if((contractionCE32 & Collation::CONTRACT_TRAILING_CCC) != 0 &&
                    // Discontiguous contraction matching extends an existing match.
                    // If there is no match yet, then there is nothing to do.
                    ((contractionCE32 & Collation::CONTRACT_SINGLE_CP_NO_MATCH) == 0 ||
                        sinceMatch < lookAhead)) {
                // The last character of at least one suffix has lccc!=0,
                // allowing for discontiguous contractions.
                // UCA S2.1.1 only processes non-starters immediately following
                // "a match in the table" (sinceMatch=1).
                if(sinceMatch > 1) {
                    // Return to the state after the last match.
                    // (Return to sinceMatch=0 and re-fetch the first partially-matched character.)
                    backwardNumSkipped(sinceMatch, errorCode);
                    c = nextSkippedCodePoint(errorCode);
                    lookAhead -= sinceMatch - 1;
                    sinceMatch = 1;
                }
                if(d->getFCD16(c) > 0xff) {
                    return nextCE32FromDiscontiguousContraction(
                        d, suffixes, ce32, lookAhead, c, errorCode);
                }
            }
            break;
        } else {
            // Continue after partial match (USTRINGTRIE_NO_VALUE) for c.
            // It does not have a result value, therefore it is not itself "a match in the table".
            // If a partially-matched c has ccc!=0 then
            // it might be skipped in discontiguous contraction.
            c = nextCp;
            ++sinceMatch;
        }
        ++lookAhead;
        match = suffixes.nextForCodePoint(c);
    }
    backwardNumSkipped(sinceMatch, errorCode);
    return ce32;
}

uint32_t
CollationIterator::nextCE32FromDiscontiguousContraction(
        const CollationData *d, UCharsTrie &suffixes, uint32_t ce32,
        int32_t lookAhead, UChar32 c,
        UErrorCode &errorCode) {
    if(U_FAILURE(errorCode)) { return 0; }

    // UCA section 3.3.2 Contractions:
    // Contractions that end with non-starter characters
    // are known as discontiguous contractions.
    // ... discontiguous contractions must be detected in input text
    // whenever the final sequence of non-starter characters could be rearranged
    // so as to make a contiguous matching sequence that is canonically equivalent.

    // UCA: http://www.unicode.org/reports/tr10/#S2.1
    // S2.1 Find the longest initial substring S at each point that has a match in the table.
    // S2.1.1 If there are any non-starters following S, process each non-starter C.
    // S2.1.2 If C is not blocked from S, find if S + C has a match in the table.
    //     Note: A non-starter in a string is called blocked
    //     if there is another non-starter of the same canonical combining class or zero
    //     between it and the last character of canonical combining class 0.
    // S2.1.3 If there is a match, replace S by S + C, and remove C.

    // First: Is a discontiguous contraction even possible?
    uint16_t fcd16 = d->getFCD16(c);
    U_ASSERT(fcd16 > 0xff);  // The caller checked this already, as a shortcut.
    UChar32 nextCp = nextSkippedCodePoint(errorCode);
    if(nextCp < 0) {
        // No further text.
        backwardNumSkipped(1, errorCode);
        return ce32;
    }
    ++lookAhead;
    uint8_t prevCC = (uint8_t)fcd16;
    fcd16 = d->getFCD16(nextCp);
    if(fcd16 <= 0xff) {
        // The next code point after c is a starter (S2.1.1 "process each non-starter").
        backwardNumSkipped(2, errorCode);
        return ce32;
    }

    // We have read and matched (lookAhead-2) code points,
    // read non-matching c and peeked ahead at nextCp.
    // Return to the state before the mismatch and continue matching with nextCp.
    if(skipped == NULL || skipped->isEmpty()) {
        if(skipped == NULL) {
            skipped = new SkippedState();
            if(skipped == NULL) {
                errorCode = U_MEMORY_ALLOCATION_ERROR;
                return 0;
            }
        }
        suffixes.reset();
        if(lookAhead > 2) {
            // Replay the partial match so far.
            backwardNumCodePoints(lookAhead, errorCode);
            suffixes.firstForCodePoint(nextCodePoint(errorCode));
            for(int32_t i = 3; i < lookAhead; ++i) {
                suffixes.nextForCodePoint(nextCodePoint(errorCode));
            }
            // Skip c (which did not match) and nextCp (which we will try now).
            forwardNumCodePoints(2, errorCode);
        }
        skipped->saveTrieState(suffixes);
    } else {
        // Reset to the trie state before the failed match of c.
        skipped->resetToTrieState(suffixes);
    }

    skipped->setFirstSkipped(c);
    // Number of code points read since the last match (at this point: c and nextCp).
    int32_t sinceMatch = 2;
    c = nextCp;
    for(;;) {
        UStringTrieResult match;
        // "If C is not blocked from S, find if S + C has a match in the table." (S2.1.2)
        if(prevCC < (fcd16 >> 8) && USTRINGTRIE_HAS_VALUE(match = suffixes.nextForCodePoint(c))) {
            // "If there is a match, replace S by S + C, and remove C." (S2.1.3)
            // Keep prevCC unchanged.
            ce32 = (uint32_t)suffixes.getValue();
            sinceMatch = 0;
            skipped->recordMatch();
            if(!USTRINGTRIE_HAS_NEXT(match)) { break; }
            skipped->saveTrieState(suffixes);
        } else {
            // No match for "S + C", skip C.
            skipped->skip(c);
            skipped->resetToTrieState(suffixes);
            prevCC = (uint8_t)fcd16;
        }
        if((c = nextSkippedCodePoint(errorCode)) < 0) { break; }
        ++sinceMatch;
        fcd16 = d->getFCD16(c);
        if(fcd16 <= 0xff) {
            // The next code point after c is a starter (S2.1.1 "process each non-starter").
            break;
        }
    }
    backwardNumSkipped(sinceMatch, errorCode);
    UBool isTopDiscontiguous = skipped->isEmpty();
    skipped->replaceMatch();
    if(isTopDiscontiguous && !skipped->isEmpty()) {
        // We did get a match after skipping one or more combining marks,
        // and we are not in a recursive discontiguous contraction.
        // Append CEs from the contraction ce32
        // and then from the combining marks that we skipped before the match.
        c = U_SENTINEL;
        for(;;) {
            appendCEsFromCE32(d, c, ce32, TRUE, errorCode);
            // Fetch CE32s for skipped combining marks from the normal data, with fallback,
            // rather than from the CollationData where we found the contraction.
            if(!skipped->hasNext()) { break; }
            c = skipped->next();
            ce32 = getDataCE32(c);
            if(ce32 == Collation::FALLBACK_CE32) {
                d = data->base;
                ce32 = d->getCE32(c);
            } else {
                d = data;
            }
            // Note: A nested discontiguous-contraction match
            // replaces consumed combining marks with newly skipped ones
            // and resets the reading position to the beginning.
        }
        skipped->clear();
        ce32 = Collation::NO_CE32;  // Signal to the caller that the result is in the ceBuffer.
    }
    return ce32;
}

void
CollationIterator::appendNumericCEs(uint32_t ce32, UBool forward, UErrorCode &errorCode) {
    // Collect digits.
    CharString digits;
    if(forward) {
        for(;;) {
            char digit = Collation::digitFromCE32(ce32);
            digits.append(digit, errorCode);
            if(numCpFwd == 0) { break; }
            UChar32 c = nextCodePoint(errorCode);
            if(c < 0) { break; }
            ce32 = data->getCE32(c);
            if(ce32 == Collation::FALLBACK_CE32) {
                ce32 = data->base->getCE32(c);
            }
            if(!Collation::hasCE32Tag(ce32, Collation::DIGIT_TAG)) {
                backwardNumCodePoints(1, errorCode);
                break;
            }
            if(numCpFwd > 0) { --numCpFwd; }
        }
    } else {
        for(;;) {
            char digit = Collation::digitFromCE32(ce32);
            digits.append(digit, errorCode);
            UChar32 c = previousCodePoint(errorCode);
            if(c < 0) { break; }
            ce32 = data->getCE32(c);
            if(ce32 == Collation::FALLBACK_CE32) {
                ce32 = data->base->getCE32(c);
            }
            if(!Collation::hasCE32Tag(ce32, Collation::DIGIT_TAG)) {
                forwardNumCodePoints(1, errorCode);
                break;
            }
        }
        // Reverse the digit string.
        char *p = digits.data();
        char *q = p + digits.length() - 1;
        while(p < q) {
            char digit = *p;
            *p++ = *q;
            *q-- = digit;
        }
    }
    if(U_FAILURE(errorCode)) { return; }
    int32_t pos = 0;
    do {
        // Skip leading zeros.
        while(pos < (digits.length() - 1) && digits[pos] == 0) { ++pos; }
        // Write a sequence of CEs for at most 254 digits at a time.
        int32_t segmentLength = digits.length() - pos;
        if(segmentLength > 254) { segmentLength = 254; }
        appendNumericSegmentCEs(digits.data() + pos, segmentLength, errorCode);
        pos += segmentLength;
    } while(U_SUCCESS(errorCode) && pos < digits.length());
}

void
CollationIterator::appendNumericSegmentCEs(const char *digits, int32_t length, UErrorCode &errorCode) {
    U_ASSERT(1 <= length && length <= 254);
    U_ASSERT(length == 1 || digits[0] != 0);
    uint32_t numericPrimary = data->numericPrimary;
    // Note: We use primary byte values 2..255: digits are not compressible.
    if(length <= 7) {
        // Very dense encoding for small numbers.
        int32_t value = digits[0];
        for(int32_t i = 1; i < length; ++i) {
            value = value * 10 + digits[i];
        }
        // Primary weight second byte values:
        //     74 byte values   2.. 75 for small numbers in two-byte primary weights.
        //     40 byte values  76..115 for medium numbers in three-byte primary weights.
        //     16 byte values 116..131 for large numbers in four-byte primary weights.
        //    124 byte values 132..255 for very large numbers with 4..127 digit pairs.
        int32_t firstByte = 2;
        int32_t numBytes = 74;
        if(value < numBytes) {
            // Two-byte primary for 0..73, good for day & month numbers etc.
            uint32_t primary = numericPrimary | ((firstByte + value) << 16);
            ceBuffer.append(Collation::makeCE(primary), errorCode);
            return;
        }
        value -= numBytes;
        firstByte += numBytes;
        numBytes = 40;
        if(value < numBytes * 254) {
            // Three-byte primary for 74..10233=74+40*254-1, good for year numbers and more.
            uint32_t primary = numericPrimary |
                ((firstByte + value / 254) << 16) | ((2 + value % 254) << 8);
            ceBuffer.append(Collation::makeCE(primary), errorCode);
            return;
        }
        value -= numBytes * 254;
        firstByte += numBytes;
        numBytes = 16;
        if(value < numBytes * 254 * 254) {
            // Four-byte primary for 10234..1042489=10234+16*254*254-1.
            uint32_t primary = numericPrimary | (2 + value % 254);
            value /= 254;
            primary |= (2 + value % 254) << 8;
            value /= 254;
            primary |= (firstByte + value % 254) << 16;
            ceBuffer.append(Collation::makeCE(primary), errorCode);
            return;
        }
        // original value > 1042489
    }
    U_ASSERT(length >= 7);

    // The second primary byte value 132..255 indicates the number of digit pairs (4..127),
    // then we generate primary bytes with those pairs.
    // Omit trailing 00 pairs.
    // Decrement the value for the last pair.

    // Set the exponent. 4 pairs->132, 5 pairs->133, ..., 127 pairs->255.
    int32_t numPairs = (length + 1) / 2;
    uint32_t primary = numericPrimary | ((132 - 4 + numPairs) << 16);
    // Find the length without trailing 00 pairs.
    while(digits[length - 1] == 0 && digits[length - 2] == 0) {
        length -= 2;
    }
    // Read the first pair.
    uint32_t pair;
    int32_t pos;
    if(length & 1) {
        // Only "half a pair" if we have an odd number of digits.
        pair = digits[0];
        pos = 1;
    } else {
        pair = digits[0] * 10 + digits[1];
        pos = 2;
    }
    pair = 11 + 2 * pair;
    // Add the pairs of digits between pos and length.
    int32_t shift = 8;
    while(pos < length) {
        if(shift == 0) {
            // Every three pairs/bytes we need to store a 4-byte-primary CE
            // and start with a new CE with the '0' primary lead byte.
            primary |= pair;
            ceBuffer.append(Collation::makeCE(primary), errorCode);
            primary = numericPrimary;
            shift = 16;
        } else {
            primary |= pair << shift;
            shift -= 8;
        }
        pair = 11 + 2 * (digits[pos] * 10 + digits[pos + 1]);
        pos += 2;
    }
    primary |= (pair - 1) << shift;
    ceBuffer.append(Collation::makeCE(primary), errorCode);
}

int64_t
CollationIterator::previousCE(UVector32 &offsets, UErrorCode &errorCode) {
    if(ceBuffer.length > 0) {
        // Return the previous buffered CE.
        return ceBuffer.get(--ceBuffer.length);
    }
    offsets.removeAllElements();
    int32_t limitOffset = getOffset();
    UChar32 c = previousCodePoint(errorCode);
    if(c < 0) { return Collation::NO_CE; }
    if(data->isUnsafeBackward(c, isNumeric)) {
        return previousCEUnsafe(c, offsets, errorCode);
    }
    // Simple, safe-backwards iteration:
    // Get a CE going backwards, handle prefixes but no contractions.
    uint32_t ce32 = data->getCE32(c);
    const CollationData *d;
    if(ce32 == Collation::FALLBACK_CE32) {
        d = data->base;
        ce32 = d->getCE32(c);
    } else {
        d = data;
    }
    if(Collation::isSimpleOrLongCE32(ce32)) {
        return Collation::ceFromCE32(ce32);
    }
    appendCEsFromCE32(d, c, ce32, FALSE, errorCode);
    if(U_SUCCESS(errorCode)) {
        if(ceBuffer.length > 1) {
            offsets.addElement(getOffset(), errorCode);
            // For an expansion, the offset of each non-initial CE is the limit offset,
            // consistent with forward iteration.
            while(offsets.size() <= ceBuffer.length) {
                offsets.addElement(limitOffset, errorCode);
            };
        }
        return ceBuffer.get(--ceBuffer.length);
    } else {
        return Collation::NO_CE_PRIMARY;
    }
}

int64_t
CollationIterator::previousCEUnsafe(UChar32 c, UVector32 &offsets, UErrorCode &errorCode) {
    // We just move through the input counting safe and unsafe code points
    // without collecting the unsafe-backward substring into a buffer and
    // switching to it.
    // This is to keep the logic simple. Otherwise we would have to handle
    // prefix matching going before the backward buffer, switching
    // to iteration and back, etc.
    // In the most important case of iterating over a normal string,
    // reading from the string itself is already maximally fast.
    // The only drawback there is that after getting the CEs we always
    // skip backward to the safe character rather than switching out
    // of a backwardBuffer.
    // But this should not be the common case for previousCE(),
    // and correctness and maintainability are more important than
    // complex optimizations.
    // Find the first safe character before c.
    int32_t numBackward = 1;
    while((c = previousCodePoint(errorCode)) >= 0) {
        ++numBackward;
        if(!data->isUnsafeBackward(c, isNumeric)) {
            break;
        }
    }
    // Set the forward iteration limit.
    // Note: This counts code points.
    // We cannot enforce a limit in the middle of a surrogate pair or similar.
    numCpFwd = numBackward;
    // Reset the forward iterator.
    cesIndex = 0;
    U_ASSERT(ceBuffer.length == 0);
    // Go forward and collect the CEs.
    int32_t offset = getOffset();
    while(numCpFwd > 0) {
        // nextCE() normally reads one code point.
        // Contraction matching and digit specials read more and check numCpFwd.
        --numCpFwd;
        // Append one or more CEs to the ceBuffer.
        (void)nextCE(errorCode);
        U_ASSERT(U_FAILURE(errorCode) || ceBuffer.get(ceBuffer.length - 1) != Collation::NO_CE);
        // No need to loop for getting each expansion CE from nextCE().
        cesIndex = ceBuffer.length;
        // However, we need to write an offset for each CE.
        // This is for CollationElementIterator::getOffset() to return
        // intermediate offsets from the unsafe-backwards segment.
        U_ASSERT(offsets.size() < ceBuffer.length);
        offsets.addElement(offset, errorCode);
        // For an expansion, the offset of each non-initial CE is the limit offset,
        // consistent with forward iteration.
        offset = getOffset();
        while(offsets.size() < ceBuffer.length) {
            offsets.addElement(offset, errorCode);
        };
    }
    U_ASSERT(offsets.size() == ceBuffer.length);
    // End offset corresponding to just after the unsafe-backwards segment.
    offsets.addElement(offset, errorCode);
    // Reset the forward iteration limit
    // and move backward to before the segment for which we fetched CEs.
    numCpFwd = -1;
    backwardNumCodePoints(numBackward, errorCode);
    // Use the collected CEs and return the last one.
    cesIndex = 0;  // Avoid cesIndex > ceBuffer.length when that gets decremented.
    if(U_SUCCESS(errorCode)) {
        return ceBuffer.get(--ceBuffer.length);
    } else {
        return Collation::NO_CE_PRIMARY;
    }
}

U_NAMESPACE_END

#endif  // !UCONFIG_NO_COLLATION
