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