Home | History | Annotate | Download | only in i18n
      1 /*
      2 *******************************************************************************
      3 * Copyright (C) 2010-2014, International Business Machines
      4 * Corporation and others.  All Rights Reserved.
      5 *******************************************************************************
      6 * collationiterator.cpp
      7 *
      8 * created on: 2010oct27
      9 * created by: Markus W. Scherer
     10 */
     11 
     12 #include "utypeinfo.h"  // for 'typeid' to work
     13 
     14 #include "unicode/utypes.h"
     15 
     16 #if !UCONFIG_NO_COLLATION
     17 
     18 #include "unicode/ucharstrie.h"
     19 #include "unicode/ustringtrie.h"
     20 #include "charstr.h"
     21 #include "cmemory.h"
     22 #include "collation.h"
     23 #include "collationdata.h"
     24 #include "collationfcd.h"
     25 #include "collationiterator.h"
     26 #include "normalizer2impl.h"
     27 #include "uassert.h"
     28 #include "uvectr32.h"
     29 
     30 U_NAMESPACE_BEGIN
     31 
     32 CollationIterator::CEBuffer::~CEBuffer() {}
     33 
     34 UBool
     35 CollationIterator::CEBuffer::ensureAppendCapacity(int32_t appCap, UErrorCode &errorCode) {
     36     int32_t capacity = buffer.getCapacity();
     37     if((length + appCap) <= capacity) { return TRUE; }
     38     if(U_FAILURE(errorCode)) { return FALSE; }
     39     do {
     40         if(capacity < 1000) {
     41             capacity *= 4;
     42         } else {
     43             capacity *= 2;
     44         }
     45     } while(capacity < (length + appCap));
     46     int64_t *p = buffer.resize(capacity, length);
     47     if(p == NULL) {
     48         errorCode = U_MEMORY_ALLOCATION_ERROR;
     49         return FALSE;
     50     }
     51     return TRUE;
     52 }
     53 
     54 // State of combining marks skipped in discontiguous contraction.
     55 // We create a state object on first use and keep it around deactivated between uses.
     56 class SkippedState : public UMemory {
     57 public:
     58     // Born active but empty.
     59     SkippedState() : pos(0), skipLengthAtMatch(0) {}
     60     void clear() {
     61         oldBuffer.remove();
     62         pos = 0;
     63         // The newBuffer is reset by setFirstSkipped().
     64     }
     65 
     66     UBool isEmpty() const { return oldBuffer.isEmpty(); }
     67 
     68     UBool hasNext() const { return pos < oldBuffer.length(); }
     69 
     70     // Requires hasNext().
     71     UChar32 next() {
     72         UChar32 c = oldBuffer.char32At(pos);
     73         pos += U16_LENGTH(c);
     74         return c;
     75     }
     76 
     77     // Accounts for one more input code point read beyond the end of the marks buffer.
     78     void incBeyond() {
     79         U_ASSERT(!hasNext());
     80         ++pos;
     81     }
     82 
     83     // Goes backward through the skipped-marks buffer.
     84     // Returns the number of code points read beyond the skipped marks
     85     // that need to be backtracked through normal input.
     86     int32_t backwardNumCodePoints(int32_t n) {
     87         int32_t length = oldBuffer.length();
     88         int32_t beyond = pos - length;
     89         if(beyond > 0) {
     90             if(beyond >= n) {
     91                 // Not back far enough to re-enter the oldBuffer.
     92                 pos -= n;
     93                 return n;
     94             } else {
     95                 // Back out all beyond-oldBuffer code points and re-enter the buffer.
     96                 pos = oldBuffer.moveIndex32(length, beyond - n);
     97                 return beyond;
     98             }
     99         } else {
    100             // Go backwards from inside the oldBuffer.
    101             pos = oldBuffer.moveIndex32(pos, -n);
    102             return 0;
    103         }
    104     }
    105 
    106     void setFirstSkipped(UChar32 c) {
    107         skipLengthAtMatch = 0;
    108         newBuffer.setTo(c);
    109     }
    110 
    111     void skip(UChar32 c) {
    112         newBuffer.append(c);
    113     }
    114 
    115     void recordMatch() { skipLengthAtMatch = newBuffer.length(); }
    116 
    117     // Replaces the characters we consumed with the newly skipped ones.
    118     void replaceMatch() {
    119         // Note: UnicodeString.replace() pins pos to at most length().
    120         oldBuffer.replace(0, pos, newBuffer, 0, skipLengthAtMatch);
    121         pos = 0;
    122     }
    123 
    124     void saveTrieState(const UCharsTrie &trie) { trie.saveState(state); }
    125     void resetToTrieState(UCharsTrie &trie) const { trie.resetToState(state); }
    126 
    127 private:
    128     // Combining marks skipped in previous discontiguous-contraction matching.
    129     // After that discontiguous contraction was completed, we start reading them from here.
    130     UnicodeString oldBuffer;
    131     // Combining marks newly skipped in current discontiguous-contraction matching.
    132     // These might have been read from the normal text or from the oldBuffer.
    133     UnicodeString newBuffer;
    134     // Reading index in oldBuffer,
    135     // or counter for how many code points have been read beyond oldBuffer (pos-oldBuffer.length()).
    136     int32_t pos;
    137     // newBuffer.length() at the time of the last matching character.
    138     // When a partial match fails, we back out skipped and partial-matching input characters.
    139     int32_t skipLengthAtMatch;
    140     // We save the trie state before we attempt to match a character,
    141     // so that we can skip it and try the next one.
    142     UCharsTrie::State state;
    143 };
    144 
    145 CollationIterator::CollationIterator(const CollationIterator &other)
    146         : UObject(other),
    147           trie(other.trie),
    148           data(other.data),
    149           cesIndex(other.cesIndex),
    150           skipped(NULL),
    151           numCpFwd(other.numCpFwd),
    152           isNumeric(other.isNumeric) {
    153     UErrorCode errorCode = U_ZERO_ERROR;
    154     int32_t length = other.ceBuffer.length;
    155     if(length > 0 && ceBuffer.ensureAppendCapacity(length, errorCode)) {
    156         for(int32_t i = 0; i < length; ++i) {
    157             ceBuffer.set(i, other.ceBuffer.get(i));
    158         }
    159         ceBuffer.length = length;
    160     } else {
    161         cesIndex = 0;
    162     }
    163 }
    164 
    165 CollationIterator::~CollationIterator() {
    166     delete skipped;
    167 }
    168 
    169 UBool
    170 CollationIterator::operator==(const CollationIterator &other) const {
    171     // Subclasses: Call this method and then add more specific checks.
    172     // Compare the iterator state but not the collation data (trie & data fields):
    173     // Assume that the caller compares the data.
    174     // Ignore skipped since that should be unused between calls to nextCE().
    175     // (It only stays around to avoid another memory allocation.)
    176     if(!(typeid(*this) == typeid(other) &&
    177             ceBuffer.length == other.ceBuffer.length &&
    178             cesIndex == other.cesIndex &&
    179             numCpFwd == other.numCpFwd &&
    180             isNumeric == other.isNumeric)) {
    181         return FALSE;
    182     }
    183     for(int32_t i = 0; i < ceBuffer.length; ++i) {
    184         if(ceBuffer.get(i) != other.ceBuffer.get(i)) { return FALSE; }
    185     }
    186     return TRUE;
    187 }
    188 
    189 void
    190 CollationIterator::reset() {
    191     cesIndex = ceBuffer.length = 0;
    192     if(skipped != NULL) { skipped->clear(); }
    193 }
    194 
    195 int32_t
    196 CollationIterator::fetchCEs(UErrorCode &errorCode) {
    197     while(U_SUCCESS(errorCode) && nextCE(errorCode) != Collation::NO_CE) {
    198         // No need to loop for each expansion CE.
    199         cesIndex = ceBuffer.length;
    200     }
    201     return ceBuffer.length;
    202 }
    203 
    204 uint32_t
    205 CollationIterator::handleNextCE32(UChar32 &c, UErrorCode &errorCode) {
    206     c = nextCodePoint(errorCode);
    207     return (c < 0) ? Collation::FALLBACK_CE32 : data->getCE32(c);
    208 }
    209 
    210 UChar
    211 CollationIterator::handleGetTrailSurrogate() {
    212     return 0;
    213 }
    214 
    215 UBool
    216 CollationIterator::foundNULTerminator() {
    217     return FALSE;
    218 }
    219 
    220 UBool
    221 CollationIterator::forbidSurrogateCodePoints() const {
    222     return FALSE;
    223 }
    224 
    225 uint32_t
    226 CollationIterator::getDataCE32(UChar32 c) const {
    227     return data->getCE32(c);
    228 }
    229 
    230 uint32_t
    231 CollationIterator::getCE32FromBuilderData(uint32_t /*ce32*/, UErrorCode &errorCode) {
    232     if(U_SUCCESS(errorCode)) { errorCode = U_INTERNAL_PROGRAM_ERROR; }
    233     return 0;
    234 }
    235 
    236 int64_t
    237 CollationIterator::nextCEFromCE32(const CollationData *d, UChar32 c, uint32_t ce32,
    238                                   UErrorCode &errorCode) {
    239     --ceBuffer.length;  // Undo ceBuffer.incLength().
    240     appendCEsFromCE32(d, c, ce32, TRUE, errorCode);
    241     if(U_SUCCESS(errorCode)) {
    242         return ceBuffer.get(cesIndex++);
    243     } else {
    244         return Collation::NO_CE_PRIMARY;
    245     }
    246 }
    247 
    248 void
    249 CollationIterator::appendCEsFromCE32(const CollationData *d, UChar32 c, uint32_t ce32,
    250                                      UBool forward, UErrorCode &errorCode) {
    251     while(Collation::isSpecialCE32(ce32)) {
    252         switch(Collation::tagFromCE32(ce32)) {
    253         case Collation::FALLBACK_TAG:
    254         case Collation::RESERVED_TAG_3:
    255             if(U_SUCCESS(errorCode)) { errorCode = U_INTERNAL_PROGRAM_ERROR; }
    256             return;
    257         case Collation::LONG_PRIMARY_TAG:
    258             ceBuffer.append(Collation::ceFromLongPrimaryCE32(ce32), errorCode);
    259             return;
    260         case Collation::LONG_SECONDARY_TAG:
    261             ceBuffer.append(Collation::ceFromLongSecondaryCE32(ce32), errorCode);
    262             return;
    263         case Collation::LATIN_EXPANSION_TAG:
    264             if(ceBuffer.ensureAppendCapacity(2, errorCode)) {
    265                 ceBuffer.set(ceBuffer.length, Collation::latinCE0FromCE32(ce32));
    266                 ceBuffer.set(ceBuffer.length + 1, Collation::latinCE1FromCE32(ce32));
    267                 ceBuffer.length += 2;
    268             }
    269             return;
    270         case Collation::EXPANSION32_TAG: {
    271             const uint32_t *ce32s = d->ce32s + Collation::indexFromCE32(ce32);
    272             int32_t length = Collation::lengthFromCE32(ce32);
    273             if(ceBuffer.ensureAppendCapacity(length, errorCode)) {
    274                 do {
    275                     ceBuffer.appendUnsafe(Collation::ceFromCE32(*ce32s++));
    276                 } while(--length > 0);
    277             }
    278             return;
    279         }
    280         case Collation::EXPANSION_TAG: {
    281             const int64_t *ces = d->ces + Collation::indexFromCE32(ce32);
    282             int32_t length = Collation::lengthFromCE32(ce32);
    283             if(ceBuffer.ensureAppendCapacity(length, errorCode)) {
    284                 do {
    285                     ceBuffer.appendUnsafe(*ces++);
    286                 } while(--length > 0);
    287             }
    288             return;
    289         }
    290         case Collation::BUILDER_DATA_TAG:
    291             ce32 = getCE32FromBuilderData(ce32, errorCode);
    292             if(U_FAILURE(errorCode)) { return; }
    293             if(ce32 == Collation::FALLBACK_CE32) {
    294                 d = data->base;
    295                 ce32 = d->getCE32(c);
    296             }
    297             break;
    298         case Collation::PREFIX_TAG:
    299             if(forward) { backwardNumCodePoints(1, errorCode); }
    300             ce32 = getCE32FromPrefix(d, ce32, errorCode);
    301             if(forward) { forwardNumCodePoints(1, errorCode); }
    302             break;
    303         case Collation::CONTRACTION_TAG: {
    304             const UChar *p = d->contexts + Collation::indexFromCE32(ce32);
    305             uint32_t defaultCE32 = CollationData::readCE32(p);  // Default if no suffix match.
    306             if(!forward) {
    307                 // Backward contractions are handled by previousCEUnsafe().
    308                 // c has contractions but they were not found.
    309                 ce32 = defaultCE32;
    310                 break;
    311             }
    312             UChar32 nextCp;
    313             if(skipped == NULL && numCpFwd < 0) {
    314                 // Some portion of nextCE32FromContraction() pulled out here as an ASCII fast path,
    315                 // avoiding the function call and the nextSkippedCodePoint() overhead.
    316                 nextCp = nextCodePoint(errorCode);
    317                 if(nextCp < 0) {
    318                     // No more text.
    319                     ce32 = defaultCE32;
    320                     break;
    321                 } else if((ce32 & Collation::CONTRACT_NEXT_CCC) != 0 &&
    322                         !CollationFCD::mayHaveLccc(nextCp)) {
    323                     // All contraction suffixes start with characters with lccc!=0
    324                     // but the next code point has lccc==0.
    325                     backwardNumCodePoints(1, errorCode);
    326                     ce32 = defaultCE32;
    327                     break;
    328                 }
    329             } else {
    330                 nextCp = nextSkippedCodePoint(errorCode);
    331                 if(nextCp < 0) {
    332                     // No more text.
    333                     ce32 = defaultCE32;
    334                     break;
    335                 } else if((ce32 & Collation::CONTRACT_NEXT_CCC) != 0 &&
    336                         !CollationFCD::mayHaveLccc(nextCp)) {
    337                     // All contraction suffixes start with characters with lccc!=0
    338                     // but the next code point has lccc==0.
    339                     backwardNumSkipped(1, errorCode);
    340                     ce32 = defaultCE32;
    341                     break;
    342                 }
    343             }
    344             ce32 = nextCE32FromContraction(d, ce32, p + 2, defaultCE32, nextCp, errorCode);
    345             if(ce32 == Collation::NO_CE32) {
    346                 // CEs from a discontiguous contraction plus the skipped combining marks
    347                 // have been appended already.
    348                 return;
    349             }
    350             break;
    351         }
    352         case Collation::DIGIT_TAG:
    353             if(isNumeric) {
    354                 appendNumericCEs(ce32, forward, errorCode);
    355                 return;
    356             } else {
    357                 // Fetch the non-numeric-collation CE32 and continue.
    358                 ce32 = d->ce32s[Collation::indexFromCE32(ce32)];
    359                 break;
    360             }
    361         case Collation::U0000_TAG:
    362             U_ASSERT(c == 0);
    363             if(forward && foundNULTerminator()) {
    364                 // Handle NUL-termination. (Not needed in Java.)
    365                 ceBuffer.append(Collation::NO_CE, errorCode);
    366                 return;
    367             } else {
    368                 // Fetch the normal ce32 for U+0000 and continue.
    369                 ce32 = d->ce32s[0];
    370                 break;
    371             }
    372         case Collation::HANGUL_TAG: {
    373             const uint32_t *jamoCE32s = d->jamoCE32s;
    374             c -= Hangul::HANGUL_BASE;
    375             UChar32 t = c % Hangul::JAMO_T_COUNT;
    376             c /= Hangul::JAMO_T_COUNT;
    377             UChar32 v = c % Hangul::JAMO_V_COUNT;
    378             c /= Hangul::JAMO_V_COUNT;
    379             if((ce32 & Collation::HANGUL_NO_SPECIAL_JAMO) != 0) {
    380                 // None of the Jamo CE32s are isSpecialCE32().
    381                 // Avoid recursive function calls and per-Jamo tests.
    382                 if(ceBuffer.ensureAppendCapacity(t == 0 ? 2 : 3, errorCode)) {
    383                     ceBuffer.set(ceBuffer.length, Collation::ceFromCE32(jamoCE32s[c]));
    384                     ceBuffer.set(ceBuffer.length + 1, Collation::ceFromCE32(jamoCE32s[19 + v]));
    385                     ceBuffer.length += 2;
    386                     if(t != 0) {
    387                         ceBuffer.appendUnsafe(Collation::ceFromCE32(jamoCE32s[39 + t]));
    388                     }
    389                 }
    390                 return;
    391             } else {
    392                 // We should not need to compute each Jamo code point.
    393                 // In particular, there should be no offset or implicit ce32.
    394                 appendCEsFromCE32(d, U_SENTINEL, jamoCE32s[c], forward, errorCode);
    395                 appendCEsFromCE32(d, U_SENTINEL, jamoCE32s[19 + v], forward, errorCode);
    396                 if(t == 0) { return; }
    397                 // offset 39 = 19 + 21 - 1:
    398                 // 19 = JAMO_L_COUNT
    399                 // 21 = JAMO_T_COUNT
    400                 // -1 = omit t==0
    401                 ce32 = jamoCE32s[39 + t];
    402                 c = U_SENTINEL;
    403                 break;
    404             }
    405         }
    406         case Collation::LEAD_SURROGATE_TAG: {
    407             U_ASSERT(forward);  // Backward iteration should never see lead surrogate code _unit_ data.
    408             U_ASSERT(U16_IS_LEAD(c));
    409             UChar trail;
    410             if(U16_IS_TRAIL(trail = handleGetTrailSurrogate())) {
    411                 c = U16_GET_SUPPLEMENTARY(c, trail);
    412                 ce32 &= Collation::LEAD_TYPE_MASK;
    413                 if(ce32 == Collation::LEAD_ALL_UNASSIGNED) {
    414                     ce32 = Collation::UNASSIGNED_CE32;  // unassigned-implicit
    415                 } else if(ce32 == Collation::LEAD_ALL_FALLBACK ||
    416                         (ce32 = d->getCE32FromSupplementary(c)) == Collation::FALLBACK_CE32) {
    417                     // fall back to the base data
    418                     d = d->base;
    419                     ce32 = d->getCE32FromSupplementary(c);
    420                 }
    421             } else {
    422                 // c is an unpaired surrogate.
    423                 ce32 = Collation::UNASSIGNED_CE32;
    424             }
    425             break;
    426         }
    427         case Collation::OFFSET_TAG:
    428             U_ASSERT(c >= 0);
    429             ceBuffer.append(d->getCEFromOffsetCE32(c, ce32), errorCode);
    430             return;
    431         case Collation::IMPLICIT_TAG:
    432             U_ASSERT(c >= 0);
    433             if(U_IS_SURROGATE(c) && forbidSurrogateCodePoints()) {
    434                 ce32 = Collation::FFFD_CE32;
    435                 break;
    436             } else {
    437                 ceBuffer.append(Collation::unassignedCEFromCodePoint(c), errorCode);
    438                 return;
    439             }
    440         }
    441     }
    442     ceBuffer.append(Collation::ceFromSimpleCE32(ce32), errorCode);
    443 }
    444 
    445 uint32_t
    446 CollationIterator::getCE32FromPrefix(const CollationData *d, uint32_t ce32,
    447                                      UErrorCode &errorCode) {
    448     const UChar *p = d->contexts + Collation::indexFromCE32(ce32);
    449     ce32 = CollationData::readCE32(p);  // Default if no prefix match.
    450     p += 2;
    451     // Number of code points read before the original code point.
    452     int32_t lookBehind = 0;
    453     UCharsTrie prefixes(p);
    454     for(;;) {
    455         UChar32 c = previousCodePoint(errorCode);
    456         if(c < 0) { break; }
    457         ++lookBehind;
    458         UStringTrieResult match = prefixes.nextForCodePoint(c);
    459         if(USTRINGTRIE_HAS_VALUE(match)) {
    460             ce32 = (uint32_t)prefixes.getValue();
    461         }
    462         if(!USTRINGTRIE_HAS_NEXT(match)) { break; }
    463     }
    464     forwardNumCodePoints(lookBehind, errorCode);
    465     return ce32;
    466 }
    467 
    468 UChar32
    469 CollationIterator::nextSkippedCodePoint(UErrorCode &errorCode) {
    470     if(skipped != NULL && skipped->hasNext()) { return skipped->next(); }
    471     if(numCpFwd == 0) { return U_SENTINEL; }
    472     UChar32 c = nextCodePoint(errorCode);
    473     if(skipped != NULL && !skipped->isEmpty() && c >= 0) { skipped->incBeyond(); }
    474     if(numCpFwd > 0 && c >= 0) { --numCpFwd; }
    475     return c;
    476 }
    477 
    478 void
    479 CollationIterator::backwardNumSkipped(int32_t n, UErrorCode &errorCode) {
    480     if(skipped != NULL && !skipped->isEmpty()) {
    481         n = skipped->backwardNumCodePoints(n);
    482     }
    483     backwardNumCodePoints(n, errorCode);
    484     if(numCpFwd >= 0) { numCpFwd += n; }
    485 }
    486 
    487 uint32_t
    488 CollationIterator::nextCE32FromContraction(const CollationData *d, uint32_t contractionCE32,
    489                                            const UChar *p, uint32_t ce32, UChar32 c,
    490                                            UErrorCode &errorCode) {
    491     // c: next code point after the original one
    492 
    493     // Number of code points read beyond the original code point.
    494     // Needed for discontiguous contraction matching.
    495     int32_t lookAhead = 1;
    496     // Number of code points read since the last match (initially only c).
    497     int32_t sinceMatch = 1;
    498     // Normally we only need a contiguous match,
    499     // and therefore need not remember the suffixes state from before a mismatch for retrying.
    500     // If we are already processing skipped combining marks, then we do track the state.
    501     UCharsTrie suffixes(p);
    502     if(skipped != NULL && !skipped->isEmpty()) { skipped->saveTrieState(suffixes); }
    503     UStringTrieResult match = suffixes.firstForCodePoint(c);
    504     for(;;) {
    505         UChar32 nextCp;
    506         if(USTRINGTRIE_HAS_VALUE(match)) {
    507             ce32 = (uint32_t)suffixes.getValue();
    508             if(!USTRINGTRIE_HAS_NEXT(match) || (c = nextSkippedCodePoint(errorCode)) < 0) {
    509                 return ce32;
    510             }
    511             if(skipped != NULL && !skipped->isEmpty()) { skipped->saveTrieState(suffixes); }
    512             sinceMatch = 1;
    513         } else if(match == USTRINGTRIE_NO_MATCH || (nextCp = nextSkippedCodePoint(errorCode)) < 0) {
    514             // No match for c, or partial match (USTRINGTRIE_NO_VALUE) and no further text.
    515             // Back up if necessary, and try a discontiguous contraction.
    516             if((contractionCE32 & Collation::CONTRACT_TRAILING_CCC) != 0 &&
    517                     // Discontiguous contraction matching extends an existing match.
    518                     // If there is no match yet, then there is nothing to do.
    519                     ((contractionCE32 & Collation::CONTRACT_SINGLE_CP_NO_MATCH) == 0 ||
    520                         sinceMatch < lookAhead)) {
    521                 // The last character of at least one suffix has lccc!=0,
    522                 // allowing for discontiguous contractions.
    523                 // UCA S2.1.1 only processes non-starters immediately following
    524                 // "a match in the table" (sinceMatch=1).
    525                 if(sinceMatch > 1) {
    526                     // Return to the state after the last match.
    527                     // (Return to sinceMatch=0 and re-fetch the first partially-matched character.)
    528                     backwardNumSkipped(sinceMatch, errorCode);
    529                     c = nextSkippedCodePoint(errorCode);
    530                     lookAhead -= sinceMatch - 1;
    531                     sinceMatch = 1;
    532                 }
    533                 if(d->getFCD16(c) > 0xff) {
    534                     return nextCE32FromDiscontiguousContraction(
    535                         d, suffixes, ce32, lookAhead, c, errorCode);
    536                 }
    537             }
    538             break;
    539         } else {
    540             // Continue after partial match (USTRINGTRIE_NO_VALUE) for c.
    541             // It does not have a result value, therefore it is not itself "a match in the table".
    542             // If a partially-matched c has ccc!=0 then
    543             // it might be skipped in discontiguous contraction.
    544             c = nextCp;
    545             ++sinceMatch;
    546         }
    547         ++lookAhead;
    548         match = suffixes.nextForCodePoint(c);
    549     }
    550     backwardNumSkipped(sinceMatch, errorCode);
    551     return ce32;
    552 }
    553 
    554 uint32_t
    555 CollationIterator::nextCE32FromDiscontiguousContraction(
    556         const CollationData *d, UCharsTrie &suffixes, uint32_t ce32,
    557         int32_t lookAhead, UChar32 c,
    558         UErrorCode &errorCode) {
    559     if(U_FAILURE(errorCode)) { return 0; }
    560 
    561     // UCA section 3.3.2 Contractions:
    562     // Contractions that end with non-starter characters
    563     // are known as discontiguous contractions.
    564     // ... discontiguous contractions must be detected in input text
    565     // whenever the final sequence of non-starter characters could be rearranged
    566     // so as to make a contiguous matching sequence that is canonically equivalent.
    567 
    568     // UCA: http://www.unicode.org/reports/tr10/#S2.1
    569     // S2.1 Find the longest initial substring S at each point that has a match in the table.
    570     // S2.1.1 If there are any non-starters following S, process each non-starter C.
    571     // S2.1.2 If C is not blocked from S, find if S + C has a match in the table.
    572     //     Note: A non-starter in a string is called blocked
    573     //     if there is another non-starter of the same canonical combining class or zero
    574     //     between it and the last character of canonical combining class 0.
    575     // S2.1.3 If there is a match, replace S by S + C, and remove C.
    576 
    577     // First: Is a discontiguous contraction even possible?
    578     uint16_t fcd16 = d->getFCD16(c);
    579     U_ASSERT(fcd16 > 0xff);  // The caller checked this already, as a shortcut.
    580     UChar32 nextCp = nextSkippedCodePoint(errorCode);
    581     if(nextCp < 0) {
    582         // No further text.
    583         backwardNumSkipped(1, errorCode);
    584         return ce32;
    585     }
    586     ++lookAhead;
    587     uint8_t prevCC = (uint8_t)fcd16;
    588     fcd16 = d->getFCD16(nextCp);
    589     if(fcd16 <= 0xff) {
    590         // The next code point after c is a starter (S2.1.1 "process each non-starter").
    591         backwardNumSkipped(2, errorCode);
    592         return ce32;
    593     }
    594 
    595     // We have read and matched (lookAhead-2) code points,
    596     // read non-matching c and peeked ahead at nextCp.
    597     // Return to the state before the mismatch and continue matching with nextCp.
    598     if(skipped == NULL || skipped->isEmpty()) {
    599         if(skipped == NULL) {
    600             skipped = new SkippedState();
    601             if(skipped == NULL) {
    602                 errorCode = U_MEMORY_ALLOCATION_ERROR;
    603                 return 0;
    604             }
    605         }
    606         suffixes.reset();
    607         if(lookAhead > 2) {
    608             // Replay the partial match so far.
    609             backwardNumCodePoints(lookAhead, errorCode);
    610             suffixes.firstForCodePoint(nextCodePoint(errorCode));
    611             for(int32_t i = 3; i < lookAhead; ++i) {
    612                 suffixes.nextForCodePoint(nextCodePoint(errorCode));
    613             }
    614             // Skip c (which did not match) and nextCp (which we will try now).
    615             forwardNumCodePoints(2, errorCode);
    616         }
    617         skipped->saveTrieState(suffixes);
    618     } else {
    619         // Reset to the trie state before the failed match of c.
    620         skipped->resetToTrieState(suffixes);
    621     }
    622 
    623     skipped->setFirstSkipped(c);
    624     // Number of code points read since the last match (at this point: c and nextCp).
    625     int32_t sinceMatch = 2;
    626     c = nextCp;
    627     for(;;) {
    628         UStringTrieResult match;
    629         // "If C is not blocked from S, find if S + C has a match in the table." (S2.1.2)
    630         if(prevCC < (fcd16 >> 8) && USTRINGTRIE_HAS_VALUE(match = suffixes.nextForCodePoint(c))) {
    631             // "If there is a match, replace S by S + C, and remove C." (S2.1.3)
    632             // Keep prevCC unchanged.
    633             ce32 = (uint32_t)suffixes.getValue();
    634             sinceMatch = 0;
    635             skipped->recordMatch();
    636             if(!USTRINGTRIE_HAS_NEXT(match)) { break; }
    637             skipped->saveTrieState(suffixes);
    638         } else {
    639             // No match for "S + C", skip C.
    640             skipped->skip(c);
    641             skipped->resetToTrieState(suffixes);
    642             prevCC = (uint8_t)fcd16;
    643         }
    644         if((c = nextSkippedCodePoint(errorCode)) < 0) { break; }
    645         ++sinceMatch;
    646         fcd16 = d->getFCD16(c);
    647         if(fcd16 <= 0xff) {
    648             // The next code point after c is a starter (S2.1.1 "process each non-starter").
    649             break;
    650         }
    651     }
    652     backwardNumSkipped(sinceMatch, errorCode);
    653     UBool isTopDiscontiguous = skipped->isEmpty();
    654     skipped->replaceMatch();
    655     if(isTopDiscontiguous && !skipped->isEmpty()) {
    656         // We did get a match after skipping one or more combining marks,
    657         // and we are not in a recursive discontiguous contraction.
    658         // Append CEs from the contraction ce32
    659         // and then from the combining marks that we skipped before the match.
    660         c = U_SENTINEL;
    661         for(;;) {
    662             appendCEsFromCE32(d, c, ce32, TRUE, errorCode);
    663             // Fetch CE32s for skipped combining marks from the normal data, with fallback,
    664             // rather than from the CollationData where we found the contraction.
    665             if(!skipped->hasNext()) { break; }
    666             c = skipped->next();
    667             ce32 = getDataCE32(c);
    668             if(ce32 == Collation::FALLBACK_CE32) {
    669                 d = data->base;
    670                 ce32 = d->getCE32(c);
    671             } else {
    672                 d = data;
    673             }
    674             // Note: A nested discontiguous-contraction match
    675             // replaces consumed combining marks with newly skipped ones
    676             // and resets the reading position to the beginning.
    677         }
    678         skipped->clear();
    679         ce32 = Collation::NO_CE32;  // Signal to the caller that the result is in the ceBuffer.
    680     }
    681     return ce32;
    682 }
    683 
    684 void
    685 CollationIterator::appendNumericCEs(uint32_t ce32, UBool forward, UErrorCode &errorCode) {
    686     // Collect digits.
    687     CharString digits;
    688     if(forward) {
    689         for(;;) {
    690             char digit = Collation::digitFromCE32(ce32);
    691             digits.append(digit, errorCode);
    692             if(numCpFwd == 0) { break; }
    693             UChar32 c = nextCodePoint(errorCode);
    694             if(c < 0) { break; }
    695             ce32 = data->getCE32(c);
    696             if(ce32 == Collation::FALLBACK_CE32) {
    697                 ce32 = data->base->getCE32(c);
    698             }
    699             if(!Collation::hasCE32Tag(ce32, Collation::DIGIT_TAG)) {
    700                 backwardNumCodePoints(1, errorCode);
    701                 break;
    702             }
    703             if(numCpFwd > 0) { --numCpFwd; }
    704         }
    705     } else {
    706         for(;;) {
    707             char digit = Collation::digitFromCE32(ce32);
    708             digits.append(digit, errorCode);
    709             UChar32 c = previousCodePoint(errorCode);
    710             if(c < 0) { break; }
    711             ce32 = data->getCE32(c);
    712             if(ce32 == Collation::FALLBACK_CE32) {
    713                 ce32 = data->base->getCE32(c);
    714             }
    715             if(!Collation::hasCE32Tag(ce32, Collation::DIGIT_TAG)) {
    716                 forwardNumCodePoints(1, errorCode);
    717                 break;
    718             }
    719         }
    720         // Reverse the digit string.
    721         char *p = digits.data();
    722         char *q = p + digits.length() - 1;
    723         while(p < q) {
    724             char digit = *p;
    725             *p++ = *q;
    726             *q-- = digit;
    727         }
    728     }
    729     if(U_FAILURE(errorCode)) { return; }
    730     int32_t pos = 0;
    731     do {
    732         // Skip leading zeros.
    733         while(pos < (digits.length() - 1) && digits[pos] == 0) { ++pos; }
    734         // Write a sequence of CEs for at most 254 digits at a time.
    735         int32_t segmentLength = digits.length() - pos;
    736         if(segmentLength > 254) { segmentLength = 254; }
    737         appendNumericSegmentCEs(digits.data() + pos, segmentLength, errorCode);
    738         pos += segmentLength;
    739     } while(U_SUCCESS(errorCode) && pos < digits.length());
    740 }
    741 
    742 void
    743 CollationIterator::appendNumericSegmentCEs(const char *digits, int32_t length, UErrorCode &errorCode) {
    744     U_ASSERT(1 <= length && length <= 254);
    745     U_ASSERT(length == 1 || digits[0] != 0);
    746     uint32_t numericPrimary = data->numericPrimary;
    747     // Note: We use primary byte values 2..255: digits are not compressible.
    748     if(length <= 7) {
    749         // Very dense encoding for small numbers.
    750         int32_t value = digits[0];
    751         for(int32_t i = 1; i < length; ++i) {
    752             value = value * 10 + digits[i];
    753         }
    754         // Primary weight second byte values:
    755         //     74 byte values   2.. 75 for small numbers in two-byte primary weights.
    756         //     40 byte values  76..115 for medium numbers in three-byte primary weights.
    757         //     16 byte values 116..131 for large numbers in four-byte primary weights.
    758         //    124 byte values 132..255 for very large numbers with 4..127 digit pairs.
    759         int32_t firstByte = 2;
    760         int32_t numBytes = 74;
    761         if(value < numBytes) {
    762             // Two-byte primary for 0..73, good for day & month numbers etc.
    763             uint32_t primary = numericPrimary | ((firstByte + value) << 16);
    764             ceBuffer.append(Collation::makeCE(primary), errorCode);
    765             return;
    766         }
    767         value -= numBytes;
    768         firstByte += numBytes;
    769         numBytes = 40;
    770         if(value < numBytes * 254) {
    771             // Three-byte primary for 74..10233=74+40*254-1, good for year numbers and more.
    772             uint32_t primary = numericPrimary |
    773                 ((firstByte + value / 254) << 16) | ((2 + value % 254) << 8);
    774             ceBuffer.append(Collation::makeCE(primary), errorCode);
    775             return;
    776         }
    777         value -= numBytes * 254;
    778         firstByte += numBytes;
    779         numBytes = 16;
    780         if(value < numBytes * 254 * 254) {
    781             // Four-byte primary for 10234..1042489=10234+16*254*254-1.
    782             uint32_t primary = numericPrimary | (2 + value % 254);
    783             value /= 254;
    784             primary |= (2 + value % 254) << 8;
    785             value /= 254;
    786             primary |= (firstByte + value % 254) << 16;
    787             ceBuffer.append(Collation::makeCE(primary), errorCode);
    788             return;
    789         }
    790         // original value > 1042489
    791     }
    792     U_ASSERT(length >= 7);
    793 
    794     // The second primary byte value 132..255 indicates the number of digit pairs (4..127),
    795     // then we generate primary bytes with those pairs.
    796     // Omit trailing 00 pairs.
    797     // Decrement the value for the last pair.
    798 
    799     // Set the exponent. 4 pairs->132, 5 pairs->133, ..., 127 pairs->255.
    800     int32_t numPairs = (length + 1) / 2;
    801     uint32_t primary = numericPrimary | ((132 - 4 + numPairs) << 16);
    802     // Find the length without trailing 00 pairs.
    803     while(digits[length - 1] == 0 && digits[length - 2] == 0) {
    804         length -= 2;
    805     }
    806     // Read the first pair.
    807     uint32_t pair;
    808     int32_t pos;
    809     if(length & 1) {
    810         // Only "half a pair" if we have an odd number of digits.
    811         pair = digits[0];
    812         pos = 1;
    813     } else {
    814         pair = digits[0] * 10 + digits[1];
    815         pos = 2;
    816     }
    817     pair = 11 + 2 * pair;
    818     // Add the pairs of digits between pos and length.
    819     int32_t shift = 8;
    820     while(pos < length) {
    821         if(shift == 0) {
    822             // Every three pairs/bytes we need to store a 4-byte-primary CE
    823             // and start with a new CE with the '0' primary lead byte.
    824             primary |= pair;
    825             ceBuffer.append(Collation::makeCE(primary), errorCode);
    826             primary = numericPrimary;
    827             shift = 16;
    828         } else {
    829             primary |= pair << shift;
    830             shift -= 8;
    831         }
    832         pair = 11 + 2 * (digits[pos] * 10 + digits[pos + 1]);
    833         pos += 2;
    834     }
    835     primary |= (pair - 1) << shift;
    836     ceBuffer.append(Collation::makeCE(primary), errorCode);
    837 }
    838 
    839 int64_t
    840 CollationIterator::previousCE(UVector32 &offsets, UErrorCode &errorCode) {
    841     if(ceBuffer.length > 0) {
    842         // Return the previous buffered CE.
    843         return ceBuffer.get(--ceBuffer.length);
    844     }
    845     offsets.removeAllElements();
    846     int32_t limitOffset = getOffset();
    847     UChar32 c = previousCodePoint(errorCode);
    848     if(c < 0) { return Collation::NO_CE; }
    849     if(data->isUnsafeBackward(c, isNumeric)) {
    850         return previousCEUnsafe(c, offsets, errorCode);
    851     }
    852     // Simple, safe-backwards iteration:
    853     // Get a CE going backwards, handle prefixes but no contractions.
    854     uint32_t ce32 = data->getCE32(c);
    855     const CollationData *d;
    856     if(ce32 == Collation::FALLBACK_CE32) {
    857         d = data->base;
    858         ce32 = d->getCE32(c);
    859     } else {
    860         d = data;
    861     }
    862     if(Collation::isSimpleOrLongCE32(ce32)) {
    863         return Collation::ceFromCE32(ce32);
    864     }
    865     appendCEsFromCE32(d, c, ce32, FALSE, errorCode);
    866     if(U_SUCCESS(errorCode)) {
    867         if(ceBuffer.length > 1) {
    868             offsets.addElement(getOffset(), errorCode);
    869             // For an expansion, the offset of each non-initial CE is the limit offset,
    870             // consistent with forward iteration.
    871             while(offsets.size() <= ceBuffer.length) {
    872                 offsets.addElement(limitOffset, errorCode);
    873             };
    874         }
    875         return ceBuffer.get(--ceBuffer.length);
    876     } else {
    877         return Collation::NO_CE_PRIMARY;
    878     }
    879 }
    880 
    881 int64_t
    882 CollationIterator::previousCEUnsafe(UChar32 c, UVector32 &offsets, UErrorCode &errorCode) {
    883     // We just move through the input counting safe and unsafe code points
    884     // without collecting the unsafe-backward substring into a buffer and
    885     // switching to it.
    886     // This is to keep the logic simple. Otherwise we would have to handle
    887     // prefix matching going before the backward buffer, switching
    888     // to iteration and back, etc.
    889     // In the most important case of iterating over a normal string,
    890     // reading from the string itself is already maximally fast.
    891     // The only drawback there is that after getting the CEs we always
    892     // skip backward to the safe character rather than switching out
    893     // of a backwardBuffer.
    894     // But this should not be the common case for previousCE(),
    895     // and correctness and maintainability are more important than
    896     // complex optimizations.
    897     // Find the first safe character before c.
    898     int32_t numBackward = 1;
    899     while((c = previousCodePoint(errorCode)) >= 0) {
    900         ++numBackward;
    901         if(!data->isUnsafeBackward(c, isNumeric)) {
    902             break;
    903         }
    904     }
    905     // Set the forward iteration limit.
    906     // Note: This counts code points.
    907     // We cannot enforce a limit in the middle of a surrogate pair or similar.
    908     numCpFwd = numBackward;
    909     // Reset the forward iterator.
    910     cesIndex = 0;
    911     U_ASSERT(ceBuffer.length == 0);
    912     // Go forward and collect the CEs.
    913     int32_t offset = getOffset();
    914     while(numCpFwd > 0) {
    915         // nextCE() normally reads one code point.
    916         // Contraction matching and digit specials read more and check numCpFwd.
    917         --numCpFwd;
    918         // Append one or more CEs to the ceBuffer.
    919         (void)nextCE(errorCode);
    920         U_ASSERT(U_FAILURE(errorCode) || ceBuffer.get(ceBuffer.length - 1) != Collation::NO_CE);
    921         // No need to loop for getting each expansion CE from nextCE().
    922         cesIndex = ceBuffer.length;
    923         // However, we need to write an offset for each CE.
    924         // This is for CollationElementIterator::getOffset() to return
    925         // intermediate offsets from the unsafe-backwards segment.
    926         U_ASSERT(offsets.size() < ceBuffer.length);
    927         offsets.addElement(offset, errorCode);
    928         // For an expansion, the offset of each non-initial CE is the limit offset,
    929         // consistent with forward iteration.
    930         offset = getOffset();
    931         while(offsets.size() < ceBuffer.length) {
    932             offsets.addElement(offset, errorCode);
    933         };
    934     }
    935     U_ASSERT(offsets.size() == ceBuffer.length);
    936     // End offset corresponding to just after the unsafe-backwards segment.
    937     offsets.addElement(offset, errorCode);
    938     // Reset the forward iteration limit
    939     // and move backward to before the segment for which we fetched CEs.
    940     numCpFwd = -1;
    941     backwardNumCodePoints(numBackward, errorCode);
    942     // Use the collected CEs and return the last one.
    943     cesIndex = 0;  // Avoid cesIndex > ceBuffer.length when that gets decremented.
    944     if(U_SUCCESS(errorCode)) {
    945         return ceBuffer.get(--ceBuffer.length);
    946     } else {
    947         return Collation::NO_CE_PRIMARY;
    948     }
    949 }
    950 
    951 U_NAMESPACE_END
    952 
    953 #endif  // !UCONFIG_NO_COLLATION
    954