1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 ******************************************************************************
6 * Copyright (C) 2001-2014, International Business Machines
7 * Corporation and others. All Rights Reserved.
9 ******************************************************************************
10 * file name: utrie2.cpp
12 * tab size: 8 (not used)
15 * created on: 2008aug16 (starting from a copy of utrie.c)
16 * created by: Markus W. Scherer
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.
24 * This file contains only the runtime and enumeration code, for read-only access.
25 * See utrie2_builder.c for the builder code.
31 #include "unicode/utypes.h"
32 #include "unicode/utf.h"
33 #include "unicode/utf8.h"
34 #include "unicode/utf16.h"
37 #include "utrie2_impl.h"
40 /* Public UTrie2 API implementation ----------------------------------------- */
43 get32(const UNewTrie2
*trie
, UChar32 c
, UBool fromLSCP
) {
46 if(c
>=trie
->highStart
&& (!U_IS_LEAD(c
) || fromLSCP
)) {
47 return trie
->data
[trie
->dataLength
-UTRIE2_DATA_GRANULARITY
];
50 if(U_IS_LEAD(c
) && fromLSCP
) {
51 i2
=(UTRIE2_LSCP_INDEX_2_OFFSET
-(0xd800>>UTRIE2_SHIFT_2
))+
54 i2
=trie
->index1
[c
>>UTRIE2_SHIFT_1
]+
55 ((c
>>UTRIE2_SHIFT_2
)&UTRIE2_INDEX_2_MASK
);
57 block
=trie
->index2
[i2
];
58 return trie
->data
[block
+(c
&UTRIE2_DATA_MASK
)];
61 U_CAPI
uint32_t U_EXPORT2
62 utrie2_get32(const UTrie2
*trie
, UChar32 c
) {
63 if(trie
->data16
!=NULL
) {
64 return UTRIE2_GET16(trie
, c
);
65 } else if(trie
->data32
!=NULL
) {
66 return UTRIE2_GET32(trie
, c
);
67 } else if((uint32_t)c
>0x10ffff) {
68 return trie
->errorValue
;
70 return get32(trie
->newTrie
, c
, TRUE
);
74 U_CAPI
uint32_t U_EXPORT2
75 utrie2_get32FromLeadSurrogateCodeUnit(const UTrie2
*trie
, UChar32 c
) {
77 return trie
->errorValue
;
79 if(trie
->data16
!=NULL
) {
80 return UTRIE2_GET16_FROM_U16_SINGLE_LEAD(trie
, c
);
81 } else if(trie
->data32
!=NULL
) {
82 return UTRIE2_GET32_FROM_U16_SINGLE_LEAD(trie
, c
);
84 return get32(trie
->newTrie
, c
, FALSE
);
89 u8Index(const UTrie2
*trie
, UChar32 c
, int32_t i
) {
91 _UTRIE2_INDEX_FROM_CP(
93 trie
->data32
==NULL
? trie
->indexLength
: 0,
98 U_CAPI
int32_t U_EXPORT2
99 utrie2_internalU8NextIndex(const UTrie2
*trie
, UChar32 c
,
100 const uint8_t *src
, const uint8_t *limit
) {
103 /* support 64-bit pointers by avoiding cast of arbitrary difference */
105 length
=(int32_t)(limit
-src
);
109 c
=utf8_nextCharSafeBody(src
, &i
, length
, c
, -1);
110 return u8Index(trie
, c
, i
);
113 U_CAPI
int32_t U_EXPORT2
114 utrie2_internalU8PrevIndex(const UTrie2
*trie
, UChar32 c
,
115 const uint8_t *start
, const uint8_t *src
) {
117 /* support 64-bit pointers by avoiding cast of arbitrary difference */
119 i
=length
=(int32_t)(src
-start
);
124 c
=utf8_prevCharSafeBody(start
, 0, &i
, c
, -1);
125 i
=length
-i
; /* number of bytes read backward from src */
126 return u8Index(trie
, c
, i
);
129 U_CAPI UTrie2
* U_EXPORT2
130 utrie2_openFromSerialized(UTrie2ValueBits valueBits
,
131 const void *data
, int32_t length
, int32_t *pActualLength
,
132 UErrorCode
*pErrorCode
) {
133 const UTrie2Header
*header
;
135 int32_t actualLength
;
140 if(U_FAILURE(*pErrorCode
)) {
144 if( length
<=0 || (U_POINTER_MASK_LSB(data
, 3)!=0) ||
145 valueBits
<0 || UTRIE2_COUNT_VALUE_BITS
<=valueBits
147 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
151 /* enough data for a trie header? */
152 if(length
<(int32_t)sizeof(UTrie2Header
)) {
153 *pErrorCode
=U_INVALID_FORMAT_ERROR
;
157 /* check the signature */
158 header
=(const UTrie2Header
*)data
;
159 if(header
->signature
!=UTRIE2_SIG
) {
160 *pErrorCode
=U_INVALID_FORMAT_ERROR
;
164 /* get the options */
165 if(valueBits
!=(UTrie2ValueBits
)(header
->options
&UTRIE2_OPTIONS_VALUE_BITS_MASK
)) {
166 *pErrorCode
=U_INVALID_FORMAT_ERROR
;
170 /* get the length values and offsets */
171 uprv_memset(&tempTrie
, 0, sizeof(tempTrie
));
172 tempTrie
.indexLength
=header
->indexLength
;
173 tempTrie
.dataLength
=header
->shiftedDataLength
<<UTRIE2_INDEX_SHIFT
;
174 tempTrie
.index2NullOffset
=header
->index2NullOffset
;
175 tempTrie
.dataNullOffset
=header
->dataNullOffset
;
177 tempTrie
.highStart
=header
->shiftedHighStart
<<UTRIE2_SHIFT_1
;
178 tempTrie
.highValueIndex
=tempTrie
.dataLength
-UTRIE2_DATA_GRANULARITY
;
179 if(valueBits
==UTRIE2_16_VALUE_BITS
) {
180 tempTrie
.highValueIndex
+=tempTrie
.indexLength
;
183 /* calculate the actual length */
184 actualLength
=(int32_t)sizeof(UTrie2Header
)+tempTrie
.indexLength
*2;
185 if(valueBits
==UTRIE2_16_VALUE_BITS
) {
186 actualLength
+=tempTrie
.dataLength
*2;
188 actualLength
+=tempTrie
.dataLength
*4;
190 if(length
<actualLength
) {
191 *pErrorCode
=U_INVALID_FORMAT_ERROR
; /* not enough bytes */
195 /* allocate the trie */
196 trie
=(UTrie2
*)uprv_malloc(sizeof(UTrie2
));
198 *pErrorCode
=U_MEMORY_ALLOCATION_ERROR
;
201 uprv_memcpy(trie
, &tempTrie
, sizeof(tempTrie
));
202 trie
->memory
=(uint32_t *)data
;
203 trie
->length
=actualLength
;
204 trie
->isMemoryOwned
=FALSE
;
206 /* set the pointers to its index and data arrays */
207 p16
=(const uint16_t *)(header
+1);
209 p16
+=trie
->indexLength
;
213 case UTRIE2_16_VALUE_BITS
:
216 trie
->initialValue
=trie
->index
[trie
->dataNullOffset
];
217 trie
->errorValue
=trie
->data16
[UTRIE2_BAD_UTF8_DATA_OFFSET
];
219 case UTRIE2_32_VALUE_BITS
:
221 trie
->data32
=(const uint32_t *)p16
;
222 trie
->initialValue
=trie
->data32
[trie
->dataNullOffset
];
223 trie
->errorValue
=trie
->data32
[UTRIE2_BAD_UTF8_DATA_OFFSET
];
226 *pErrorCode
=U_INVALID_FORMAT_ERROR
;
230 if(pActualLength
!=NULL
) {
231 *pActualLength
=actualLength
;
236 U_CAPI UTrie2
* U_EXPORT2
237 utrie2_openDummy(UTrie2ValueBits valueBits
,
238 uint32_t initialValue
, uint32_t errorValue
,
239 UErrorCode
*pErrorCode
) {
241 UTrie2Header
*header
;
244 int32_t indexLength
, dataLength
, length
, i
;
245 int32_t dataMove
; /* >0 if the data is moved to the end of the index array */
247 if(U_FAILURE(*pErrorCode
)) {
251 if(valueBits
<0 || UTRIE2_COUNT_VALUE_BITS
<=valueBits
) {
252 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
256 /* calculate the total length of the dummy trie data */
257 indexLength
=UTRIE2_INDEX_1_OFFSET
;
258 dataLength
=UTRIE2_DATA_START_OFFSET
+UTRIE2_DATA_GRANULARITY
;
259 length
=(int32_t)sizeof(UTrie2Header
)+indexLength
*2;
260 if(valueBits
==UTRIE2_16_VALUE_BITS
) {
261 length
+=dataLength
*2;
263 length
+=dataLength
*4;
266 /* allocate the trie */
267 trie
=(UTrie2
*)uprv_malloc(sizeof(UTrie2
));
269 *pErrorCode
=U_MEMORY_ALLOCATION_ERROR
;
272 uprv_memset(trie
, 0, sizeof(UTrie2
));
273 trie
->memory
=uprv_malloc(length
);
274 if(trie
->memory
==NULL
) {
276 *pErrorCode
=U_MEMORY_ALLOCATION_ERROR
;
280 trie
->isMemoryOwned
=TRUE
;
282 /* set the UTrie2 fields */
283 if(valueBits
==UTRIE2_16_VALUE_BITS
) {
284 dataMove
=indexLength
;
289 trie
->indexLength
=indexLength
;
290 trie
->dataLength
=dataLength
;
291 trie
->index2NullOffset
=UTRIE2_INDEX_2_OFFSET
;
292 trie
->dataNullOffset
=(uint16_t)dataMove
;
293 trie
->initialValue
=initialValue
;
294 trie
->errorValue
=errorValue
;
296 trie
->highValueIndex
=dataMove
+UTRIE2_DATA_START_OFFSET
;
298 /* set the header fields */
299 header
=(UTrie2Header
*)trie
->memory
;
301 header
->signature
=UTRIE2_SIG
; /* "Tri2" */
302 header
->options
=(uint16_t)valueBits
;
304 header
->indexLength
=(uint16_t)indexLength
;
305 header
->shiftedDataLength
=(uint16_t)(dataLength
>>UTRIE2_INDEX_SHIFT
);
306 header
->index2NullOffset
=(uint16_t)UTRIE2_INDEX_2_OFFSET
;
307 header
->dataNullOffset
=(uint16_t)dataMove
;
308 header
->shiftedHighStart
=0;
310 /* fill the index and data arrays */
311 dest16
=(uint16_t *)(header
+1);
314 /* write the index-2 array values shifted right by UTRIE2_INDEX_SHIFT */
315 for(i
=0; i
<UTRIE2_INDEX_2_BMP_LENGTH
; ++i
) {
316 *dest16
++=(uint16_t)(dataMove
>>UTRIE2_INDEX_SHIFT
); /* null data block */
319 /* write UTF-8 2-byte index-2 values, not right-shifted */
320 for(i
=0; i
<(0xc2-0xc0); ++i
) { /* C0..C1 */
321 *dest16
++=(uint16_t)(dataMove
+UTRIE2_BAD_UTF8_DATA_OFFSET
);
323 for(; i
<(0xe0-0xc0); ++i
) { /* C2..DF */
324 *dest16
++=(uint16_t)dataMove
;
327 /* write the 16/32-bit data array */
329 case UTRIE2_16_VALUE_BITS
:
330 /* write 16-bit data values */
333 for(i
=0; i
<0x80; ++i
) {
334 *dest16
++=(uint16_t)initialValue
;
337 *dest16
++=(uint16_t)errorValue
;
339 /* highValue and reserved values */
340 for(i
=0; i
<UTRIE2_DATA_GRANULARITY
; ++i
) {
341 *dest16
++=(uint16_t)initialValue
;
344 case UTRIE2_32_VALUE_BITS
:
345 /* write 32-bit data values */
346 p
=(uint32_t *)dest16
;
349 for(i
=0; i
<0x80; ++i
) {
355 /* highValue and reserved values */
356 for(i
=0; i
<UTRIE2_DATA_GRANULARITY
; ++i
) {
361 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
368 U_CAPI
void U_EXPORT2
369 utrie2_close(UTrie2
*trie
) {
371 if(trie
->isMemoryOwned
) {
372 uprv_free(trie
->memory
);
374 if(trie
->newTrie
!=NULL
) {
375 uprv_free(trie
->newTrie
->data
);
376 uprv_free(trie
->newTrie
);
382 U_CAPI
int32_t U_EXPORT2
383 utrie2_getVersion(const void *data
, int32_t length
, UBool anyEndianOk
) {
385 if(length
<16 || data
==NULL
|| (U_POINTER_MASK_LSB(data
, 3)!=0)) {
388 signature
=*(const uint32_t *)data
;
389 if(signature
==UTRIE2_SIG
) {
392 if(anyEndianOk
&& signature
==UTRIE2_OE_SIG
) {
395 if(signature
==UTRIE_SIG
) {
398 if(anyEndianOk
&& signature
==UTRIE_OE_SIG
) {
404 U_CAPI UBool U_EXPORT2
405 utrie2_isFrozen(const UTrie2
*trie
) {
406 return (UBool
)(trie
->newTrie
==NULL
);
409 U_CAPI
int32_t U_EXPORT2
410 utrie2_serialize(const UTrie2
*trie
,
411 void *data
, int32_t capacity
,
412 UErrorCode
*pErrorCode
) {
414 if(U_FAILURE(*pErrorCode
)) {
418 if( trie
==NULL
|| trie
->memory
==NULL
|| trie
->newTrie
!=NULL
||
419 capacity
<0 || (capacity
>0 && (data
==NULL
|| (U_POINTER_MASK_LSB(data
, 3)!=0)))
421 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
425 if(capacity
>=trie
->length
) {
426 uprv_memcpy(data
, trie
->memory
, trie
->length
);
428 *pErrorCode
=U_BUFFER_OVERFLOW_ERROR
;
433 U_CAPI
int32_t U_EXPORT2
434 utrie2_swap(const UDataSwapper
*ds
,
435 const void *inData
, int32_t length
, void *outData
,
436 UErrorCode
*pErrorCode
) {
437 const UTrie2Header
*inTrie
;
439 int32_t dataLength
, size
;
440 UTrie2ValueBits valueBits
;
442 if(U_FAILURE(*pErrorCode
)) {
445 if(ds
==NULL
|| inData
==NULL
|| (length
>=0 && outData
==NULL
)) {
446 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
450 /* setup and swapping */
451 if(length
>=0 && length
<(int32_t)sizeof(UTrie2Header
)) {
452 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
456 inTrie
=(const UTrie2Header
*)inData
;
457 trie
.signature
=ds
->readUInt32(inTrie
->signature
);
458 trie
.options
=ds
->readUInt16(inTrie
->options
);
459 trie
.indexLength
=ds
->readUInt16(inTrie
->indexLength
);
460 trie
.shiftedDataLength
=ds
->readUInt16(inTrie
->shiftedDataLength
);
462 valueBits
=(UTrie2ValueBits
)(trie
.options
&UTRIE2_OPTIONS_VALUE_BITS_MASK
);
463 dataLength
=(int32_t)trie
.shiftedDataLength
<<UTRIE2_INDEX_SHIFT
;
465 if( trie
.signature
!=UTRIE2_SIG
||
466 valueBits
<0 || UTRIE2_COUNT_VALUE_BITS
<=valueBits
||
467 trie
.indexLength
<UTRIE2_INDEX_1_OFFSET
||
468 dataLength
<UTRIE2_DATA_START_OFFSET
470 *pErrorCode
=U_INVALID_FORMAT_ERROR
; /* not a UTrie */
474 size
=sizeof(UTrie2Header
)+trie
.indexLength
*2;
476 case UTRIE2_16_VALUE_BITS
:
479 case UTRIE2_32_VALUE_BITS
:
483 *pErrorCode
=U_INVALID_FORMAT_ERROR
;
488 UTrie2Header
*outTrie
;
491 *pErrorCode
=U_INDEX_OUTOFBOUNDS_ERROR
;
495 outTrie
=(UTrie2Header
*)outData
;
497 /* swap the header */
498 ds
->swapArray32(ds
, &inTrie
->signature
, 4, &outTrie
->signature
, pErrorCode
);
499 ds
->swapArray16(ds
, &inTrie
->options
, 12, &outTrie
->options
, pErrorCode
);
501 /* swap the index and the data */
503 case UTRIE2_16_VALUE_BITS
:
504 ds
->swapArray16(ds
, inTrie
+1, (trie
.indexLength
+dataLength
)*2, outTrie
+1, pErrorCode
);
506 case UTRIE2_32_VALUE_BITS
:
507 ds
->swapArray16(ds
, inTrie
+1, trie
.indexLength
*2, outTrie
+1, pErrorCode
);
508 ds
->swapArray32(ds
, (const uint16_t *)(inTrie
+1)+trie
.indexLength
, dataLength
*4,
509 (uint16_t *)(outTrie
+1)+trie
.indexLength
, pErrorCode
);
512 *pErrorCode
=U_INVALID_FORMAT_ERROR
;
520 // utrie2_swapAnyVersion() should be defined here but lives in utrie2_builder.c
521 // to avoid a dependency from utrie2.cpp on utrie.c.
523 /* enumeration -------------------------------------------------------------- */
525 #define MIN_VALUE(a, b) ((a)<(b) ? (a) : (b))
527 /* default UTrie2EnumValue() returns the input value itself */
528 static uint32_t U_CALLCONV
529 enumSameValue(const void * /*context*/, uint32_t value
) {
534 * Enumerate all ranges of code points with the same relevant values.
535 * The values are transformed from the raw trie entries by the enumValue function.
537 * Currently requires start<limit and both start and limit must be multiples
538 * of UTRIE2_DATA_BLOCK_LENGTH.
541 * - Skip a whole block if we know that it is filled with a single value,
542 * and it is the same as we visited just before.
543 * - Handle the null block specially because we know a priori that it is filled
544 * with a single value.
547 enumEitherTrie(const UTrie2
*trie
,
548 UChar32 start
, UChar32 limit
,
549 UTrie2EnumValue
*enumValue
, UTrie2EnumRange
*enumRange
, const void *context
) {
550 const uint32_t *data32
;
553 uint32_t value
, prevValue
, initialValue
;
554 UChar32 c
, prev
, highStart
;
555 int32_t j
, i2Block
, prevI2Block
, index2NullOffset
, block
, prevBlock
, nullBlock
;
557 if(enumRange
==NULL
) {
560 if(enumValue
==NULL
) {
561 enumValue
=enumSameValue
;
564 if(trie
->newTrie
==NULL
) {
567 U_ASSERT(idx
!=NULL
); /* the following code assumes trie->newTrie is not NULL when idx is NULL */
570 index2NullOffset
=trie
->index2NullOffset
;
571 nullBlock
=trie
->dataNullOffset
;
573 /* unfrozen, mutable trie */
575 data32
=trie
->newTrie
->data
;
576 U_ASSERT(data32
!=NULL
); /* the following code assumes idx is not NULL when data32 is NULL */
578 index2NullOffset
=trie
->newTrie
->index2NullOffset
;
579 nullBlock
=trie
->newTrie
->dataNullOffset
;
582 highStart
=trie
->highStart
;
584 /* get the enumeration value that corresponds to an initial-value trie data entry */
585 initialValue
=enumValue(context
, trie
->initialValue
);
587 /* set variables for previous range */
593 /* enumerate index-2 blocks */
594 for(c
=start
; c
<limit
&& c
<highStart
;) {
595 /* Code point limit for iterating inside this i2Block. */
596 UChar32 tempLimit
=c
+UTRIE2_CP_PER_INDEX_1_ENTRY
;
597 if(limit
<tempLimit
) {
601 if(!U_IS_SURROGATE(c
)) {
602 i2Block
=c
>>UTRIE2_SHIFT_2
;
603 } else if(U_IS_SURROGATE_LEAD(c
)) {
605 * Enumerate values for lead surrogate code points, not code units:
606 * This special block has half the normal length.
608 i2Block
=UTRIE2_LSCP_INDEX_2_OFFSET
;
609 tempLimit
=MIN_VALUE(0xdc00, limit
);
612 * Switch back to the normal part of the index-2 table.
613 * Enumerate the second half of the surrogates block.
615 i2Block
=0xd800>>UTRIE2_SHIFT_2
;
616 tempLimit
=MIN_VALUE(0xe000, limit
);
619 /* supplementary code points */
621 i2Block
=idx
[(UTRIE2_INDEX_1_OFFSET
-UTRIE2_OMITTED_BMP_INDEX_1_LENGTH
)+
622 (c
>>UTRIE2_SHIFT_1
)];
624 i2Block
=trie
->newTrie
->index1
[c
>>UTRIE2_SHIFT_1
];
626 if(i2Block
==prevI2Block
&& (c
-prev
)>=UTRIE2_CP_PER_INDEX_1_ENTRY
) {
628 * The index-2 block is the same as the previous one, and filled with prevValue.
629 * Only possible for supplementary code points because the linear-BMP index-2
630 * table creates unique i2Block values.
632 c
+=UTRIE2_CP_PER_INDEX_1_ENTRY
;
637 if(i2Block
==index2NullOffset
) {
638 /* this is the null index-2 block */
639 if(prevValue
!=initialValue
) {
640 if(prev
<c
&& !enumRange(context
, prev
, c
-1, prevValue
)) {
645 prevValue
=initialValue
;
647 c
+=UTRIE2_CP_PER_INDEX_1_ENTRY
;
649 /* enumerate data blocks for one index-2 block */
651 i2
=(c
>>UTRIE2_SHIFT_2
)&UTRIE2_INDEX_2_MASK
;
652 if((c
>>UTRIE2_SHIFT_1
)==(tempLimit
>>UTRIE2_SHIFT_1
)) {
653 i2Limit
=(tempLimit
>>UTRIE2_SHIFT_2
)&UTRIE2_INDEX_2_MASK
;
655 i2Limit
=UTRIE2_INDEX_2_BLOCK_LENGTH
;
657 for(; i2
<i2Limit
; ++i2
) {
659 block
=(int32_t)idx
[i2Block
+i2
]<<UTRIE2_INDEX_SHIFT
;
661 block
=trie
->newTrie
->index2
[i2Block
+i2
];
663 if(block
==prevBlock
&& (c
-prev
)>=UTRIE2_DATA_BLOCK_LENGTH
) {
664 /* the block is the same as the previous one, and filled with prevValue */
665 c
+=UTRIE2_DATA_BLOCK_LENGTH
;
669 if(block
==nullBlock
) {
670 /* this is the null data block */
671 if(prevValue
!=initialValue
) {
672 if(prev
<c
&& !enumRange(context
, prev
, c
-1, prevValue
)) {
676 prevValue
=initialValue
;
678 c
+=UTRIE2_DATA_BLOCK_LENGTH
;
680 for(j
=0; j
<UTRIE2_DATA_BLOCK_LENGTH
; ++j
) {
681 value
=enumValue(context
, data32
!=NULL
? data32
[block
+j
] : idx
[block
+j
]);
682 if(value
!=prevValue
) {
683 if(prev
<c
&& !enumRange(context
, prev
, c
-1, prevValue
)) {
697 c
=limit
; /* could be higher if in the index2NullOffset */
699 /* c==highStart<limit */
704 data32
[trie
->highValueIndex
] :
705 idx
[trie
->highValueIndex
];
707 highValue
=trie
->newTrie
->data
[trie
->newTrie
->dataLength
-UTRIE2_DATA_GRANULARITY
];
709 value
=enumValue(context
, highValue
);
710 if(value
!=prevValue
) {
711 if(prev
<c
&& !enumRange(context
, prev
, c
-1, prevValue
)) {
720 /* deliver last range */
721 enumRange(context
, prev
, c
-1, prevValue
);
724 U_CAPI
void U_EXPORT2
725 utrie2_enum(const UTrie2
*trie
,
726 UTrie2EnumValue
*enumValue
, UTrie2EnumRange
*enumRange
, const void *context
) {
727 enumEitherTrie(trie
, 0, 0x110000, enumValue
, enumRange
, context
);
730 U_CAPI
void U_EXPORT2
731 utrie2_enumForLeadSurrogate(const UTrie2
*trie
, UChar32 lead
,
732 UTrie2EnumValue
*enumValue
, UTrie2EnumRange
*enumRange
,
733 const void *context
) {
734 if(!U16_IS_LEAD(lead
)) {
737 lead
=(lead
-0xd7c0)<<10; /* start code point */
738 enumEitherTrie(trie
, lead
, lead
+0x400, enumValue
, enumRange
, context
);
741 /* C++ convenience wrappers ------------------------------------------------- */
745 uint16_t BackwardUTrie2StringIterator::previous16() {
746 codePointLimit
=codePointStart
;
747 if(start
>=codePointStart
) {
748 codePoint
=U_SENTINEL
;
752 UTRIE2_U16_PREV16(trie
, start
, codePointStart
, codePoint
, result
);
756 uint16_t ForwardUTrie2StringIterator::next16() {
757 codePointStart
=codePointLimit
;
758 if(codePointLimit
==limit
) {
759 codePoint
=U_SENTINEL
;
763 UTRIE2_U16_NEXT16(trie
, codePointLimit
, limit
, codePoint
, result
);