Coverage Report

Created: 2023-02-22 06:51

/src/icu/source/common/utrie2.cpp
Line
Count
Source (jump to first uncovered line)
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
0
get32(const UNewTrie2 *trie, UChar32 c, UBool fromLSCP) {
43
0
    int32_t i2, block;
44
45
0
    if(c>=trie->highStart && (!U_IS_LEAD(c) || fromLSCP)) {
46
0
        return trie->data[trie->dataLength-UTRIE2_DATA_GRANULARITY];
47
0
    }
48
49
0
    if(U_IS_LEAD(c) && fromLSCP) {
50
0
        i2=(UTRIE2_LSCP_INDEX_2_OFFSET-(0xd800>>UTRIE2_SHIFT_2))+
51
0
            (c>>UTRIE2_SHIFT_2);
52
0
    } else {
53
0
        i2=trie->index1[c>>UTRIE2_SHIFT_1]+
54
0
            ((c>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK);
55
0
    }
56
0
    block=trie->index2[i2];
57
0
    return trie->data[block+(c&UTRIE2_DATA_MASK)];
58
0
}
59
60
U_CAPI uint32_t U_EXPORT2
61
0
utrie2_get32(const UTrie2 *trie, UChar32 c) {
62
0
    if(trie->data16!=NULL) {
63
0
        return UTRIE2_GET16(trie, c);
64
0
    } else if(trie->data32!=NULL) {
65
0
        return UTRIE2_GET32(trie, c);
66
0
    } else if((uint32_t)c>0x10ffff) {
67
0
        return trie->errorValue;
68
0
    } else {
69
0
        return get32(trie->newTrie, c, TRUE);
70
0
    }
71
0
}
72
73
U_CAPI uint32_t U_EXPORT2
74
0
utrie2_get32FromLeadSurrogateCodeUnit(const UTrie2 *trie, UChar32 c) {
75
0
    if(!U_IS_LEAD(c)) {
76
0
        return trie->errorValue;
77
0
    }
78
0
    if(trie->data16!=NULL) {
79
0
        return UTRIE2_GET16_FROM_U16_SINGLE_LEAD(trie, c);
80
0
    } else if(trie->data32!=NULL) {
81
0
        return UTRIE2_GET32_FROM_U16_SINGLE_LEAD(trie, c);
82
0
    } else {
83
0
        return get32(trie->newTrie, c, FALSE);
84
0
    }
85
0
}
86
87
static inline int32_t
88
0
u8Index(const UTrie2 *trie, UChar32 c, int32_t i) {
89
0
    int32_t idx=
90
0
        _UTRIE2_INDEX_FROM_CP(
91
0
            trie,
92
0
            trie->data32==NULL ? trie->indexLength : 0,
93
0
            c);
94
0
    return (idx<<3)|i;
95
0
}
96
97
U_CAPI int32_t U_EXPORT2
98
utrie2_internalU8NextIndex(const UTrie2 *trie, UChar32 c,
99
0
                           const uint8_t *src, const uint8_t *limit) {
100
0
    int32_t i, length;
101
0
    i=0;
102
    /* support 64-bit pointers by avoiding cast of arbitrary difference */
103
0
    if((limit-src)<=7) {
104
0
        length=(int32_t)(limit-src);
105
0
    } else {
106
0
        length=7;
107
0
    }
108
0
    c=utf8_nextCharSafeBody(src, &i, length, c, -1);
109
0
    return u8Index(trie, c, i);
110
0
}
111
112
U_CAPI int32_t U_EXPORT2
113
utrie2_internalU8PrevIndex(const UTrie2 *trie, UChar32 c,
114
0
                           const uint8_t *start, const uint8_t *src) {
115
0
    int32_t i, length;
116
    /* support 64-bit pointers by avoiding cast of arbitrary difference */
117
0
    if((src-start)<=7) {
118
0
        i=length=(int32_t)(src-start);
119
0
    } else {
120
0
        i=length=7;
121
0
        start=src-7;
122
0
    }
123
0
    c=utf8_prevCharSafeBody(start, 0, &i, c, -1);
124
0
    i=length-i;  /* number of bytes read backward from src */
125
0
    return u8Index(trie, c, i);
126
0
}
127
128
U_CAPI UTrie2 * U_EXPORT2
129
utrie2_openFromSerialized(UTrie2ValueBits valueBits,
130
                          const void *data, int32_t length, int32_t *pActualLength,
131
0
                          UErrorCode *pErrorCode) {
132
0
    const UTrie2Header *header;
133
0
    const uint16_t *p16;
134
0
    int32_t actualLength;
135
136
0
    UTrie2 tempTrie;
137
0
    UTrie2 *trie;
138
139
0
    if(U_FAILURE(*pErrorCode)) {
140
0
        return 0;
141
0
    }
142
143
0
    if( length<=0 || (U_POINTER_MASK_LSB(data, 3)!=0) ||
144
0
        valueBits<0 || UTRIE2_COUNT_VALUE_BITS<=valueBits
145
0
    ) {
146
0
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
147
0
        return 0;
148
0
    }
149
150
    /* enough data for a trie header? */
151
0
    if(length<(int32_t)sizeof(UTrie2Header)) {
152
0
        *pErrorCode=U_INVALID_FORMAT_ERROR;
153
0
        return 0;
154
0
    }
155
156
    /* check the signature */
157
0
    header=(const UTrie2Header *)data;
158
0
    if(header->signature!=UTRIE2_SIG) {
159
0
        *pErrorCode=U_INVALID_FORMAT_ERROR;
160
0
        return 0;
161
0
    }
162
163
    /* get the options */
164
0
    if(valueBits!=(UTrie2ValueBits)(header->options&UTRIE2_OPTIONS_VALUE_BITS_MASK)) {
165
0
        *pErrorCode=U_INVALID_FORMAT_ERROR;
166
0
        return 0;
167
0
    }
168
169
    /* get the length values and offsets */
170
0
    uprv_memset(&tempTrie, 0, sizeof(tempTrie));
171
0
    tempTrie.indexLength=header->indexLength;
172
0
    tempTrie.dataLength=header->shiftedDataLength<<UTRIE2_INDEX_SHIFT;
173
0
    tempTrie.index2NullOffset=header->index2NullOffset;
174
0
    tempTrie.dataNullOffset=header->dataNullOffset;
175
176
0
    tempTrie.highStart=header->shiftedHighStart<<UTRIE2_SHIFT_1;
177
0
    tempTrie.highValueIndex=tempTrie.dataLength-UTRIE2_DATA_GRANULARITY;
178
0
    if(valueBits==UTRIE2_16_VALUE_BITS) {
179
0
        tempTrie.highValueIndex+=tempTrie.indexLength;
180
0
    }
181
182
    /* calculate the actual length */
183
0
    actualLength=(int32_t)sizeof(UTrie2Header)+tempTrie.indexLength*2;
184
0
    if(valueBits==UTRIE2_16_VALUE_BITS) {
185
0
        actualLength+=tempTrie.dataLength*2;
186
0
    } else {
187
0
        actualLength+=tempTrie.dataLength*4;
188
0
    }
189
0
    if(length<actualLength) {
190
0
        *pErrorCode=U_INVALID_FORMAT_ERROR;  /* not enough bytes */
191
0
        return 0;
192
0
    }
193
194
    /* allocate the trie */
195
0
    trie=(UTrie2 *)uprv_malloc(sizeof(UTrie2));
196
0
    if(trie==NULL) {
197
0
        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
198
0
        return 0;
199
0
    }
200
0
    uprv_memcpy(trie, &tempTrie, sizeof(tempTrie));
201
0
    trie->memory=(uint32_t *)data;
202
0
    trie->length=actualLength;
203
0
    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
0
    p16=(const uint16_t *)(header+1);
210
0
    trie->index=p16;
211
0
    p16+=trie->indexLength;
212
213
    /* get the data */
214
0
    switch(valueBits) {
215
0
    case UTRIE2_16_VALUE_BITS:
216
0
        trie->data16=p16;
217
0
        trie->data32=NULL;
218
0
        trie->initialValue=trie->index[trie->dataNullOffset];
219
0
        trie->errorValue=trie->data16[UTRIE2_BAD_UTF8_DATA_OFFSET];
220
0
        break;
221
0
    case UTRIE2_32_VALUE_BITS:
222
0
        trie->data16=NULL;
223
0
        trie->data32=(const uint32_t *)p16;
224
0
        trie->initialValue=trie->data32[trie->dataNullOffset];
225
0
        trie->errorValue=trie->data32[UTRIE2_BAD_UTF8_DATA_OFFSET];
226
0
        break;
227
0
    default:
228
0
        *pErrorCode=U_INVALID_FORMAT_ERROR;
229
0
        return 0;
230
0
    }
231
232
0
    if(pActualLength!=NULL) {
233
0
        *pActualLength=actualLength;
234
0
    }
235
0
    return trie;
236
0
}
237
238
U_CAPI UTrie2 * U_EXPORT2
239
utrie2_openDummy(UTrie2ValueBits valueBits,
240
                 uint32_t initialValue, uint32_t errorValue,
241
0
                 UErrorCode *pErrorCode) {
242
0
    UTrie2 *trie;
243
0
    UTrie2Header *header;
244
0
    uint32_t *p;
245
0
    uint16_t *dest16;
246
0
    int32_t indexLength, dataLength, length, i;
247
0
    int32_t dataMove;  /* >0 if the data is moved to the end of the index array */
248
249
0
    if(U_FAILURE(*pErrorCode)) {
250
0
        return 0;
251
0
    }
252
253
0
    if(valueBits<0 || UTRIE2_COUNT_VALUE_BITS<=valueBits) {
254
0
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
255
0
        return 0;
256
0
    }
257
258
    /* calculate the total length of the dummy trie data */
259
0
    indexLength=UTRIE2_INDEX_1_OFFSET;
260
0
    dataLength=UTRIE2_DATA_START_OFFSET+UTRIE2_DATA_GRANULARITY;
261
0
    length=(int32_t)sizeof(UTrie2Header)+indexLength*2;
262
0
    if(valueBits==UTRIE2_16_VALUE_BITS) {
263
0
        length+=dataLength*2;
264
0
    } else {
265
0
        length+=dataLength*4;
266
0
    }
267
268
    /* allocate the trie */
269
0
    trie=(UTrie2 *)uprv_malloc(sizeof(UTrie2));
270
0
    if(trie==NULL) {
271
0
        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
272
0
        return 0;
273
0
    }
274
0
    uprv_memset(trie, 0, sizeof(UTrie2));
275
0
    trie->memory=uprv_malloc(length);
276
0
    if(trie->memory==NULL) {
277
0
        uprv_free(trie);
278
0
        *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
279
0
        return 0;
280
0
    }
281
0
    trie->length=length;
282
0
    trie->isMemoryOwned=TRUE;
283
284
    /* set the UTrie2 fields */
285
0
    if(valueBits==UTRIE2_16_VALUE_BITS) {
286
0
        dataMove=indexLength;
287
0
    } else {
288
0
        dataMove=0;
289
0
    }
290
291
0
    trie->indexLength=indexLength;
292
0
    trie->dataLength=dataLength;
293
0
    trie->index2NullOffset=UTRIE2_INDEX_2_OFFSET;
294
0
    trie->dataNullOffset=(uint16_t)dataMove;
295
0
    trie->initialValue=initialValue;
296
0
    trie->errorValue=errorValue;
297
0
    trie->highStart=0;
298
0
    trie->highValueIndex=dataMove+UTRIE2_DATA_START_OFFSET;
299
#ifdef UTRIE2_DEBUG
300
    trie->name="dummy";
301
#endif
302
303
    /* set the header fields */
304
0
    header=(UTrie2Header *)trie->memory;
305
306
0
    header->signature=UTRIE2_SIG; /* "Tri2" */
307
0
    header->options=(uint16_t)valueBits;
308
309
0
    header->indexLength=(uint16_t)indexLength;
310
0
    header->shiftedDataLength=(uint16_t)(dataLength>>UTRIE2_INDEX_SHIFT);
311
0
    header->index2NullOffset=(uint16_t)UTRIE2_INDEX_2_OFFSET;
312
0
    header->dataNullOffset=(uint16_t)dataMove;
313
0
    header->shiftedHighStart=0;
314
315
    /* fill the index and data arrays */
316
0
    dest16=(uint16_t *)(header+1);
317
0
    trie->index=dest16;
318
319
    /* write the index-2 array values shifted right by UTRIE2_INDEX_SHIFT */
320
0
    for(i=0; i<UTRIE2_INDEX_2_BMP_LENGTH; ++i) {
321
0
        *dest16++=(uint16_t)(dataMove>>UTRIE2_INDEX_SHIFT);  /* null data block */
322
0
    }
323
324
    /* write UTF-8 2-byte index-2 values, not right-shifted */
325
0
    for(i=0; i<(0xc2-0xc0); ++i) {                                  /* C0..C1 */
326
0
        *dest16++=(uint16_t)(dataMove+UTRIE2_BAD_UTF8_DATA_OFFSET);
327
0
    }
328
0
    for(; i<(0xe0-0xc0); ++i) {                                     /* C2..DF */
329
0
        *dest16++=(uint16_t)dataMove;
330
0
    }
331
332
    /* write the 16/32-bit data array */
333
0
    switch(valueBits) {
334
0
    case UTRIE2_16_VALUE_BITS:
335
        /* write 16-bit data values */
336
0
        trie->data16=dest16;
337
0
        trie->data32=NULL;
338
0
        for(i=0; i<0x80; ++i) {
339
0
            *dest16++=(uint16_t)initialValue;
340
0
        }
341
0
        for(; i<0xc0; ++i) {
342
0
            *dest16++=(uint16_t)errorValue;
343
0
        }
344
        /* highValue and reserved values */
345
0
        for(i=0; i<UTRIE2_DATA_GRANULARITY; ++i) {
346
0
            *dest16++=(uint16_t)initialValue;
347
0
        }
348
0
        break;
349
0
    case UTRIE2_32_VALUE_BITS:
350
        /* write 32-bit data values */
351
0
        p=(uint32_t *)dest16;
352
0
        trie->data16=NULL;
353
0
        trie->data32=p;
354
0
        for(i=0; i<0x80; ++i) {
355
0
            *p++=initialValue;
356
0
        }
357
0
        for(; i<0xc0; ++i) {
358
0
            *p++=errorValue;
359
0
        }
360
        /* highValue and reserved values */
361
0
        for(i=0; i<UTRIE2_DATA_GRANULARITY; ++i) {
362
0
            *p++=initialValue;
363
0
        }
364
0
        break;
365
0
    default:
366
0
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
367
0
        return 0;
368
0
    }
369
370
0
    return trie;
371
0
}
372
373
U_CAPI void U_EXPORT2
374
0
utrie2_close(UTrie2 *trie) {
375
0
    if(trie!=NULL) {
376
0
        if(trie->isMemoryOwned) {
377
0
            uprv_free(trie->memory);
378
0
        }
379
0
        if(trie->newTrie!=NULL) {
380
0
            uprv_free(trie->newTrie->data);
381
#ifdef UCPTRIE_DEBUG
382
            umutablecptrie_close(trie->newTrie->t3);
383
#endif
384
0
            uprv_free(trie->newTrie);
385
0
        }
386
0
        uprv_free(trie);
387
0
    }
388
0
}
389
390
U_CAPI UBool U_EXPORT2
391
0
utrie2_isFrozen(const UTrie2 *trie) {
392
0
    return (UBool)(trie->newTrie==NULL);
393
0
}
394
395
U_CAPI int32_t U_EXPORT2
396
utrie2_serialize(const UTrie2 *trie,
397
                 void *data, int32_t capacity,
398
0
                 UErrorCode *pErrorCode) {
399
    /* argument check */
400
0
    if(U_FAILURE(*pErrorCode)) {
401
0
        return 0;
402
0
    }
403
404
0
    if( trie==NULL || trie->memory==NULL || trie->newTrie!=NULL ||
405
0
        capacity<0 || (capacity>0 && (data==NULL || (U_POINTER_MASK_LSB(data, 3)!=0)))
406
0
    ) {
407
0
        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
408
0
        return 0;
409
0
    }
410
411
0
    if(capacity>=trie->length) {
412
0
        uprv_memcpy(data, trie->memory, trie->length);
413
0
    } else {
414
0
        *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
415
0
    }
416
0
    return trie->length;
417
0
}
418
419
/* enumeration -------------------------------------------------------------- */
420
421
0
#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
0
enumSameValue(const void * /*context*/, uint32_t value) {
426
0
    return value;
427
0
}
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
0
               UTrie2EnumValue *enumValue, UTrie2EnumRange *enumRange, const void *context) {
446
0
    const uint32_t *data32;
447
0
    const uint16_t *idx;
448
449
0
    uint32_t value, prevValue, initialValue;
450
0
    UChar32 c, prev, highStart;
451
0
    int32_t j, i2Block, prevI2Block, index2NullOffset, block, prevBlock, nullBlock;
452
453
0
    if(enumRange==NULL) {
454
0
        return;
455
0
    }
456
0
    if(enumValue==NULL) {
457
0
        enumValue=enumSameValue;
458
0
    }
459
460
0
    if(trie->newTrie==NULL) {
461
        /* frozen trie */
462
0
        idx=trie->index;
463
0
        U_ASSERT(idx!=NULL); /* the following code assumes trie->newTrie is not NULL when idx is NULL */
464
0
        data32=trie->data32;
465
466
0
        index2NullOffset=trie->index2NullOffset;
467
0
        nullBlock=trie->dataNullOffset;
468
0
    } else {
469
        /* unfrozen, mutable trie */
470
0
        idx=NULL;
471
0
        data32=trie->newTrie->data;
472
0
        U_ASSERT(data32!=NULL); /* the following code assumes idx is not NULL when data32 is NULL */
473
474
0
        index2NullOffset=trie->newTrie->index2NullOffset;
475
0
        nullBlock=trie->newTrie->dataNullOffset;
476
0
    }
477
478
0
    highStart=trie->highStart;
479
480
    /* get the enumeration value that corresponds to an initial-value trie data entry */
481
0
    initialValue=enumValue(context, trie->initialValue);
482
483
    /* set variables for previous range */
484
0
    prevI2Block=-1;
485
0
    prevBlock=-1;
486
0
    prev=start;
487
0
    prevValue=0;
488
489
    /* enumerate index-2 blocks */
490
0
    for(c=start; c<limit && c<highStart;) {
491
        /* Code point limit for iterating inside this i2Block. */
492
0
        UChar32 tempLimit=c+UTRIE2_CP_PER_INDEX_1_ENTRY;
493
0
        if(limit<tempLimit) {
494
0
            tempLimit=limit;
495
0
        }
496
0
        if(c<=0xffff) {
497
0
            if(!U_IS_SURROGATE(c)) {
498
0
                i2Block=c>>UTRIE2_SHIFT_2;
499
0
            } 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
0
                i2Block=UTRIE2_LSCP_INDEX_2_OFFSET;
505
0
                tempLimit=MIN_VALUE(0xdc00, limit);
506
0
            } 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
0
                i2Block=0xd800>>UTRIE2_SHIFT_2;
512
0
                tempLimit=MIN_VALUE(0xe000, limit);
513
0
            }
514
0
        } else {
515
            /* supplementary code points */
516
0
            if(idx!=NULL) {
517
0
                i2Block=idx[(UTRIE2_INDEX_1_OFFSET-UTRIE2_OMITTED_BMP_INDEX_1_LENGTH)+
518
0
                              (c>>UTRIE2_SHIFT_1)];
519
0
            } else {
520
0
                i2Block=trie->newTrie->index1[c>>UTRIE2_SHIFT_1];
521
0
            }
522
0
            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
0
                c+=UTRIE2_CP_PER_INDEX_1_ENTRY;
529
0
                continue;
530
0
            }
531
0
        }
532
0
        prevI2Block=i2Block;
533
0
        if(i2Block==index2NullOffset) {
534
            /* this is the null index-2 block */
535
0
            if(prevValue!=initialValue) {
536
0
                if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
537
0
                    return;
538
0
                }
539
0
                prevBlock=nullBlock;
540
0
                prev=c;
541
0
                prevValue=initialValue;
542
0
            }
543
0
            c+=UTRIE2_CP_PER_INDEX_1_ENTRY;
544
0
        } else {
545
            /* enumerate data blocks for one index-2 block */
546
0
            int32_t i2, i2Limit;
547
0
            i2=(c>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK;
548
0
            if((c>>UTRIE2_SHIFT_1)==(tempLimit>>UTRIE2_SHIFT_1)) {
549
0
                i2Limit=(tempLimit>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK;
550
0
            } else {
551
0
                i2Limit=UTRIE2_INDEX_2_BLOCK_LENGTH;
552
0
            }
553
0
            for(; i2<i2Limit; ++i2) {
554
0
                if(idx!=NULL) {
555
0
                    block=(int32_t)idx[i2Block+i2]<<UTRIE2_INDEX_SHIFT;
556
0
                } else {
557
0
                    block=trie->newTrie->index2[i2Block+i2];
558
0
                }
559
0
                if(block==prevBlock && (c-prev)>=UTRIE2_DATA_BLOCK_LENGTH) {
560
                    /* the block is the same as the previous one, and filled with prevValue */
561
0
                    c+=UTRIE2_DATA_BLOCK_LENGTH;
562
0
                    continue;
563
0
                }
564
0
                prevBlock=block;
565
0
                if(block==nullBlock) {
566
                    /* this is the null data block */
567
0
                    if(prevValue!=initialValue) {
568
0
                        if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
569
0
                            return;
570
0
                        }
571
0
                        prev=c;
572
0
                        prevValue=initialValue;
573
0
                    }
574
0
                    c+=UTRIE2_DATA_BLOCK_LENGTH;
575
0
                } else {
576
0
                    for(j=0; j<UTRIE2_DATA_BLOCK_LENGTH; ++j) {
577
0
                        value=enumValue(context, data32!=NULL ? data32[block+j] : idx[block+j]);
578
0
                        if(value!=prevValue) {
579
0
                            if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
580
0
                                return;
581
0
                            }
582
0
                            prev=c;
583
0
                            prevValue=value;
584
0
                        }
585
0
                        ++c;
586
0
                    }
587
0
                }
588
0
            }
589
0
        }
590
0
    }
591
592
0
    if(c>limit) {
593
0
        c=limit;  /* could be higher if in the index2NullOffset */
594
0
    } else if(c<limit) {
595
        /* c==highStart<limit */
596
0
        uint32_t highValue;
597
0
        if(idx!=NULL) {
598
0
            highValue=
599
0
                data32!=NULL ?
600
0
                    data32[trie->highValueIndex] :
601
0
                    idx[trie->highValueIndex];
602
0
        } else {
603
0
            highValue=trie->newTrie->data[trie->newTrie->dataLength-UTRIE2_DATA_GRANULARITY];
604
0
        }
605
0
        value=enumValue(context, highValue);
606
0
        if(value!=prevValue) {
607
0
            if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
608
0
                return;
609
0
            }
610
0
            prev=c;
611
0
            prevValue=value;
612
0
        }
613
0
        c=limit;
614
0
    }
615
616
    /* deliver last range */
617
0
    enumRange(context, prev, c-1, prevValue);
618
0
}
619
620
U_CAPI void U_EXPORT2
621
utrie2_enum(const UTrie2 *trie,
622
0
            UTrie2EnumValue *enumValue, UTrie2EnumRange *enumRange, const void *context) {
623
0
    enumEitherTrie(trie, 0, 0x110000, enumValue, enumRange, context);
624
0
}
625
626
U_CAPI void U_EXPORT2
627
utrie2_enumForLeadSurrogate(const UTrie2 *trie, UChar32 lead,
628
                            UTrie2EnumValue *enumValue, UTrie2EnumRange *enumRange,
629
0
                            const void *context) {
630
0
    if(!U16_IS_LEAD(lead)) {
631
0
        return;
632
0
    }
633
0
    lead=(lead-0xd7c0)<<10;   /* start code point */
634
0
    enumEitherTrie(trie, lead, lead+0x400, enumValue, enumRange, context);
635
0
}
636
637
/* C++ convenience wrappers ------------------------------------------------- */
638
639
U_NAMESPACE_BEGIN
640
641
0
uint16_t BackwardUTrie2StringIterator::previous16() {
642
0
    codePointLimit=codePointStart;
643
0
    if(start>=codePointStart) {
644
0
        codePoint=U_SENTINEL;
645
0
        return static_cast<uint16_t>(trie->errorValue);
646
0
    }
647
0
    uint16_t result;
648
0
    UTRIE2_U16_PREV16(trie, start, codePointStart, codePoint, result);
649
0
    return result;
650
0
}
651
652
0
uint16_t ForwardUTrie2StringIterator::next16() {
653
0
    codePointStart=codePointLimit;
654
0
    if(codePointLimit==limit) {
655
0
        codePoint=U_SENTINEL;
656
0
        return static_cast<uint16_t>(trie->errorValue);
657
0
    }
658
0
    uint16_t result;
659
0
    UTRIE2_U16_NEXT16(trie, codePointLimit, limit, codePoint, result);
660
0
    return result;
661
0
}
662
663
U_NAMESPACE_END