tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

utrie2.cpp (21235B)


      1 // © 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 ******************************************************************************
      5 *
      6 *   Copyright (C) 2001-2014, International Business Machines
      7 *   Corporation and others.  All Rights Reserved.
      8 *
      9 ******************************************************************************
     10 *   file name:  utrie2.cpp
     11 *   encoding:   UTF-8
     12 *   tab size:   8 (not used)
     13 *   indentation:4
     14 *
     15 *   created on: 2008aug16 (starting from a copy of utrie.c)
     16 *   created by: Markus W. Scherer
     17 *
     18 *   This is a common implementation of a Unicode trie.
     19 *   It is a kind of compressed, serializable table of 16- or 32-bit values associated with
     20 *   Unicode code points (0..0x10ffff).
     21 *   This is the second common version of a Unicode trie (hence the name UTrie2).
     22 *   See utrie2.h for a comparison.
     23 *
     24 *   This file contains only the runtime and enumeration code, for read-only access.
     25 *   See utrie2_builder.c for the builder code.
     26 */
     27 #include "unicode/utypes.h"
     28 #ifdef UCPTRIE_DEBUG
     29 #include "unicode/umutablecptrie.h"
     30 #endif
     31 #include "unicode/utf.h"
     32 #include "unicode/utf8.h"
     33 #include "unicode/utf16.h"
     34 #include "cmemory.h"
     35 #include "utrie2.h"
     36 #include "utrie2_impl.h"
     37 #include "uassert.h"
     38 
     39 /* Public UTrie2 API implementation ----------------------------------------- */
     40 
     41 static uint32_t
     42 get32(const UNewTrie2 *trie, UChar32 c, UBool fromLSCP) {
     43    int32_t i2, block;
     44 
     45    if(c>=trie->highStart && (!U_IS_LEAD(c) || fromLSCP)) {
     46        return trie->data[trie->dataLength-UTRIE2_DATA_GRANULARITY];
     47    }
     48 
     49    if(U_IS_LEAD(c) && fromLSCP) {
     50        i2=(UTRIE2_LSCP_INDEX_2_OFFSET-(0xd800>>UTRIE2_SHIFT_2))+
     51            (c>>UTRIE2_SHIFT_2);
     52    } else {
     53        i2=trie->index1[c>>UTRIE2_SHIFT_1]+
     54            ((c>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK);
     55    }
     56    block=trie->index2[i2];
     57    return trie->data[block+(c&UTRIE2_DATA_MASK)];
     58 }
     59 
     60 U_CAPI uint32_t U_EXPORT2
     61 utrie2_get32(const UTrie2 *trie, UChar32 c) {
     62    if(trie->data16!=nullptr) {
     63        return UTRIE2_GET16(trie, c);
     64    } else if(trie->data32!=nullptr) {
     65        return UTRIE2_GET32(trie, c);
     66    } else if((uint32_t)c>0x10ffff) {
     67        return trie->errorValue;
     68    } else {
     69        return get32(trie->newTrie, c, true);
     70    }
     71 }
     72 
     73 U_CAPI uint32_t U_EXPORT2
     74 utrie2_get32FromLeadSurrogateCodeUnit(const UTrie2 *trie, UChar32 c) {
     75    if(!U_IS_LEAD(c)) {
     76        return trie->errorValue;
     77    }
     78    if(trie->data16!=nullptr) {
     79        return UTRIE2_GET16_FROM_U16_SINGLE_LEAD(trie, c);
     80    } else if(trie->data32!=nullptr) {
     81        return UTRIE2_GET32_FROM_U16_SINGLE_LEAD(trie, c);
     82    } else {
     83        return get32(trie->newTrie, c, false);
     84    }
     85 }
     86 
     87 static inline int32_t
     88 u8Index(const UTrie2 *trie, UChar32 c, int32_t i) {
     89    int32_t idx=
     90        _UTRIE2_INDEX_FROM_CP(
     91            trie,
     92            trie->data32==nullptr ? trie->indexLength : 0,
     93            c);
     94    return (idx<<3)|i;
     95 }
     96 
     97 U_CAPI int32_t U_EXPORT2
     98 utrie2_internalU8NextIndex(const UTrie2 *trie, UChar32 c,
     99                           const uint8_t *src, const uint8_t *limit) {
    100    int32_t i, length;
    101    i=0;
    102    /* support 64-bit pointers by avoiding cast of arbitrary difference */
    103    if((limit-src)<=7) {
    104        length=(int32_t)(limit-src);
    105    } else {
    106        length=7;
    107    }
    108    c=utf8_nextCharSafeBody(src, &i, length, c, -1);
    109    return u8Index(trie, c, i);
    110 }
    111 
    112 U_CAPI int32_t U_EXPORT2
    113 utrie2_internalU8PrevIndex(const UTrie2 *trie, UChar32 c,
    114                           const uint8_t *start, const uint8_t *src) {
    115    int32_t i, length;
    116    /* support 64-bit pointers by avoiding cast of arbitrary difference */
    117    if((src-start)<=7) {
    118        i=length=(int32_t)(src-start);
    119    } else {
    120        i=length=7;
    121        start=src-7;
    122    }
    123    c=utf8_prevCharSafeBody(start, 0, &i, c, -1);
    124    i=length-i;  /* number of bytes read backward from src */
    125    return u8Index(trie, c, i);
    126 }
    127 
    128 U_CAPI UTrie2 * U_EXPORT2
    129 utrie2_openFromSerialized(UTrie2ValueBits valueBits,
    130                          const void *data, int32_t length, int32_t *pActualLength,
    131                          UErrorCode *pErrorCode) {
    132    const UTrie2Header *header;
    133    const uint16_t *p16;
    134    int32_t actualLength;
    135 
    136    UTrie2 tempTrie;
    137    UTrie2 *trie;
    138 
    139    if(U_FAILURE(*pErrorCode)) {
    140        return nullptr;
    141    }
    142 
    143    if( length<=0 || (U_POINTER_MASK_LSB(data, 3)!=0) ||
    144        valueBits<0 || UTRIE2_COUNT_VALUE_BITS<=valueBits
    145    ) {
    146        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
    147        return nullptr;
    148    }
    149 
    150    /* enough data for a trie header? */
    151    if(length<(int32_t)sizeof(UTrie2Header)) {
    152        *pErrorCode=U_INVALID_FORMAT_ERROR;
    153        return nullptr;
    154    }
    155 
    156    /* check the signature */
    157    header=(const UTrie2Header *)data;
    158    if(header->signature!=UTRIE2_SIG) {
    159        *pErrorCode=U_INVALID_FORMAT_ERROR;
    160        return nullptr;
    161    }
    162 
    163    /* get the options */
    164    if(valueBits!=(UTrie2ValueBits)(header->options&UTRIE2_OPTIONS_VALUE_BITS_MASK)) {
    165        *pErrorCode=U_INVALID_FORMAT_ERROR;
    166        return nullptr;
    167    }
    168 
    169    /* get the length values and offsets */
    170    uprv_memset(&tempTrie, 0, sizeof(tempTrie));
    171    tempTrie.indexLength=header->indexLength;
    172    tempTrie.dataLength=header->shiftedDataLength<<UTRIE2_INDEX_SHIFT;
    173    tempTrie.index2NullOffset=header->index2NullOffset;
    174    tempTrie.dataNullOffset=header->dataNullOffset;
    175 
    176    tempTrie.highStart=header->shiftedHighStart<<UTRIE2_SHIFT_1;
    177    tempTrie.highValueIndex=tempTrie.dataLength-UTRIE2_DATA_GRANULARITY;
    178    if(valueBits==UTRIE2_16_VALUE_BITS) {
    179        tempTrie.highValueIndex+=tempTrie.indexLength;
    180    }
    181 
    182    /* calculate the actual length */
    183    actualLength=(int32_t)sizeof(UTrie2Header)+tempTrie.indexLength*2;
    184    if(valueBits==UTRIE2_16_VALUE_BITS) {
    185        actualLength+=tempTrie.dataLength*2;
    186    } else {
    187        actualLength+=tempTrie.dataLength*4;
    188    }
    189    if(length<actualLength) {
    190        *pErrorCode=U_INVALID_FORMAT_ERROR;  /* not enough bytes */
    191        return nullptr;
    192    }
    193 
    194    /* allocate the trie */
    195    trie=(UTrie2 *)uprv_malloc(sizeof(UTrie2));
    196    if(trie==nullptr) {
    197        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
    198        return nullptr;
    199    }
    200    uprv_memcpy(trie, &tempTrie, sizeof(tempTrie));
    201    trie->memory=(uint32_t *)data;
    202    trie->length=actualLength;
    203    trie->isMemoryOwned=false;
    204 #ifdef UTRIE2_DEBUG
    205    trie->name="fromSerialized";
    206 #endif
    207 
    208    /* set the pointers to its index and data arrays */
    209    p16=(const uint16_t *)(header+1);
    210    trie->index=p16;
    211    p16+=trie->indexLength;
    212 
    213    /* get the data */
    214    switch(valueBits) {
    215    case UTRIE2_16_VALUE_BITS:
    216        trie->data16=p16;
    217        trie->data32=nullptr;
    218        trie->initialValue=trie->index[trie->dataNullOffset];
    219        trie->errorValue=trie->data16[UTRIE2_BAD_UTF8_DATA_OFFSET];
    220        break;
    221    case UTRIE2_32_VALUE_BITS:
    222        trie->data16=nullptr;
    223        trie->data32=(const uint32_t *)p16;
    224        trie->initialValue=trie->data32[trie->dataNullOffset];
    225        trie->errorValue=trie->data32[UTRIE2_BAD_UTF8_DATA_OFFSET];
    226        break;
    227    default:
    228        *pErrorCode=U_INVALID_FORMAT_ERROR;
    229        return nullptr;
    230    }
    231 
    232    if(pActualLength!=nullptr) {
    233        *pActualLength=actualLength;
    234    }
    235    return trie;
    236 }
    237 
    238 U_CAPI UTrie2 * U_EXPORT2
    239 utrie2_openDummy(UTrie2ValueBits valueBits,
    240                 uint32_t initialValue, uint32_t errorValue,
    241                 UErrorCode *pErrorCode) {
    242    UTrie2 *trie;
    243    UTrie2Header *header;
    244    uint32_t *p;
    245    uint16_t *dest16;
    246    int32_t indexLength, dataLength, length, i;
    247    int32_t dataMove;  /* >0 if the data is moved to the end of the index array */
    248 
    249    if(U_FAILURE(*pErrorCode)) {
    250        return nullptr;
    251    }
    252 
    253    if(valueBits<0 || UTRIE2_COUNT_VALUE_BITS<=valueBits) {
    254        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
    255        return nullptr;
    256    }
    257 
    258    /* calculate the total length of the dummy trie data */
    259    indexLength=UTRIE2_INDEX_1_OFFSET;
    260    dataLength=UTRIE2_DATA_START_OFFSET+UTRIE2_DATA_GRANULARITY;
    261    length=(int32_t)sizeof(UTrie2Header)+indexLength*2;
    262    if(valueBits==UTRIE2_16_VALUE_BITS) {
    263        length+=dataLength*2;
    264    } else {
    265        length+=dataLength*4;
    266    }
    267 
    268    /* allocate the trie */
    269    trie=(UTrie2 *)uprv_malloc(sizeof(UTrie2));
    270    if(trie==nullptr) {
    271        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
    272        return nullptr;
    273    }
    274    uprv_memset(trie, 0, sizeof(UTrie2));
    275    trie->memory=uprv_malloc(length);
    276    if(trie->memory==nullptr) {
    277        uprv_free(trie);
    278        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
    279        return nullptr;
    280    }
    281    trie->length=length;
    282    trie->isMemoryOwned=true;
    283 
    284    /* set the UTrie2 fields */
    285    if(valueBits==UTRIE2_16_VALUE_BITS) {
    286        dataMove=indexLength;
    287    } else {
    288        dataMove=0;
    289    }
    290 
    291    trie->indexLength=indexLength;
    292    trie->dataLength=dataLength;
    293    trie->index2NullOffset=UTRIE2_INDEX_2_OFFSET;
    294    trie->dataNullOffset=(uint16_t)dataMove;
    295    trie->initialValue=initialValue;
    296    trie->errorValue=errorValue;
    297    trie->highStart=0;
    298    trie->highValueIndex=dataMove+UTRIE2_DATA_START_OFFSET;
    299 #ifdef UTRIE2_DEBUG
    300    trie->name="dummy";
    301 #endif
    302 
    303    /* set the header fields */
    304    header=(UTrie2Header *)trie->memory;
    305 
    306    header->signature=UTRIE2_SIG; /* "Tri2" */
    307    header->options=(uint16_t)valueBits;
    308 
    309    header->indexLength=(uint16_t)indexLength;
    310    header->shiftedDataLength=(uint16_t)(dataLength>>UTRIE2_INDEX_SHIFT);
    311    header->index2NullOffset=(uint16_t)UTRIE2_INDEX_2_OFFSET;
    312    header->dataNullOffset=(uint16_t)dataMove;
    313    header->shiftedHighStart=0;
    314 
    315    /* fill the index and data arrays */
    316    dest16=(uint16_t *)(header+1);
    317    trie->index=dest16;
    318 
    319    /* write the index-2 array values shifted right by UTRIE2_INDEX_SHIFT */
    320    for(i=0; i<UTRIE2_INDEX_2_BMP_LENGTH; ++i) {
    321        *dest16++=(uint16_t)(dataMove>>UTRIE2_INDEX_SHIFT);  /* null data block */
    322    }
    323 
    324    /* write UTF-8 2-byte index-2 values, not right-shifted */
    325    for(i=0; i<(0xc2-0xc0); ++i) {                                  /* C0..C1 */
    326        *dest16++=(uint16_t)(dataMove+UTRIE2_BAD_UTF8_DATA_OFFSET);
    327    }
    328    for(; i<(0xe0-0xc0); ++i) {                                     /* C2..DF */
    329        *dest16++=(uint16_t)dataMove;
    330    }
    331 
    332    /* write the 16/32-bit data array */
    333    switch(valueBits) {
    334    case UTRIE2_16_VALUE_BITS:
    335        /* write 16-bit data values */
    336        trie->data16=dest16;
    337        trie->data32=nullptr;
    338        for(i=0; i<0x80; ++i) {
    339            *dest16++=(uint16_t)initialValue;
    340        }
    341        for(; i<0xc0; ++i) {
    342            *dest16++=(uint16_t)errorValue;
    343        }
    344        /* highValue and reserved values */
    345        for(i=0; i<UTRIE2_DATA_GRANULARITY; ++i) {
    346            *dest16++=(uint16_t)initialValue;
    347        }
    348        break;
    349    case UTRIE2_32_VALUE_BITS:
    350        /* write 32-bit data values */
    351        p=(uint32_t *)dest16;
    352        trie->data16=nullptr;
    353        trie->data32=p;
    354        for(i=0; i<0x80; ++i) {
    355            *p++=initialValue;
    356        }
    357        for(; i<0xc0; ++i) {
    358            *p++=errorValue;
    359        }
    360        /* highValue and reserved values */
    361        for(i=0; i<UTRIE2_DATA_GRANULARITY; ++i) {
    362            *p++=initialValue;
    363        }
    364        break;
    365    default:
    366        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
    367        return nullptr;
    368    }
    369 
    370    return trie;
    371 }
    372 
    373 U_CAPI void U_EXPORT2
    374 utrie2_close(UTrie2 *trie) {
    375    if(trie!=nullptr) {
    376        if(trie->isMemoryOwned) {
    377            uprv_free(trie->memory);
    378        }
    379        if(trie->newTrie!=nullptr) {
    380            uprv_free(trie->newTrie->data);
    381 #ifdef UCPTRIE_DEBUG
    382            umutablecptrie_close(trie->newTrie->t3);
    383 #endif
    384            uprv_free(trie->newTrie);
    385        }
    386        uprv_free(trie);
    387    }
    388 }
    389 
    390 U_CAPI UBool U_EXPORT2
    391 utrie2_isFrozen(const UTrie2 *trie) {
    392    return trie->newTrie==nullptr;
    393 }
    394 
    395 U_CAPI int32_t U_EXPORT2
    396 utrie2_serialize(const UTrie2 *trie,
    397                 void *data, int32_t capacity,
    398                 UErrorCode *pErrorCode) {
    399    /* argument check */
    400    if(U_FAILURE(*pErrorCode)) {
    401        return 0;
    402    }
    403 
    404    if( trie==nullptr || trie->memory==nullptr || trie->newTrie!=nullptr ||
    405        capacity<0 || (capacity>0 && (data==nullptr || (U_POINTER_MASK_LSB(data, 3)!=0)))
    406    ) {
    407        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
    408        return 0;
    409    }
    410 
    411    if(capacity>=trie->length) {
    412        uprv_memcpy(data, trie->memory, trie->length);
    413    } else {
    414        *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
    415    }
    416    return trie->length;
    417 }
    418 
    419 /* enumeration -------------------------------------------------------------- */
    420 
    421 #define MIN_VALUE(a, b) ((a)<(b) ? (a) : (b))
    422 
    423 /* default UTrie2EnumValue() returns the input value itself */
    424 static uint32_t U_CALLCONV
    425 enumSameValue(const void * /*context*/, uint32_t value) {
    426    return value;
    427 }
    428 
    429 /**
    430 * Enumerate all ranges of code points with the same relevant values.
    431 * The values are transformed from the raw trie entries by the enumValue function.
    432 *
    433 * Currently requires start<limit and both start and limit must be multiples
    434 * of UTRIE2_DATA_BLOCK_LENGTH.
    435 *
    436 * Optimizations:
    437 * - Skip a whole block if we know that it is filled with a single value,
    438 *   and it is the same as we visited just before.
    439 * - Handle the null block specially because we know a priori that it is filled
    440 *   with a single value.
    441 */
    442 static void
    443 enumEitherTrie(const UTrie2 *trie,
    444               UChar32 start, UChar32 limit,
    445               UTrie2EnumValue *enumValue, UTrie2EnumRange *enumRange, const void *context) {
    446    const uint32_t *data32;
    447    const uint16_t *idx;
    448 
    449    uint32_t value, prevValue, initialValue;
    450    UChar32 c, prev, highStart;
    451    int32_t j, i2Block, prevI2Block, index2NullOffset, block, prevBlock, nullBlock;
    452 
    453    if(enumRange==nullptr) {
    454        return;
    455    }
    456    if(enumValue==nullptr) {
    457        enumValue=enumSameValue;
    458    }
    459 
    460    if(trie->newTrie==nullptr) {
    461        /* frozen trie */
    462        idx=trie->index;
    463        U_ASSERT(idx!=nullptr); /* the following code assumes trie->newTrie is not nullptr when idx is nullptr */
    464        data32=trie->data32;
    465 
    466        index2NullOffset=trie->index2NullOffset;
    467        nullBlock=trie->dataNullOffset;
    468    } else {
    469        /* unfrozen, mutable trie */
    470        idx=nullptr;
    471        data32=trie->newTrie->data;
    472        U_ASSERT(data32!=nullptr); /* the following code assumes idx is not nullptr when data32 is nullptr */
    473 
    474        index2NullOffset=trie->newTrie->index2NullOffset;
    475        nullBlock=trie->newTrie->dataNullOffset;
    476    }
    477 
    478    highStart=trie->highStart;
    479 
    480    /* get the enumeration value that corresponds to an initial-value trie data entry */
    481    initialValue=enumValue(context, trie->initialValue);
    482 
    483    /* set variables for previous range */
    484    prevI2Block=-1;
    485    prevBlock=-1;
    486    prev=start;
    487    prevValue=0;
    488 
    489    /* enumerate index-2 blocks */
    490    for(c=start; c<limit && c<highStart;) {
    491        /* Code point limit for iterating inside this i2Block. */
    492        UChar32 tempLimit=c+UTRIE2_CP_PER_INDEX_1_ENTRY;
    493        if(limit<tempLimit) {
    494            tempLimit=limit;
    495        }
    496        if(c<=0xffff) {
    497            if(!U_IS_SURROGATE(c)) {
    498                i2Block=c>>UTRIE2_SHIFT_2;
    499            } else if(U_IS_SURROGATE_LEAD(c)) {
    500                /*
    501                 * Enumerate values for lead surrogate code points, not code units:
    502                 * This special block has half the normal length.
    503                 */
    504                i2Block=UTRIE2_LSCP_INDEX_2_OFFSET;
    505                tempLimit=MIN_VALUE(0xdc00, limit);
    506            } else {
    507                /*
    508                 * Switch back to the normal part of the index-2 table.
    509                 * Enumerate the second half of the surrogates block.
    510                 */
    511                i2Block=0xd800>>UTRIE2_SHIFT_2;
    512                tempLimit=MIN_VALUE(0xe000, limit);
    513            }
    514        } else {
    515            /* supplementary code points */
    516            if(idx!=nullptr) {
    517                i2Block=idx[(UTRIE2_INDEX_1_OFFSET-UTRIE2_OMITTED_BMP_INDEX_1_LENGTH)+
    518                              (c>>UTRIE2_SHIFT_1)];
    519            } else {
    520                i2Block=trie->newTrie->index1[c>>UTRIE2_SHIFT_1];
    521            }
    522            if(i2Block==prevI2Block && (c-prev)>=UTRIE2_CP_PER_INDEX_1_ENTRY) {
    523                /*
    524                 * The index-2 block is the same as the previous one, and filled with prevValue.
    525                 * Only possible for supplementary code points because the linear-BMP index-2
    526                 * table creates unique i2Block values.
    527                 */
    528                c+=UTRIE2_CP_PER_INDEX_1_ENTRY;
    529                continue;
    530            }
    531        }
    532        prevI2Block=i2Block;
    533        if(i2Block==index2NullOffset) {
    534            /* this is the null index-2 block */
    535            if(prevValue!=initialValue) {
    536                if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
    537                    return;
    538                }
    539                prevBlock=nullBlock;
    540                prev=c;
    541                prevValue=initialValue;
    542            }
    543            c+=UTRIE2_CP_PER_INDEX_1_ENTRY;
    544        } else {
    545            /* enumerate data blocks for one index-2 block */
    546            int32_t i2, i2Limit;
    547            i2=(c>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK;
    548            if((c>>UTRIE2_SHIFT_1)==(tempLimit>>UTRIE2_SHIFT_1)) {
    549                i2Limit=(tempLimit>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK;
    550            } else {
    551                i2Limit=UTRIE2_INDEX_2_BLOCK_LENGTH;
    552            }
    553            for(; i2<i2Limit; ++i2) {
    554                if(idx!=nullptr) {
    555                    block = static_cast<int32_t>(idx[i2Block + i2]) << UTRIE2_INDEX_SHIFT;
    556                } else {
    557                    block=trie->newTrie->index2[i2Block+i2];
    558                }
    559                if(block==prevBlock && (c-prev)>=UTRIE2_DATA_BLOCK_LENGTH) {
    560                    /* the block is the same as the previous one, and filled with prevValue */
    561                    c+=UTRIE2_DATA_BLOCK_LENGTH;
    562                    continue;
    563                }
    564                prevBlock=block;
    565                if(block==nullBlock) {
    566                    /* this is the null data block */
    567                    if(prevValue!=initialValue) {
    568                        if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
    569                            return;
    570                        }
    571                        prev=c;
    572                        prevValue=initialValue;
    573                    }
    574                    c+=UTRIE2_DATA_BLOCK_LENGTH;
    575                } else {
    576                    for(j=0; j<UTRIE2_DATA_BLOCK_LENGTH; ++j) {
    577                        value=enumValue(context, data32!=nullptr ? data32[block+j] : idx[block+j]);
    578                        if(value!=prevValue) {
    579                            if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
    580                                return;
    581                            }
    582                            prev=c;
    583                            prevValue=value;
    584                        }
    585                        ++c;
    586                    }
    587                }
    588            }
    589        }
    590    }
    591 
    592    if(c>limit) {
    593        c=limit;  /* could be higher if in the index2NullOffset */
    594    } else if(c<limit) {
    595        /* c==highStart<limit */
    596        uint32_t highValue;
    597        if(idx!=nullptr) {
    598            highValue=
    599                data32!=nullptr ?
    600                    data32[trie->highValueIndex] :
    601                    idx[trie->highValueIndex];
    602        } else {
    603            highValue=trie->newTrie->data[trie->newTrie->dataLength-UTRIE2_DATA_GRANULARITY];
    604        }
    605        value=enumValue(context, highValue);
    606        if(value!=prevValue) {
    607            if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
    608                return;
    609            }
    610            prev=c;
    611            prevValue=value;
    612        }
    613        c=limit;
    614    }
    615 
    616    /* deliver last range */
    617    enumRange(context, prev, c-1, prevValue);
    618 }
    619 
    620 U_CAPI void U_EXPORT2
    621 utrie2_enum(const UTrie2 *trie,
    622            UTrie2EnumValue *enumValue, UTrie2EnumRange *enumRange, const void *context) {
    623    enumEitherTrie(trie, 0, 0x110000, enumValue, enumRange, context);
    624 }
    625 
    626 U_CAPI void U_EXPORT2
    627 utrie2_enumForLeadSurrogate(const UTrie2 *trie, UChar32 lead,
    628                            UTrie2EnumValue *enumValue, UTrie2EnumRange *enumRange,
    629                            const void *context) {
    630    if(!U16_IS_LEAD(lead)) {
    631        return;
    632    }
    633    lead=(lead-0xd7c0)<<10;   /* start code point */
    634    enumEitherTrie(trie, lead, lead+0x400, enumValue, enumRange, context);
    635 }
    636 
    637 /* C++ convenience wrappers ------------------------------------------------- */
    638 
    639 U_NAMESPACE_BEGIN
    640 
    641 uint16_t BackwardUTrie2StringIterator::previous16() {
    642    codePointLimit=codePointStart;
    643    if(start>=codePointStart) {
    644        codePoint=U_SENTINEL;
    645        return static_cast<uint16_t>(trie->errorValue);
    646    }
    647    uint16_t result;
    648    UTRIE2_U16_PREV16(trie, start, codePointStart, codePoint, result);
    649    return result;
    650 }
    651 
    652 uint16_t ForwardUTrie2StringIterator::next16() {
    653    codePointStart=codePointLimit;
    654    if(codePointLimit==limit) {
    655        codePoint=U_SENTINEL;
    656        return static_cast<uint16_t>(trie->errorValue);
    657    }
    658    uint16_t result;
    659    UTRIE2_U16_NEXT16(trie, codePointLimit, limit, codePoint, result);
    660    return result;
    661 }
    662 
    663 U_NAMESPACE_END