Home | History | Annotate | Download | only in common
      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!=NULL) {
     63         return UTRIE2_GET16(trie, c);
     64     } else if(trie->data32!=NULL) {
     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!=NULL) {
     79         return UTRIE2_GET16_FROM_U16_SINGLE_LEAD(trie, c);
     80     } else if(trie->data32!=NULL) {
     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==NULL ? 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 0;
    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 0;
    148     }
    149 
    150     /* enough data for a trie header? */
    151     if(length<(int32_t)sizeof(UTrie2Header)) {
    152         *pErrorCode=U_INVALID_FORMAT_ERROR;
    153         return 0;
    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 0;
    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 0;
    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 0;
    192     }
    193 
    194     /* allocate the trie */
    195     trie=(UTrie2 *)uprv_malloc(sizeof(UTrie2));
    196     if(trie==NULL) {
    197         *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
    198         return 0;
    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=NULL;
    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=NULL;
    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 0;
    230     }
    231 
    232     if(pActualLength!=NULL) {
    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 0;
    251     }
    252 
    253     if(valueBits<0 || UTRIE2_COUNT_VALUE_BITS<=valueBits) {
    254         *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
    255         return 0;
    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==NULL) {
    271         *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
    272         return 0;
    273     }
    274     uprv_memset(trie, 0, sizeof(UTrie2));
    275     trie->memory=uprv_malloc(length);
    276     if(trie->memory==NULL) {
    277         uprv_free(trie);
    278         *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
    279         return 0;
    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=NULL;
    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=NULL;
    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 0;
    368     }
    369 
    370     return trie;
    371 }
    372 
    373 U_CAPI void U_EXPORT2
    374 utrie2_close(UTrie2 *trie) {
    375     if(trie!=NULL) {
    376         if(trie->isMemoryOwned) {
    377             uprv_free(trie->memory);
    378         }
    379         if(trie->newTrie!=NULL) {
    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 (UBool)(trie->newTrie==NULL);
    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==NULL || trie->memory==NULL || trie->newTrie!=NULL ||
    405         capacity<0 || (capacity>0 && (data==NULL || (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==NULL) {
    454         return;
    455     }
    456     if(enumValue==NULL) {
    457         enumValue=enumSameValue;
    458     }
    459 
    460     if(trie->newTrie==NULL) {
    461         /* frozen trie */
    462         idx=trie->index;
    463         U_ASSERT(idx!=NULL); /* the following code assumes trie->newTrie is not NULL when idx is NULL */
    464         data32=trie->data32;
    465 
    466         index2NullOffset=trie->index2NullOffset;
    467         nullBlock=trie->dataNullOffset;
    468     } else {
    469         /* unfrozen, mutable trie */
    470         idx=NULL;
    471         data32=trie->newTrie->data;
    472         U_ASSERT(data32!=NULL); /* the following code assumes idx is not NULL when data32 is NULL */
    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!=NULL) {
    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!=NULL) {
    555                     block=(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!=NULL ? 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!=NULL) {
    598             highValue=
    599                 data32!=NULL ?
    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
    664