Line data Source code
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 : #ifdef UTRIE2_DEBUG
28 : # include <stdio.h>
29 : #endif
30 :
31 : #include "unicode/utypes.h"
32 : #include "unicode/utf.h"
33 : #include "unicode/utf8.h"
34 : #include "unicode/utf16.h"
35 : #include "cmemory.h"
36 : #include "utrie2.h"
37 : #include "utrie2_impl.h"
38 : #include "uassert.h"
39 :
40 : /* Public UTrie2 API implementation ----------------------------------------- */
41 :
42 : static uint32_t
43 0 : get32(const UNewTrie2 *trie, UChar32 c, UBool fromLSCP) {
44 : int32_t i2, block;
45 :
46 0 : if(c>=trie->highStart && (!U_IS_LEAD(c) || fromLSCP)) {
47 0 : return trie->data[trie->dataLength-UTRIE2_DATA_GRANULARITY];
48 : }
49 :
50 0 : if(U_IS_LEAD(c) && fromLSCP) {
51 0 : i2=(UTRIE2_LSCP_INDEX_2_OFFSET-(0xd800>>UTRIE2_SHIFT_2))+
52 0 : (c>>UTRIE2_SHIFT_2);
53 : } else {
54 0 : i2=trie->index1[c>>UTRIE2_SHIFT_1]+
55 0 : ((c>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK);
56 : }
57 0 : block=trie->index2[i2];
58 0 : return trie->data[block+(c&UTRIE2_DATA_MASK)];
59 : }
60 :
61 : U_CAPI uint32_t U_EXPORT2
62 0 : utrie2_get32(const UTrie2 *trie, UChar32 c) {
63 0 : if(trie->data16!=NULL) {
64 0 : return UTRIE2_GET16(trie, c);
65 0 : } else if(trie->data32!=NULL) {
66 0 : return UTRIE2_GET32(trie, c);
67 0 : } else if((uint32_t)c>0x10ffff) {
68 0 : return trie->errorValue;
69 : } else {
70 0 : return get32(trie->newTrie, c, TRUE);
71 : }
72 : }
73 :
74 : U_CAPI uint32_t U_EXPORT2
75 0 : utrie2_get32FromLeadSurrogateCodeUnit(const UTrie2 *trie, UChar32 c) {
76 0 : if(!U_IS_LEAD(c)) {
77 0 : return trie->errorValue;
78 : }
79 0 : if(trie->data16!=NULL) {
80 0 : return UTRIE2_GET16_FROM_U16_SINGLE_LEAD(trie, c);
81 0 : } else if(trie->data32!=NULL) {
82 0 : return UTRIE2_GET32_FROM_U16_SINGLE_LEAD(trie, c);
83 : } else {
84 0 : return get32(trie->newTrie, c, FALSE);
85 : }
86 : }
87 :
88 : static inline int32_t
89 0 : u8Index(const UTrie2 *trie, UChar32 c, int32_t i) {
90 : int32_t idx=
91 0 : _UTRIE2_INDEX_FROM_CP(
92 : trie,
93 : trie->data32==NULL ? trie->indexLength : 0,
94 : c);
95 0 : return (idx<<3)|i;
96 : }
97 :
98 : U_CAPI int32_t U_EXPORT2
99 0 : utrie2_internalU8NextIndex(const UTrie2 *trie, UChar32 c,
100 : const uint8_t *src, const uint8_t *limit) {
101 : int32_t i, length;
102 0 : i=0;
103 : /* support 64-bit pointers by avoiding cast of arbitrary difference */
104 0 : if((limit-src)<=7) {
105 0 : length=(int32_t)(limit-src);
106 : } else {
107 0 : length=7;
108 : }
109 0 : c=utf8_nextCharSafeBody(src, &i, length, c, -1);
110 0 : return u8Index(trie, c, i);
111 : }
112 :
113 : U_CAPI int32_t U_EXPORT2
114 0 : utrie2_internalU8PrevIndex(const UTrie2 *trie, UChar32 c,
115 : const uint8_t *start, const uint8_t *src) {
116 : int32_t i, length;
117 : /* support 64-bit pointers by avoiding cast of arbitrary difference */
118 0 : if((src-start)<=7) {
119 0 : i=length=(int32_t)(src-start);
120 : } else {
121 0 : i=length=7;
122 0 : start=src-7;
123 : }
124 0 : c=utf8_prevCharSafeBody(start, 0, &i, c, -1);
125 0 : i=length-i; /* number of bytes read backward from src */
126 0 : return u8Index(trie, c, i);
127 : }
128 :
129 : U_CAPI UTrie2 * U_EXPORT2
130 3 : utrie2_openFromSerialized(UTrie2ValueBits valueBits,
131 : const void *data, int32_t length, int32_t *pActualLength,
132 : UErrorCode *pErrorCode) {
133 : const UTrie2Header *header;
134 : const uint16_t *p16;
135 : int32_t actualLength;
136 :
137 : UTrie2 tempTrie;
138 : UTrie2 *trie;
139 :
140 3 : if(U_FAILURE(*pErrorCode)) {
141 0 : return 0;
142 : }
143 :
144 6 : if( length<=0 || (U_POINTER_MASK_LSB(data, 3)!=0) ||
145 6 : valueBits<0 || UTRIE2_COUNT_VALUE_BITS<=valueBits
146 : ) {
147 0 : *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
148 0 : return 0;
149 : }
150 :
151 : /* enough data for a trie header? */
152 3 : if(length<(int32_t)sizeof(UTrie2Header)) {
153 0 : *pErrorCode=U_INVALID_FORMAT_ERROR;
154 0 : return 0;
155 : }
156 :
157 : /* check the signature */
158 3 : header=(const UTrie2Header *)data;
159 3 : if(header->signature!=UTRIE2_SIG) {
160 0 : *pErrorCode=U_INVALID_FORMAT_ERROR;
161 0 : return 0;
162 : }
163 :
164 : /* get the options */
165 3 : if(valueBits!=(UTrie2ValueBits)(header->options&UTRIE2_OPTIONS_VALUE_BITS_MASK)) {
166 0 : *pErrorCode=U_INVALID_FORMAT_ERROR;
167 0 : return 0;
168 : }
169 :
170 : /* get the length values and offsets */
171 3 : uprv_memset(&tempTrie, 0, sizeof(tempTrie));
172 3 : tempTrie.indexLength=header->indexLength;
173 3 : tempTrie.dataLength=header->shiftedDataLength<<UTRIE2_INDEX_SHIFT;
174 3 : tempTrie.index2NullOffset=header->index2NullOffset;
175 3 : tempTrie.dataNullOffset=header->dataNullOffset;
176 :
177 3 : tempTrie.highStart=header->shiftedHighStart<<UTRIE2_SHIFT_1;
178 3 : tempTrie.highValueIndex=tempTrie.dataLength-UTRIE2_DATA_GRANULARITY;
179 3 : if(valueBits==UTRIE2_16_VALUE_BITS) {
180 3 : tempTrie.highValueIndex+=tempTrie.indexLength;
181 : }
182 :
183 : /* calculate the actual length */
184 3 : actualLength=(int32_t)sizeof(UTrie2Header)+tempTrie.indexLength*2;
185 3 : if(valueBits==UTRIE2_16_VALUE_BITS) {
186 3 : actualLength+=tempTrie.dataLength*2;
187 : } else {
188 0 : actualLength+=tempTrie.dataLength*4;
189 : }
190 3 : if(length<actualLength) {
191 0 : *pErrorCode=U_INVALID_FORMAT_ERROR; /* not enough bytes */
192 0 : return 0;
193 : }
194 :
195 : /* allocate the trie */
196 3 : trie=(UTrie2 *)uprv_malloc(sizeof(UTrie2));
197 3 : if(trie==NULL) {
198 0 : *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
199 0 : return 0;
200 : }
201 3 : uprv_memcpy(trie, &tempTrie, sizeof(tempTrie));
202 3 : trie->memory=(uint32_t *)data;
203 3 : trie->length=actualLength;
204 3 : trie->isMemoryOwned=FALSE;
205 :
206 : /* set the pointers to its index and data arrays */
207 3 : p16=(const uint16_t *)(header+1);
208 3 : trie->index=p16;
209 3 : p16+=trie->indexLength;
210 :
211 : /* get the data */
212 3 : switch(valueBits) {
213 : case UTRIE2_16_VALUE_BITS:
214 3 : trie->data16=p16;
215 3 : trie->data32=NULL;
216 3 : trie->initialValue=trie->index[trie->dataNullOffset];
217 3 : trie->errorValue=trie->data16[UTRIE2_BAD_UTF8_DATA_OFFSET];
218 3 : break;
219 : case UTRIE2_32_VALUE_BITS:
220 0 : trie->data16=NULL;
221 0 : trie->data32=(const uint32_t *)p16;
222 0 : trie->initialValue=trie->data32[trie->dataNullOffset];
223 0 : trie->errorValue=trie->data32[UTRIE2_BAD_UTF8_DATA_OFFSET];
224 0 : break;
225 : default:
226 0 : *pErrorCode=U_INVALID_FORMAT_ERROR;
227 0 : return 0;
228 : }
229 :
230 3 : if(pActualLength!=NULL) {
231 0 : *pActualLength=actualLength;
232 : }
233 3 : return trie;
234 : }
235 :
236 : U_CAPI UTrie2 * U_EXPORT2
237 0 : utrie2_openDummy(UTrie2ValueBits valueBits,
238 : uint32_t initialValue, uint32_t errorValue,
239 : UErrorCode *pErrorCode) {
240 : UTrie2 *trie;
241 : UTrie2Header *header;
242 : uint32_t *p;
243 : uint16_t *dest16;
244 : int32_t indexLength, dataLength, length, i;
245 : int32_t dataMove; /* >0 if the data is moved to the end of the index array */
246 :
247 0 : if(U_FAILURE(*pErrorCode)) {
248 0 : return 0;
249 : }
250 :
251 0 : if(valueBits<0 || UTRIE2_COUNT_VALUE_BITS<=valueBits) {
252 0 : *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
253 0 : return 0;
254 : }
255 :
256 : /* calculate the total length of the dummy trie data */
257 0 : indexLength=UTRIE2_INDEX_1_OFFSET;
258 0 : dataLength=UTRIE2_DATA_START_OFFSET+UTRIE2_DATA_GRANULARITY;
259 0 : length=(int32_t)sizeof(UTrie2Header)+indexLength*2;
260 0 : if(valueBits==UTRIE2_16_VALUE_BITS) {
261 0 : length+=dataLength*2;
262 : } else {
263 0 : length+=dataLength*4;
264 : }
265 :
266 : /* allocate the trie */
267 0 : trie=(UTrie2 *)uprv_malloc(sizeof(UTrie2));
268 0 : if(trie==NULL) {
269 0 : *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
270 0 : return 0;
271 : }
272 0 : uprv_memset(trie, 0, sizeof(UTrie2));
273 0 : trie->memory=uprv_malloc(length);
274 0 : if(trie->memory==NULL) {
275 0 : uprv_free(trie);
276 0 : *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
277 0 : return 0;
278 : }
279 0 : trie->length=length;
280 0 : trie->isMemoryOwned=TRUE;
281 :
282 : /* set the UTrie2 fields */
283 0 : if(valueBits==UTRIE2_16_VALUE_BITS) {
284 0 : dataMove=indexLength;
285 : } else {
286 0 : dataMove=0;
287 : }
288 :
289 0 : trie->indexLength=indexLength;
290 0 : trie->dataLength=dataLength;
291 0 : trie->index2NullOffset=UTRIE2_INDEX_2_OFFSET;
292 0 : trie->dataNullOffset=(uint16_t)dataMove;
293 0 : trie->initialValue=initialValue;
294 0 : trie->errorValue=errorValue;
295 0 : trie->highStart=0;
296 0 : trie->highValueIndex=dataMove+UTRIE2_DATA_START_OFFSET;
297 :
298 : /* set the header fields */
299 0 : header=(UTrie2Header *)trie->memory;
300 :
301 0 : header->signature=UTRIE2_SIG; /* "Tri2" */
302 0 : header->options=(uint16_t)valueBits;
303 :
304 0 : header->indexLength=(uint16_t)indexLength;
305 0 : header->shiftedDataLength=(uint16_t)(dataLength>>UTRIE2_INDEX_SHIFT);
306 0 : header->index2NullOffset=(uint16_t)UTRIE2_INDEX_2_OFFSET;
307 0 : header->dataNullOffset=(uint16_t)dataMove;
308 0 : header->shiftedHighStart=0;
309 :
310 : /* fill the index and data arrays */
311 0 : dest16=(uint16_t *)(header+1);
312 0 : trie->index=dest16;
313 :
314 : /* write the index-2 array values shifted right by UTRIE2_INDEX_SHIFT */
315 0 : for(i=0; i<UTRIE2_INDEX_2_BMP_LENGTH; ++i) {
316 0 : *dest16++=(uint16_t)(dataMove>>UTRIE2_INDEX_SHIFT); /* null data block */
317 : }
318 :
319 : /* write UTF-8 2-byte index-2 values, not right-shifted */
320 0 : for(i=0; i<(0xc2-0xc0); ++i) { /* C0..C1 */
321 0 : *dest16++=(uint16_t)(dataMove+UTRIE2_BAD_UTF8_DATA_OFFSET);
322 : }
323 0 : for(; i<(0xe0-0xc0); ++i) { /* C2..DF */
324 0 : *dest16++=(uint16_t)dataMove;
325 : }
326 :
327 : /* write the 16/32-bit data array */
328 0 : switch(valueBits) {
329 : case UTRIE2_16_VALUE_BITS:
330 : /* write 16-bit data values */
331 0 : trie->data16=dest16;
332 0 : trie->data32=NULL;
333 0 : for(i=0; i<0x80; ++i) {
334 0 : *dest16++=(uint16_t)initialValue;
335 : }
336 0 : for(; i<0xc0; ++i) {
337 0 : *dest16++=(uint16_t)errorValue;
338 : }
339 : /* highValue and reserved values */
340 0 : for(i=0; i<UTRIE2_DATA_GRANULARITY; ++i) {
341 0 : *dest16++=(uint16_t)initialValue;
342 : }
343 0 : break;
344 : case UTRIE2_32_VALUE_BITS:
345 : /* write 32-bit data values */
346 0 : p=(uint32_t *)dest16;
347 0 : trie->data16=NULL;
348 0 : trie->data32=p;
349 0 : for(i=0; i<0x80; ++i) {
350 0 : *p++=initialValue;
351 : }
352 0 : for(; i<0xc0; ++i) {
353 0 : *p++=errorValue;
354 : }
355 : /* highValue and reserved values */
356 0 : for(i=0; i<UTRIE2_DATA_GRANULARITY; ++i) {
357 0 : *p++=initialValue;
358 : }
359 0 : break;
360 : default:
361 0 : *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
362 0 : return 0;
363 : }
364 :
365 0 : return trie;
366 : }
367 :
368 : U_CAPI void U_EXPORT2
369 0 : utrie2_close(UTrie2 *trie) {
370 0 : if(trie!=NULL) {
371 0 : if(trie->isMemoryOwned) {
372 0 : uprv_free(trie->memory);
373 : }
374 0 : if(trie->newTrie!=NULL) {
375 0 : uprv_free(trie->newTrie->data);
376 0 : uprv_free(trie->newTrie);
377 : }
378 0 : uprv_free(trie);
379 : }
380 0 : }
381 :
382 : U_CAPI int32_t U_EXPORT2
383 0 : utrie2_getVersion(const void *data, int32_t length, UBool anyEndianOk) {
384 : uint32_t signature;
385 0 : if(length<16 || data==NULL || (U_POINTER_MASK_LSB(data, 3)!=0)) {
386 0 : return 0;
387 : }
388 0 : signature=*(const uint32_t *)data;
389 0 : if(signature==UTRIE2_SIG) {
390 0 : return 2;
391 : }
392 0 : if(anyEndianOk && signature==UTRIE2_OE_SIG) {
393 0 : return 2;
394 : }
395 0 : if(signature==UTRIE_SIG) {
396 0 : return 1;
397 : }
398 0 : if(anyEndianOk && signature==UTRIE_OE_SIG) {
399 0 : return 1;
400 : }
401 0 : return 0;
402 : }
403 :
404 : U_CAPI UBool U_EXPORT2
405 0 : utrie2_isFrozen(const UTrie2 *trie) {
406 0 : return (UBool)(trie->newTrie==NULL);
407 : }
408 :
409 : U_CAPI int32_t U_EXPORT2
410 0 : utrie2_serialize(const UTrie2 *trie,
411 : void *data, int32_t capacity,
412 : UErrorCode *pErrorCode) {
413 : /* argument check */
414 0 : if(U_FAILURE(*pErrorCode)) {
415 0 : return 0;
416 : }
417 :
418 0 : if( trie==NULL || trie->memory==NULL || trie->newTrie!=NULL ||
419 0 : capacity<0 || (capacity>0 && (data==NULL || (U_POINTER_MASK_LSB(data, 3)!=0)))
420 : ) {
421 0 : *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
422 0 : return 0;
423 : }
424 :
425 0 : if(capacity>=trie->length) {
426 0 : uprv_memcpy(data, trie->memory, trie->length);
427 : } else {
428 0 : *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
429 : }
430 0 : return trie->length;
431 : }
432 :
433 : U_CAPI int32_t U_EXPORT2
434 0 : utrie2_swap(const UDataSwapper *ds,
435 : const void *inData, int32_t length, void *outData,
436 : UErrorCode *pErrorCode) {
437 : const UTrie2Header *inTrie;
438 : UTrie2Header trie;
439 : int32_t dataLength, size;
440 : UTrie2ValueBits valueBits;
441 :
442 0 : if(U_FAILURE(*pErrorCode)) {
443 0 : return 0;
444 : }
445 0 : if(ds==NULL || inData==NULL || (length>=0 && outData==NULL)) {
446 0 : *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
447 0 : return 0;
448 : }
449 :
450 : /* setup and swapping */
451 0 : if(length>=0 && length<(int32_t)sizeof(UTrie2Header)) {
452 0 : *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
453 0 : return 0;
454 : }
455 :
456 0 : inTrie=(const UTrie2Header *)inData;
457 0 : trie.signature=ds->readUInt32(inTrie->signature);
458 0 : trie.options=ds->readUInt16(inTrie->options);
459 0 : trie.indexLength=ds->readUInt16(inTrie->indexLength);
460 0 : trie.shiftedDataLength=ds->readUInt16(inTrie->shiftedDataLength);
461 :
462 0 : valueBits=(UTrie2ValueBits)(trie.options&UTRIE2_OPTIONS_VALUE_BITS_MASK);
463 0 : dataLength=(int32_t)trie.shiftedDataLength<<UTRIE2_INDEX_SHIFT;
464 :
465 0 : if( trie.signature!=UTRIE2_SIG ||
466 0 : valueBits<0 || UTRIE2_COUNT_VALUE_BITS<=valueBits ||
467 0 : trie.indexLength<UTRIE2_INDEX_1_OFFSET ||
468 : dataLength<UTRIE2_DATA_START_OFFSET
469 : ) {
470 0 : *pErrorCode=U_INVALID_FORMAT_ERROR; /* not a UTrie */
471 0 : return 0;
472 : }
473 :
474 0 : size=sizeof(UTrie2Header)+trie.indexLength*2;
475 0 : switch(valueBits) {
476 : case UTRIE2_16_VALUE_BITS:
477 0 : size+=dataLength*2;
478 0 : break;
479 : case UTRIE2_32_VALUE_BITS:
480 0 : size+=dataLength*4;
481 0 : break;
482 : default:
483 0 : *pErrorCode=U_INVALID_FORMAT_ERROR;
484 0 : return 0;
485 : }
486 :
487 0 : if(length>=0) {
488 : UTrie2Header *outTrie;
489 :
490 0 : if(length<size) {
491 0 : *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR;
492 0 : return 0;
493 : }
494 :
495 0 : outTrie=(UTrie2Header *)outData;
496 :
497 : /* swap the header */
498 0 : ds->swapArray32(ds, &inTrie->signature, 4, &outTrie->signature, pErrorCode);
499 0 : ds->swapArray16(ds, &inTrie->options, 12, &outTrie->options, pErrorCode);
500 :
501 : /* swap the index and the data */
502 0 : switch(valueBits) {
503 : case UTRIE2_16_VALUE_BITS:
504 0 : ds->swapArray16(ds, inTrie+1, (trie.indexLength+dataLength)*2, outTrie+1, pErrorCode);
505 0 : break;
506 : case UTRIE2_32_VALUE_BITS:
507 0 : ds->swapArray16(ds, inTrie+1, trie.indexLength*2, outTrie+1, pErrorCode);
508 0 : ds->swapArray32(ds, (const uint16_t *)(inTrie+1)+trie.indexLength, dataLength*4,
509 0 : (uint16_t *)(outTrie+1)+trie.indexLength, pErrorCode);
510 0 : break;
511 : default:
512 0 : *pErrorCode=U_INVALID_FORMAT_ERROR;
513 0 : return 0;
514 : }
515 : }
516 :
517 0 : return size;
518 : }
519 :
520 : // utrie2_swapAnyVersion() should be defined here but lives in utrie2_builder.c
521 : // to avoid a dependency from utrie2.cpp on utrie.c.
522 :
523 : /* enumeration -------------------------------------------------------------- */
524 :
525 : #define MIN_VALUE(a, b) ((a)<(b) ? (a) : (b))
526 :
527 : /* default UTrie2EnumValue() returns the input value itself */
528 : static uint32_t U_CALLCONV
529 0 : enumSameValue(const void * /*context*/, uint32_t value) {
530 0 : return value;
531 : }
532 :
533 : /**
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.
536 : *
537 : * Currently requires start<limit and both start and limit must be multiples
538 : * of UTRIE2_DATA_BLOCK_LENGTH.
539 : *
540 : * Optimizations:
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.
545 : */
546 : static void
547 0 : enumEitherTrie(const UTrie2 *trie,
548 : UChar32 start, UChar32 limit,
549 : UTrie2EnumValue *enumValue, UTrie2EnumRange *enumRange, const void *context) {
550 : const uint32_t *data32;
551 : const uint16_t *idx;
552 :
553 : uint32_t value, prevValue, initialValue;
554 : UChar32 c, prev, highStart;
555 : int32_t j, i2Block, prevI2Block, index2NullOffset, block, prevBlock, nullBlock;
556 :
557 0 : if(enumRange==NULL) {
558 0 : return;
559 : }
560 0 : if(enumValue==NULL) {
561 0 : enumValue=enumSameValue;
562 : }
563 :
564 0 : if(trie->newTrie==NULL) {
565 : /* frozen trie */
566 0 : idx=trie->index;
567 0 : U_ASSERT(idx!=NULL); /* the following code assumes trie->newTrie is not NULL when idx is NULL */
568 0 : data32=trie->data32;
569 :
570 0 : index2NullOffset=trie->index2NullOffset;
571 0 : nullBlock=trie->dataNullOffset;
572 : } else {
573 : /* unfrozen, mutable trie */
574 0 : idx=NULL;
575 0 : data32=trie->newTrie->data;
576 0 : U_ASSERT(data32!=NULL); /* the following code assumes idx is not NULL when data32 is NULL */
577 :
578 0 : index2NullOffset=trie->newTrie->index2NullOffset;
579 0 : nullBlock=trie->newTrie->dataNullOffset;
580 : }
581 :
582 0 : highStart=trie->highStart;
583 :
584 : /* get the enumeration value that corresponds to an initial-value trie data entry */
585 0 : initialValue=enumValue(context, trie->initialValue);
586 :
587 : /* set variables for previous range */
588 0 : prevI2Block=-1;
589 0 : prevBlock=-1;
590 0 : prev=start;
591 0 : prevValue=0;
592 :
593 : /* enumerate index-2 blocks */
594 0 : for(c=start; c<limit && c<highStart;) {
595 : /* Code point limit for iterating inside this i2Block. */
596 0 : UChar32 tempLimit=c+UTRIE2_CP_PER_INDEX_1_ENTRY;
597 0 : if(limit<tempLimit) {
598 0 : tempLimit=limit;
599 : }
600 0 : if(c<=0xffff) {
601 0 : if(!U_IS_SURROGATE(c)) {
602 0 : i2Block=c>>UTRIE2_SHIFT_2;
603 0 : } else if(U_IS_SURROGATE_LEAD(c)) {
604 : /*
605 : * Enumerate values for lead surrogate code points, not code units:
606 : * This special block has half the normal length.
607 : */
608 0 : i2Block=UTRIE2_LSCP_INDEX_2_OFFSET;
609 0 : tempLimit=MIN_VALUE(0xdc00, limit);
610 : } else {
611 : /*
612 : * Switch back to the normal part of the index-2 table.
613 : * Enumerate the second half of the surrogates block.
614 : */
615 0 : i2Block=0xd800>>UTRIE2_SHIFT_2;
616 0 : tempLimit=MIN_VALUE(0xe000, limit);
617 : }
618 : } else {
619 : /* supplementary code points */
620 0 : if(idx!=NULL) {
621 0 : i2Block=idx[(UTRIE2_INDEX_1_OFFSET-UTRIE2_OMITTED_BMP_INDEX_1_LENGTH)+
622 0 : (c>>UTRIE2_SHIFT_1)];
623 : } else {
624 0 : i2Block=trie->newTrie->index1[c>>UTRIE2_SHIFT_1];
625 : }
626 0 : if(i2Block==prevI2Block && (c-prev)>=UTRIE2_CP_PER_INDEX_1_ENTRY) {
627 : /*
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.
631 : */
632 0 : c+=UTRIE2_CP_PER_INDEX_1_ENTRY;
633 0 : continue;
634 : }
635 : }
636 0 : prevI2Block=i2Block;
637 0 : if(i2Block==index2NullOffset) {
638 : /* this is the null index-2 block */
639 0 : if(prevValue!=initialValue) {
640 0 : if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
641 0 : return;
642 : }
643 0 : prevBlock=nullBlock;
644 0 : prev=c;
645 0 : prevValue=initialValue;
646 : }
647 0 : c+=UTRIE2_CP_PER_INDEX_1_ENTRY;
648 : } else {
649 : /* enumerate data blocks for one index-2 block */
650 : int32_t i2, i2Limit;
651 0 : i2=(c>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK;
652 0 : if((c>>UTRIE2_SHIFT_1)==(tempLimit>>UTRIE2_SHIFT_1)) {
653 0 : i2Limit=(tempLimit>>UTRIE2_SHIFT_2)&UTRIE2_INDEX_2_MASK;
654 : } else {
655 0 : i2Limit=UTRIE2_INDEX_2_BLOCK_LENGTH;
656 : }
657 0 : for(; i2<i2Limit; ++i2) {
658 0 : if(idx!=NULL) {
659 0 : block=(int32_t)idx[i2Block+i2]<<UTRIE2_INDEX_SHIFT;
660 : } else {
661 0 : block=trie->newTrie->index2[i2Block+i2];
662 : }
663 0 : if(block==prevBlock && (c-prev)>=UTRIE2_DATA_BLOCK_LENGTH) {
664 : /* the block is the same as the previous one, and filled with prevValue */
665 0 : c+=UTRIE2_DATA_BLOCK_LENGTH;
666 0 : continue;
667 : }
668 0 : prevBlock=block;
669 0 : if(block==nullBlock) {
670 : /* this is the null data block */
671 0 : if(prevValue!=initialValue) {
672 0 : if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
673 0 : return;
674 : }
675 0 : prev=c;
676 0 : prevValue=initialValue;
677 : }
678 0 : c+=UTRIE2_DATA_BLOCK_LENGTH;
679 : } else {
680 0 : for(j=0; j<UTRIE2_DATA_BLOCK_LENGTH; ++j) {
681 0 : value=enumValue(context, data32!=NULL ? data32[block+j] : idx[block+j]);
682 0 : if(value!=prevValue) {
683 0 : if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
684 0 : return;
685 : }
686 0 : prev=c;
687 0 : prevValue=value;
688 : }
689 0 : ++c;
690 : }
691 : }
692 : }
693 : }
694 : }
695 :
696 0 : if(c>limit) {
697 0 : c=limit; /* could be higher if in the index2NullOffset */
698 0 : } else if(c<limit) {
699 : /* c==highStart<limit */
700 : uint32_t highValue;
701 0 : if(idx!=NULL) {
702 0 : highValue=
703 0 : data32!=NULL ?
704 0 : data32[trie->highValueIndex] :
705 0 : idx[trie->highValueIndex];
706 : } else {
707 0 : highValue=trie->newTrie->data[trie->newTrie->dataLength-UTRIE2_DATA_GRANULARITY];
708 : }
709 0 : value=enumValue(context, highValue);
710 0 : if(value!=prevValue) {
711 0 : if(prev<c && !enumRange(context, prev, c-1, prevValue)) {
712 0 : return;
713 : }
714 0 : prev=c;
715 0 : prevValue=value;
716 : }
717 0 : c=limit;
718 : }
719 :
720 : /* deliver last range */
721 0 : enumRange(context, prev, c-1, prevValue);
722 : }
723 :
724 : U_CAPI void U_EXPORT2
725 0 : utrie2_enum(const UTrie2 *trie,
726 : UTrie2EnumValue *enumValue, UTrie2EnumRange *enumRange, const void *context) {
727 0 : enumEitherTrie(trie, 0, 0x110000, enumValue, enumRange, context);
728 0 : }
729 :
730 : U_CAPI void U_EXPORT2
731 0 : utrie2_enumForLeadSurrogate(const UTrie2 *trie, UChar32 lead,
732 : UTrie2EnumValue *enumValue, UTrie2EnumRange *enumRange,
733 : const void *context) {
734 0 : if(!U16_IS_LEAD(lead)) {
735 0 : return;
736 : }
737 0 : lead=(lead-0xd7c0)<<10; /* start code point */
738 0 : enumEitherTrie(trie, lead, lead+0x400, enumValue, enumRange, context);
739 : }
740 :
741 : /* C++ convenience wrappers ------------------------------------------------- */
742 :
743 : U_NAMESPACE_BEGIN
744 :
745 0 : uint16_t BackwardUTrie2StringIterator::previous16() {
746 0 : codePointLimit=codePointStart;
747 0 : if(start>=codePointStart) {
748 0 : codePoint=U_SENTINEL;
749 0 : return 0;
750 : }
751 : uint16_t result;
752 0 : UTRIE2_U16_PREV16(trie, start, codePointStart, codePoint, result);
753 0 : return result;
754 : }
755 :
756 0 : uint16_t ForwardUTrie2StringIterator::next16() {
757 0 : codePointStart=codePointLimit;
758 0 : if(codePointLimit==limit) {
759 0 : codePoint=U_SENTINEL;
760 0 : return 0;
761 : }
762 : uint16_t result;
763 0 : UTRIE2_U16_NEXT16(trie, codePointLimit, limit, codePoint, result);
764 0 : return result;
765 : }
766 :
767 : U_NAMESPACE_END
|