1 /* 2 ******************************************************************************* 3 * 4 * Copyright (C) 2004-2009, International Business Machines 5 * Corporation and others. All Rights Reserved. 6 * 7 ******************************************************************************* 8 * file name: ucase.c 9 * encoding: US-ASCII 10 * tab size: 8 (not used) 11 * indentation:4 12 * 13 * created on: 2004aug30 14 * created by: Markus W. Scherer 15 * 16 * Low-level Unicode character/string case mapping code. 17 * Much code moved here (and modified) from uchar.c. 18 */ 19 20 #include "unicode/utypes.h" 21 #include "unicode/uset.h" 22 #include "unicode/udata.h" /* UDataInfo */ 23 #include "ucmndata.h" /* DataHeader */ 24 #include "udatamem.h" 25 #include "umutex.h" 26 #include "uassert.h" 27 #include "cmemory.h" 28 #include "utrie2.h" 29 #include "ucase.h" 30 #include "ucln_cmn.h" 31 32 struct UCaseProps { 33 UDataMemory *mem; 34 const int32_t *indexes; 35 const uint16_t *exceptions; 36 const UChar *unfold; 37 38 UTrie2 trie; 39 uint8_t formatVersion[4]; 40 }; 41 42 /* data loading etc. -------------------------------------------------------- */ 43 44 #if UCASE_HARDCODE_DATA 45 46 /* ucase_props_data.c is machine-generated by gencase --csource */ 47 #include "ucase_props_data.c" 48 49 #else 50 51 static UBool U_CALLCONV 52 isAcceptable(void *context, 53 const char *type, const char *name, 54 const UDataInfo *pInfo) { 55 if( 56 pInfo->size>=20 && 57 pInfo->isBigEndian==U_IS_BIG_ENDIAN && 58 pInfo->charsetFamily==U_CHARSET_FAMILY && 59 pInfo->dataFormat[0]==UCASE_FMT_0 && /* dataFormat="cAsE" */ 60 pInfo->dataFormat[1]==UCASE_FMT_1 && 61 pInfo->dataFormat[2]==UCASE_FMT_2 && 62 pInfo->dataFormat[3]==UCASE_FMT_3 && 63 pInfo->formatVersion[0]==1 && 64 pInfo->formatVersion[2]==UTRIE_SHIFT && 65 pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT 66 ) { 67 UCaseProps *csp=(UCaseProps *)context; 68 uprv_memcpy(csp->formatVersion, pInfo->formatVersion, 4); 69 return TRUE; 70 } else { 71 return FALSE; 72 } 73 } 74 75 static UCaseProps * 76 ucase_openData(UCaseProps *cspProto, 77 const uint8_t *bin, int32_t length, UErrorCode *pErrorCode) { 78 UCaseProps *csp; 79 int32_t size; 80 81 cspProto->indexes=(const int32_t *)bin; 82 if( (length>=0 && length<16*4) || 83 cspProto->indexes[UCASE_IX_INDEX_TOP]<16 84 ) { 85 /* length or indexes[] too short for minimum indexes[] length of 16 */ 86 *pErrorCode=U_INVALID_FORMAT_ERROR; 87 return NULL; 88 } 89 size=cspProto->indexes[UCASE_IX_INDEX_TOP]*4; 90 if(length>=0) { 91 if(length>=size && length>=cspProto->indexes[UCASE_IX_LENGTH]) { 92 length-=size; 93 } else { 94 /* length too short for indexes[] or for the whole data length */ 95 *pErrorCode=U_INVALID_FORMAT_ERROR; 96 return NULL; 97 } 98 } 99 bin+=size; 100 /* from here on, assume that the sizes of the items fit into the total length */ 101 102 /* unserialize the trie, after indexes[] */ 103 size=cspProto->indexes[UCASE_IX_TRIE_SIZE]; 104 utrie_unserialize(&cspProto->trie, bin, size, pErrorCode); 105 if(U_FAILURE(*pErrorCode)) { 106 return NULL; 107 } 108 bin+=size; 109 110 /* get exceptions[] */ 111 size=2*cspProto->indexes[UCASE_IX_EXC_LENGTH]; 112 cspProto->exceptions=(const uint16_t *)bin; 113 bin+=size; 114 115 /* get unfold[] */ 116 size=2*cspProto->indexes[UCASE_IX_UNFOLD_LENGTH]; 117 if(size!=0) { 118 cspProto->unfold=(const UChar *)bin; 119 bin+=size; 120 } else { 121 cspProto->unfold=NULL; 122 } 123 124 /* allocate, copy, and return the new UCaseProps */ 125 csp=(UCaseProps *)uprv_malloc(sizeof(UCaseProps)); 126 if(csp==NULL) { 127 *pErrorCode=U_MEMORY_ALLOCATION_ERROR; 128 return NULL; 129 } else { 130 uprv_memcpy(csp, cspProto, sizeof(UCaseProps)); 131 return csp; 132 } 133 } 134 135 U_CAPI UCaseProps * U_EXPORT2 136 ucase_open(UErrorCode *pErrorCode) { 137 UCaseProps cspProto={ NULL }, *csp; 138 139 cspProto.mem=udata_openChoice(NULL, UCASE_DATA_TYPE, UCASE_DATA_NAME, isAcceptable, &cspProto, pErrorCode); 140 if(U_FAILURE(*pErrorCode)) { 141 return NULL; 142 } 143 144 csp=ucase_openData( 145 &cspProto, 146 udata_getMemory(cspProto.mem), 147 udata_getLength(cspProto.mem), 148 pErrorCode); 149 if(U_FAILURE(*pErrorCode)) { 150 udata_close(cspProto.mem); 151 return NULL; 152 } else { 153 return csp; 154 } 155 } 156 157 U_CAPI UCaseProps * U_EXPORT2 158 ucase_openBinary(const uint8_t *bin, int32_t length, UErrorCode *pErrorCode) { 159 UCaseProps cspProto={ NULL }; 160 const DataHeader *hdr; 161 162 if(U_FAILURE(*pErrorCode)) { 163 return NULL; 164 } 165 if(bin==NULL) { 166 *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; 167 return NULL; 168 } 169 170 /* check the header */ 171 if(length>=0 && length<20) { 172 *pErrorCode=U_INVALID_FORMAT_ERROR; 173 return NULL; 174 } 175 hdr=(const DataHeader *)bin; 176 if( 177 !(hdr->dataHeader.magic1==0xda && hdr->dataHeader.magic2==0x27 && 178 hdr->info.isBigEndian==U_IS_BIG_ENDIAN && 179 isAcceptable(&cspProto, UCASE_DATA_TYPE, UCASE_DATA_NAME, &hdr->info)) 180 ) { 181 *pErrorCode=U_INVALID_FORMAT_ERROR; 182 return NULL; 183 } 184 185 bin+=hdr->dataHeader.headerSize; 186 if(length>=0) { 187 length-=hdr->dataHeader.headerSize; 188 } 189 return ucase_openData(&cspProto, bin, length, pErrorCode); 190 } 191 192 #endif 193 194 U_CAPI void U_EXPORT2 195 ucase_close(UCaseProps *csp) { 196 if(csp!=NULL) { 197 #if !UCASE_HARDCODE_DATA 198 udata_close(csp->mem); 199 #endif 200 uprv_free(csp); 201 } 202 } 203 204 /* UCaseProps singleton ----------------------------------------------------- */ 205 206 #if !UCASE_HARDCODE_DATA 207 static UCaseProps *gCsp=NULL; 208 static UCaseProps *gCspDummy=NULL; 209 static UErrorCode gErrorCode=U_ZERO_ERROR; 210 static int8_t gHaveData=0; 211 #endif 212 213 #if !UCASE_HARDCODE_DATA 214 static UBool U_CALLCONV ucase_cleanup(void) { 215 ucase_close(gCsp); 216 gCsp=NULL; 217 ucase_close(gCspDummy); 218 gCspDummy=NULL; 219 gErrorCode=U_ZERO_ERROR; 220 gHaveData=0; 221 return TRUE; 222 } 223 #endif 224 225 U_CAPI const UCaseProps * U_EXPORT2 226 ucase_getSingleton(UErrorCode *pErrorCode) { 227 #if UCASE_HARDCODE_DATA 228 if(U_FAILURE(*pErrorCode)) { 229 return NULL; 230 } 231 return &ucase_props_singleton; 232 #else 233 int8_t haveData; 234 235 if(U_FAILURE(*pErrorCode)) { 236 return NULL; 237 } 238 239 UMTX_CHECK(NULL, gHaveData, haveData); 240 241 if(haveData>0) { 242 /* data was loaded */ 243 return gCsp; 244 } else if(haveData<0) { 245 /* data loading failed */ 246 *pErrorCode=gErrorCode; 247 return NULL; 248 } else /* haveData==0 */ { 249 /* load the data */ 250 UCaseProps *csp=ucase_open(pErrorCode); 251 if(U_FAILURE(*pErrorCode)) { 252 gHaveData=-1; 253 gErrorCode=*pErrorCode; 254 return NULL; 255 } 256 257 /* set the static variables */ 258 umtx_lock(NULL); 259 if(gCsp==NULL) { 260 gCsp=csp; 261 csp=NULL; 262 gHaveData=1; 263 ucln_common_registerCleanup(UCLN_COMMON_UCASE, ucase_cleanup); 264 } 265 umtx_unlock(NULL); 266 267 ucase_close(csp); 268 return gCsp; 269 } 270 #endif 271 } 272 273 #if !UCASE_HARDCODE_DATA 274 U_CAPI const UCaseProps * U_EXPORT2 275 ucase_getDummy(UErrorCode *pErrorCode) { 276 UCaseProps *csp; 277 278 if(U_FAILURE(*pErrorCode)) { 279 return NULL; 280 } 281 282 UMTX_CHECK(NULL, gCspDummy, csp); 283 284 if(csp!=NULL) { 285 /* the dummy object was already created */ 286 return csp; 287 } else /* csp==NULL */ { 288 /* create the dummy object */ 289 int32_t *indexes; 290 291 csp=(UCaseProps *)uprv_malloc(sizeof(UCaseProps)+UCASE_IX_TOP*4+UTRIE_DUMMY_SIZE); 292 if(csp==NULL) { 293 *pErrorCode=U_MEMORY_ALLOCATION_ERROR; 294 return NULL; 295 } 296 uprv_memset(csp, 0, sizeof(UCaseProps)+UCASE_IX_TOP*4); 297 298 csp->indexes=indexes=(int32_t *)(csp+1); 299 indexes[UCASE_IX_INDEX_TOP]=UCASE_IX_TOP; 300 301 indexes[UCASE_IX_TRIE_SIZE]= 302 utrie_unserializeDummy(&csp->trie, indexes+UCASE_IX_TOP, UTRIE_DUMMY_SIZE, 0, 0, TRUE, pErrorCode); 303 if(U_FAILURE(*pErrorCode)) { 304 uprv_free(csp); 305 return NULL; 306 } 307 308 csp->formatVersion[0]=1; 309 csp->formatVersion[2]=UTRIE_SHIFT; 310 csp->formatVersion[3]=UTRIE_INDEX_SHIFT; 311 312 /* set the static variables */ 313 umtx_lock(NULL); 314 if(gCspDummy==NULL) { 315 gCspDummy=csp; 316 csp=NULL; 317 ucln_common_registerCleanup(UCLN_COMMON_UCASE, ucase_cleanup); 318 } 319 umtx_unlock(NULL); 320 321 uprv_free(csp); 322 return gCspDummy; 323 } 324 } 325 #endif 326 327 /* set of property starts for UnicodeSet ------------------------------------ */ 328 329 static UBool U_CALLCONV 330 _enumPropertyStartsRange(const void *context, UChar32 start, UChar32 end, uint32_t value) { 331 /* add the start code point to the USet */ 332 const USetAdder *sa=(const USetAdder *)context; 333 sa->add(sa->set, start); 334 return TRUE; 335 } 336 337 U_CFUNC void U_EXPORT2 338 ucase_addPropertyStarts(const UCaseProps *csp, const USetAdder *sa, UErrorCode *pErrorCode) { 339 if(U_FAILURE(*pErrorCode)) { 340 return; 341 } 342 343 /* add the start code point of each same-value range of the trie */ 344 utrie2_enum(&csp->trie, NULL, _enumPropertyStartsRange, sa); 345 346 /* add code points with hardcoded properties, plus the ones following them */ 347 348 /* (none right now, see comment below) */ 349 350 /* 351 * Omit code points with hardcoded specialcasing properties 352 * because we do not build property UnicodeSets for them right now. 353 */ 354 } 355 356 /* data access primitives --------------------------------------------------- */ 357 358 #define GET_EXCEPTIONS(csp, props) ((csp)->exceptions+((props)>>UCASE_EXC_SHIFT)) 359 360 #define PROPS_HAS_EXCEPTION(props) ((props)&UCASE_EXCEPTION) 361 362 /* number of bits in an 8-bit integer value */ 363 static const uint8_t flagsOffset[256]={ 364 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 365 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 366 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 367 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 368 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 369 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 370 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 371 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 372 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 373 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 374 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 375 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 376 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 377 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 378 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 379 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 380 }; 381 382 #define HAS_SLOT(flags, idx) ((flags)&(1<<(idx))) 383 #define SLOT_OFFSET(flags, idx) flagsOffset[(flags)&((1<<(idx))-1)] 384 385 /* 386 * Get the value of an optional-value slot where HAS_SLOT(excWord, idx). 387 * 388 * @param excWord (in) initial exceptions word 389 * @param idx (in) desired slot index 390 * @param pExc16 (in/out) const uint16_t * after excWord=*pExc16++; 391 * moved to the last uint16_t of the value, use +1 for beginning of next slot 392 * @param value (out) int32_t or uint32_t output if hasSlot, otherwise not modified 393 */ 394 #define GET_SLOT_VALUE(excWord, idx, pExc16, value) \ 395 if(((excWord)&UCASE_EXC_DOUBLE_SLOTS)==0) { \ 396 (pExc16)+=SLOT_OFFSET(excWord, idx); \ 397 (value)=*pExc16; \ 398 } else { \ 399 (pExc16)+=2*SLOT_OFFSET(excWord, idx); \ 400 (value)=*pExc16++; \ 401 (value)=((value)<<16)|*pExc16; \ 402 } 403 404 /* simple case mappings ----------------------------------------------------- */ 405 406 U_CAPI UChar32 U_EXPORT2 407 ucase_tolower(const UCaseProps *csp, UChar32 c) { 408 uint16_t props=UTRIE2_GET16(&csp->trie, c); 409 if(!PROPS_HAS_EXCEPTION(props)) { 410 if(UCASE_GET_TYPE(props)>=UCASE_UPPER) { 411 c+=UCASE_GET_DELTA(props); 412 } 413 } else { 414 const uint16_t *pe=GET_EXCEPTIONS(csp, props); 415 uint16_t excWord=*pe++; 416 if(HAS_SLOT(excWord, UCASE_EXC_LOWER)) { 417 GET_SLOT_VALUE(excWord, UCASE_EXC_LOWER, pe, c); 418 } 419 } 420 return c; 421 } 422 423 U_CAPI UChar32 U_EXPORT2 424 ucase_toupper(const UCaseProps *csp, UChar32 c) { 425 uint16_t props=UTRIE2_GET16(&csp->trie, c); 426 if(!PROPS_HAS_EXCEPTION(props)) { 427 if(UCASE_GET_TYPE(props)==UCASE_LOWER) { 428 c+=UCASE_GET_DELTA(props); 429 } 430 } else { 431 const uint16_t *pe=GET_EXCEPTIONS(csp, props); 432 uint16_t excWord=*pe++; 433 if(HAS_SLOT(excWord, UCASE_EXC_UPPER)) { 434 GET_SLOT_VALUE(excWord, UCASE_EXC_UPPER, pe, c); 435 } 436 } 437 return c; 438 } 439 440 U_CAPI UChar32 U_EXPORT2 441 ucase_totitle(const UCaseProps *csp, UChar32 c) { 442 uint16_t props=UTRIE2_GET16(&csp->trie, c); 443 if(!PROPS_HAS_EXCEPTION(props)) { 444 if(UCASE_GET_TYPE(props)==UCASE_LOWER) { 445 c+=UCASE_GET_DELTA(props); 446 } 447 } else { 448 const uint16_t *pe=GET_EXCEPTIONS(csp, props); 449 uint16_t excWord=*pe++; 450 int32_t idx; 451 if(HAS_SLOT(excWord, UCASE_EXC_TITLE)) { 452 idx=UCASE_EXC_TITLE; 453 } else if(HAS_SLOT(excWord, UCASE_EXC_UPPER)) { 454 idx=UCASE_EXC_UPPER; 455 } else { 456 return c; 457 } 458 GET_SLOT_VALUE(excWord, idx, pe, c); 459 } 460 return c; 461 } 462 463 static const UChar iDot[2] = { 0x69, 0x307 }; 464 static const UChar jDot[2] = { 0x6a, 0x307 }; 465 static const UChar iOgonekDot[3] = { 0x12f, 0x307 }; 466 static const UChar iDotGrave[3] = { 0x69, 0x307, 0x300 }; 467 static const UChar iDotAcute[3] = { 0x69, 0x307, 0x301 }; 468 static const UChar iDotTilde[3] = { 0x69, 0x307, 0x303 }; 469 470 471 U_CFUNC void U_EXPORT2 472 ucase_addCaseClosure(const UCaseProps *csp, UChar32 c, const USetAdder *sa) { 473 uint16_t props; 474 475 /* 476 * Hardcode the case closure of i and its relatives and ignore the 477 * data file data for these characters. 478 * The Turkic dotless i and dotted I with their case mapping conditions 479 * and case folding option make the related characters behave specially. 480 * This code matches their closure behavior to their case folding behavior. 481 */ 482 483 switch(c) { 484 case 0x49: 485 /* regular i and I are in one equivalence class */ 486 sa->add(sa->set, 0x69); 487 return; 488 case 0x69: 489 sa->add(sa->set, 0x49); 490 return; 491 case 0x130: 492 /* dotted I is in a class with <0069 0307> (for canonical equivalence with <0049 0307>) */ 493 sa->addString(sa->set, iDot, 2); 494 return; 495 case 0x131: 496 /* dotless i is in a class by itself */ 497 return; 498 default: 499 /* otherwise use the data file data */ 500 break; 501 } 502 503 props=UTRIE2_GET16(&csp->trie, c); 504 if(!PROPS_HAS_EXCEPTION(props)) { 505 if(UCASE_GET_TYPE(props)!=UCASE_NONE) { 506 /* add the one simple case mapping, no matter what type it is */ 507 int32_t delta=UCASE_GET_DELTA(props); 508 if(delta!=0) { 509 sa->add(sa->set, c+delta); 510 } 511 } 512 } else { 513 /* 514 * c has exceptions, so there may be multiple simple and/or 515 * full case mappings. Add them all. 516 */ 517 const uint16_t *pe0, *pe=GET_EXCEPTIONS(csp, props); 518 const UChar *closure; 519 uint16_t excWord=*pe++; 520 int32_t idx, closureLength, fullLength, length; 521 522 pe0=pe; 523 524 /* add all simple case mappings */ 525 for(idx=UCASE_EXC_LOWER; idx<=UCASE_EXC_TITLE; ++idx) { 526 if(HAS_SLOT(excWord, idx)) { 527 pe=pe0; 528 GET_SLOT_VALUE(excWord, idx, pe, c); 529 sa->add(sa->set, c); 530 } 531 } 532 533 /* get the closure string pointer & length */ 534 if(HAS_SLOT(excWord, UCASE_EXC_CLOSURE)) { 535 pe=pe0; 536 GET_SLOT_VALUE(excWord, UCASE_EXC_CLOSURE, pe, closureLength); 537 closureLength&=UCASE_CLOSURE_MAX_LENGTH; /* higher bits are reserved */ 538 closure=(const UChar *)pe+1; /* behind this slot, unless there are full case mappings */ 539 } else { 540 closureLength=0; 541 closure=NULL; 542 } 543 544 /* add the full case folding */ 545 if(HAS_SLOT(excWord, UCASE_EXC_FULL_MAPPINGS)) { 546 pe=pe0; 547 GET_SLOT_VALUE(excWord, UCASE_EXC_FULL_MAPPINGS, pe, fullLength); 548 549 /* start of full case mapping strings */ 550 ++pe; 551 552 fullLength&=0xffff; /* bits 16 and higher are reserved */ 553 554 /* skip the lowercase result string */ 555 pe+=fullLength&UCASE_FULL_LOWER; 556 fullLength>>=4; 557 558 /* add the full case folding string */ 559 length=fullLength&0xf; 560 if(length!=0) { 561 sa->addString(sa->set, (const UChar *)pe, length); 562 pe+=length; 563 } 564 565 /* skip the uppercase and titlecase strings */ 566 fullLength>>=4; 567 pe+=fullLength&0xf; 568 fullLength>>=4; 569 pe+=fullLength; 570 571 closure=(const UChar *)pe; /* behind full case mappings */ 572 } 573 574 /* add each code point in the closure string */ 575 for(idx=0; idx<closureLength;) { 576 U16_NEXT_UNSAFE(closure, idx, c); 577 sa->add(sa->set, c); 578 } 579 } 580 } 581 582 /* 583 * compare s, which has a length, with t, which has a maximum length or is NUL-terminated 584 * must be length>0 and max>0 and length<=max 585 */ 586 static U_INLINE int32_t 587 strcmpMax(const UChar *s, int32_t length, const UChar *t, int32_t max) { 588 int32_t c1, c2; 589 590 max-=length; /* we require length<=max, so no need to decrement max in the loop */ 591 do { 592 c1=*s++; 593 c2=*t++; 594 if(c2==0) { 595 return 1; /* reached the end of t but not of s */ 596 } 597 c1-=c2; 598 if(c1!=0) { 599 return c1; /* return difference result */ 600 } 601 } while(--length>0); 602 /* ends with length==0 */ 603 604 if(max==0 || *t==0) { 605 return 0; /* equal to length of both strings */ 606 } else { 607 return -max; /* return lengh difference */ 608 } 609 } 610 611 U_CFUNC UBool U_EXPORT2 612 ucase_addStringCaseClosure(const UCaseProps *csp, const UChar *s, int32_t length, const USetAdder *sa) { 613 const UChar *unfold, *p; 614 int32_t i, start, limit, result, unfoldRows, unfoldRowWidth, unfoldStringWidth; 615 616 if(csp->unfold==NULL || s==NULL) { 617 return FALSE; /* no reverse case folding data, or no string */ 618 } 619 if(length<=1) { 620 /* the string is too short to find any match */ 621 /* 622 * more precise would be: 623 * if(!u_strHasMoreChar32Than(s, length, 1)) 624 * but this does not make much practical difference because 625 * a single supplementary code point would just not be found 626 */ 627 return FALSE; 628 } 629 630 unfold=csp->unfold; 631 unfoldRows=unfold[UCASE_UNFOLD_ROWS]; 632 unfoldRowWidth=unfold[UCASE_UNFOLD_ROW_WIDTH]; 633 unfoldStringWidth=unfold[UCASE_UNFOLD_STRING_WIDTH]; 634 unfold+=unfoldRowWidth; 635 636 if(length>unfoldStringWidth) { 637 /* the string is too long to find any match */ 638 return FALSE; 639 } 640 641 /* do a binary search for the string */ 642 start=0; 643 limit=unfoldRows; 644 while(start<limit) { 645 i=(start+limit)/2; 646 p=unfold+(i*unfoldRowWidth); 647 result=strcmpMax(s, length, p, unfoldStringWidth); 648 649 if(result==0) { 650 /* found the string: add each code point, and its case closure */ 651 UChar32 c; 652 653 for(i=unfoldStringWidth; i<unfoldRowWidth && p[i]!=0;) { 654 U16_NEXT_UNSAFE(p, i, c); 655 sa->add(sa->set, c); 656 ucase_addCaseClosure(csp, c, sa); 657 } 658 return TRUE; 659 } else if(result<0) { 660 limit=i; 661 } else /* result>0 */ { 662 start=i+1; 663 } 664 } 665 666 return FALSE; /* string not found */ 667 } 668 669 /** @return UCASE_NONE, UCASE_LOWER, UCASE_UPPER, UCASE_TITLE */ 670 U_CAPI int32_t U_EXPORT2 671 ucase_getType(const UCaseProps *csp, UChar32 c) { 672 uint16_t props=UTRIE2_GET16(&csp->trie, c); 673 return UCASE_GET_TYPE(props); 674 } 675 676 /** @return same as ucase_getType(), or <0 if c is case-ignorable */ 677 U_CAPI int32_t U_EXPORT2 678 ucase_getTypeOrIgnorable(const UCaseProps *csp, UChar32 c) { 679 uint16_t props=UTRIE2_GET16(&csp->trie, c); 680 int32_t type=UCASE_GET_TYPE(props); 681 if(type!=UCASE_NONE) { 682 return type; 683 } else if( 684 c==0x307 || 685 (props&(UCASE_EXCEPTION|UCASE_CASE_IGNORABLE))==UCASE_CASE_IGNORABLE 686 ) { 687 return -1; /* case-ignorable */ 688 } else { 689 return 0; /* c is neither cased nor case-ignorable */ 690 } 691 } 692 693 /** @return UCASE_NO_DOT, UCASE_SOFT_DOTTED, UCASE_ABOVE, UCASE_OTHER_ACCENT */ 694 static U_INLINE int32_t 695 getDotType(const UCaseProps *csp, UChar32 c) { 696 uint16_t props=UTRIE2_GET16(&csp->trie, c); 697 if(!PROPS_HAS_EXCEPTION(props)) { 698 return props&UCASE_DOT_MASK; 699 } else { 700 const uint16_t *pe=GET_EXCEPTIONS(csp, props); 701 return (*pe>>UCASE_EXC_DOT_SHIFT)&UCASE_DOT_MASK; 702 } 703 } 704 705 U_CAPI UBool U_EXPORT2 706 ucase_isSoftDotted(const UCaseProps *csp, UChar32 c) { 707 return (UBool)(getDotType(csp, c)==UCASE_SOFT_DOTTED); 708 } 709 710 U_CAPI UBool U_EXPORT2 711 ucase_isCaseSensitive(const UCaseProps *csp, UChar32 c) { 712 uint16_t props=UTRIE2_GET16(&csp->trie, c); 713 return (UBool)((props&UCASE_SENSITIVE)!=0); 714 } 715 716 /* string casing ------------------------------------------------------------ */ 717 718 /* 719 * These internal functions form the core of string case mappings. 720 * They map single code points to result code points or strings and take 721 * all necessary conditions (context, locale ID, options) into account. 722 * 723 * They do not iterate over the source or write to the destination 724 * so that the same functions are useful for non-standard string storage, 725 * such as in a Replaceable (for Transliterator) or UTF-8/32 strings etc. 726 * For the same reason, the "surrounding text" context is passed in as a 727 * UCaseContextIterator which does not make any assumptions about 728 * the underlying storage. 729 * 730 * This section contains helper functions that check for conditions 731 * in the input text surrounding the current code point 732 * according to SpecialCasing.txt. 733 * 734 * Each helper function gets the index 735 * - after the current code point if it looks at following text 736 * - before the current code point if it looks at preceding text 737 * 738 * Unicode 3.2 UAX 21 "Case Mappings" defines the conditions as follows: 739 * 740 * Final_Sigma 741 * C is preceded by a sequence consisting of 742 * a cased letter and a case-ignorable sequence, 743 * and C is not followed by a sequence consisting of 744 * an ignorable sequence and then a cased letter. 745 * 746 * More_Above 747 * C is followed by one or more characters of combining class 230 (ABOVE) 748 * in the combining character sequence. 749 * 750 * After_Soft_Dotted 751 * The last preceding character with combining class of zero before C 752 * was Soft_Dotted, 753 * and there is no intervening combining character class 230 (ABOVE). 754 * 755 * Before_Dot 756 * C is followed by combining dot above (U+0307). 757 * Any sequence of characters with a combining class that is neither 0 nor 230 758 * may intervene between the current character and the combining dot above. 759 * 760 * The erratum from 2002-10-31 adds the condition 761 * 762 * After_I 763 * The last preceding base character was an uppercase I, and there is no 764 * intervening combining character class 230 (ABOVE). 765 * 766 * (See Jitterbug 2344 and the comments on After_I below.) 767 * 768 * Helper definitions in Unicode 3.2 UAX 21: 769 * 770 * D1. A character C is defined to be cased 771 * if it meets any of the following criteria: 772 * 773 * - The general category of C is Titlecase Letter (Lt) 774 * - In [CoreProps], C has one of the properties Uppercase, or Lowercase 775 * - Given D = NFD(C), then it is not the case that: 776 * D = UCD_lower(D) = UCD_upper(D) = UCD_title(D) 777 * (This third criterium does not add any characters to the list 778 * for Unicode 3.2. Ignored.) 779 * 780 * D2. A character C is defined to be case-ignorable 781 * if it meets either of the following criteria: 782 * 783 * - The general category of C is 784 * Nonspacing Mark (Mn), or Enclosing Mark (Me), or Format Control (Cf), or 785 * Letter Modifier (Lm), or Symbol Modifier (Sk) 786 * - C is one of the following characters 787 * U+0027 APOSTROPHE 788 * U+00AD SOFT HYPHEN (SHY) 789 * U+2019 RIGHT SINGLE QUOTATION MARK 790 * (the preferred character for apostrophe) 791 * 792 * D3. A case-ignorable sequence is a sequence of 793 * zero or more case-ignorable characters. 794 */ 795 796 #define is_a(c) ((c)=='a' || (c)=='A') 797 #define is_d(c) ((c)=='d' || (c)=='D') 798 #define is_e(c) ((c)=='e' || (c)=='E') 799 #define is_i(c) ((c)=='i' || (c)=='I') 800 #define is_l(c) ((c)=='l' || (c)=='L') 801 #define is_n(c) ((c)=='n' || (c)=='N') 802 #define is_r(c) ((c)=='r' || (c)=='R') 803 #define is_t(c) ((c)=='t' || (c)=='T') 804 #define is_u(c) ((c)=='u' || (c)=='U') 805 #define is_z(c) ((c)=='z' || (c)=='Z') 806 807 /* separator? */ 808 #define is_sep(c) ((c)=='_' || (c)=='-' || (c)==0) 809 810 /** 811 * Requires non-NULL locale ID but otherwise does the equivalent of 812 * checking for language codes as if uloc_getLanguage() were called: 813 * Accepts both 2- and 3-letter codes and accepts case variants. 814 */ 815 U_CFUNC int32_t 816 ucase_getCaseLocale(const char *locale, int32_t *locCache) { 817 int32_t result; 818 char c; 819 820 if(locCache!=NULL && (result=*locCache)!=UCASE_LOC_UNKNOWN) { 821 return result; 822 } 823 824 result=UCASE_LOC_ROOT; 825 826 /* 827 * This function used to use uloc_getLanguage(), but the current code 828 * removes the dependency of this low-level code on uloc implementation code 829 * and is faster because not the whole locale ID has to be 830 * examined and copied/transformed. 831 * 832 * Because this code does not want to depend on uloc, the caller must 833 * pass in a non-NULL locale, i.e., may need to call uloc_getDefault(). 834 */ 835 c=*locale++; 836 if(is_t(c)) { 837 /* tr or tur? */ 838 c=*locale++; 839 if(is_u(c)) { 840 c=*locale++; 841 } 842 if(is_r(c)) { 843 c=*locale; 844 if(is_sep(c)) { 845 result=UCASE_LOC_TURKISH; 846 } 847 } 848 } else if(is_a(c)) { 849 /* az or aze? */ 850 c=*locale++; 851 if(is_z(c)) { 852 c=*locale++; 853 if(is_e(c)) { 854 c=*locale; 855 } 856 if(is_sep(c)) { 857 result=UCASE_LOC_TURKISH; 858 } 859 } 860 } else if(is_l(c)) { 861 /* lt or lit? */ 862 c=*locale++; 863 if(is_i(c)) { 864 c=*locale++; 865 } 866 if(is_t(c)) { 867 c=*locale; 868 if(is_sep(c)) { 869 result=UCASE_LOC_LITHUANIAN; 870 } 871 } 872 } else if(is_n(c)) { 873 /* nl or nld? */ 874 c=*locale++; 875 if(is_l(c)) { 876 c=*locale++; 877 if(is_d(c)) { 878 c=*locale; 879 } 880 if(is_sep(c)) { 881 result=UCASE_LOC_DUTCH; 882 } 883 } 884 } 885 886 if(locCache!=NULL) { 887 *locCache=result; 888 } 889 return result; 890 } 891 892 /* Is followed by {case-ignorable}* cased ? (dir determines looking forward/backward) */ 893 static UBool 894 isFollowedByCasedLetter(const UCaseProps *csp, UCaseContextIterator *iter, void *context, int8_t dir) { 895 UChar32 c; 896 uint16_t props; 897 898 if(iter==NULL) { 899 return FALSE; 900 } 901 902 for(/* dir!=0 sets direction */; (c=iter(context, dir))>=0; dir=0) { 903 props=UTRIE2_GET16(&csp->trie, c); 904 if(UCASE_GET_TYPE(props)!=UCASE_NONE) { 905 return TRUE; /* followed by cased letter */ 906 } else if(c==0x307 || (props&(UCASE_EXCEPTION|UCASE_CASE_IGNORABLE))==UCASE_CASE_IGNORABLE) { 907 /* case-ignorable, continue with the loop */ 908 } else { 909 return FALSE; /* not ignorable */ 910 } 911 } 912 913 return FALSE; /* not followed by cased letter */ 914 } 915 916 /* Is preceded by Soft_Dotted character with no intervening cc=230 ? */ 917 static UBool 918 isPrecededBySoftDotted(const UCaseProps *csp, UCaseContextIterator *iter, void *context) { 919 UChar32 c; 920 int32_t dotType; 921 int8_t dir; 922 923 if(iter==NULL) { 924 return FALSE; 925 } 926 927 for(dir=-1; (c=iter(context, dir))>=0; dir=0) { 928 dotType=getDotType(csp, c); 929 if(dotType==UCASE_SOFT_DOTTED) { 930 return TRUE; /* preceded by TYPE_i */ 931 } else if(dotType!=UCASE_OTHER_ACCENT) { 932 return FALSE; /* preceded by different base character (not TYPE_i), or intervening cc==230 */ 933 } 934 } 935 936 return FALSE; /* not preceded by TYPE_i */ 937 } 938 939 /* 940 * See Jitterbug 2344: 941 * The condition After_I for Turkic-lowercasing of U+0307 combining dot above 942 * is checked in ICU 2.0, 2.1, 2.6 but was not in 2.2 & 2.4 because 943 * we made those releases compatible with Unicode 3.2 which had not fixed 944 * a related bug in SpecialCasing.txt. 945 * 946 * From the Jitterbug 2344 text: 947 * ... this bug is listed as a Unicode erratum 948 * from 2002-10-31 at http://www.unicode.org/uni2errata/UnicodeErrata.html 949 * <quote> 950 * There are two errors in SpecialCasing.txt. 951 * 1. Missing semicolons on two lines. ... [irrelevant for ICU] 952 * 2. An incorrect context definition. Correct as follows: 953 * < 0307; ; 0307; 0307; tr After_Soft_Dotted; # COMBINING DOT ABOVE 954 * < 0307; ; 0307; 0307; az After_Soft_Dotted; # COMBINING DOT ABOVE 955 * --- 956 * > 0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE 957 * > 0307; ; 0307; 0307; az After_I; # COMBINING DOT ABOVE 958 * where the context After_I is defined as: 959 * The last preceding base character was an uppercase I, and there is no 960 * intervening combining character class 230 (ABOVE). 961 * </quote> 962 * 963 * Note that SpecialCasing.txt even in Unicode 3.2 described the condition as: 964 * 965 * # When lowercasing, remove dot_above in the sequence I + dot_above, which will turn into i. 966 * # This matches the behavior of the canonically equivalent I-dot_above 967 * 968 * See also the description in this place in older versions of uchar.c (revision 1.100). 969 * 970 * Markus W. Scherer 2003-feb-15 971 */ 972 973 /* Is preceded by base character 'I' with no intervening cc=230 ? */ 974 static UBool 975 isPrecededBy_I(const UCaseProps *csp, UCaseContextIterator *iter, void *context) { 976 UChar32 c; 977 int32_t dotType; 978 int8_t dir; 979 980 if(iter==NULL) { 981 return FALSE; 982 } 983 984 for(dir=-1; (c=iter(context, dir))>=0; dir=0) { 985 if(c==0x49) { 986 return TRUE; /* preceded by I */ 987 } 988 dotType=getDotType(csp, c); 989 if(dotType!=UCASE_OTHER_ACCENT) { 990 return FALSE; /* preceded by different base character (not I), or intervening cc==230 */ 991 } 992 } 993 994 return FALSE; /* not preceded by I */ 995 } 996 997 /* Is followed by one or more cc==230 ? */ 998 static UBool 999 isFollowedByMoreAbove(const UCaseProps *csp, UCaseContextIterator *iter, void *context) { 1000 UChar32 c; 1001 int32_t dotType; 1002 int8_t dir; 1003 1004 if(iter==NULL) { 1005 return FALSE; 1006 } 1007 1008 for(dir=1; (c=iter(context, dir))>=0; dir=0) { 1009 dotType=getDotType(csp, c); 1010 if(dotType==UCASE_ABOVE) { 1011 return TRUE; /* at least one cc==230 following */ 1012 } else if(dotType!=UCASE_OTHER_ACCENT) { 1013 return FALSE; /* next base character, no more cc==230 following */ 1014 } 1015 } 1016 1017 return FALSE; /* no more cc==230 following */ 1018 } 1019 1020 /* Is followed by a dot above (without cc==230 in between) ? */ 1021 static UBool 1022 isFollowedByDotAbove(const UCaseProps *csp, UCaseContextIterator *iter, void *context) { 1023 UChar32 c; 1024 int32_t dotType; 1025 int8_t dir; 1026 1027 if(iter==NULL) { 1028 return FALSE; 1029 } 1030 1031 for(dir=1; (c=iter(context, dir))>=0; dir=0) { 1032 if(c==0x307) { 1033 return TRUE; 1034 } 1035 dotType=getDotType(csp, c); 1036 if(dotType!=UCASE_OTHER_ACCENT) { 1037 return FALSE; /* next base character or cc==230 in between */ 1038 } 1039 } 1040 1041 return FALSE; /* no dot above following */ 1042 } 1043 1044 U_CAPI int32_t U_EXPORT2 1045 ucase_toFullLower(const UCaseProps *csp, UChar32 c, 1046 UCaseContextIterator *iter, void *context, 1047 const UChar **pString, 1048 const char *locale, int32_t *locCache) 1049 { 1050 UChar32 result=c; 1051 uint16_t props=UTRIE2_GET16(&csp->trie, c); 1052 if(!PROPS_HAS_EXCEPTION(props)) { 1053 if(UCASE_GET_TYPE(props)>=UCASE_UPPER) { 1054 result=c+UCASE_GET_DELTA(props); 1055 } 1056 } else { 1057 const uint16_t *pe=GET_EXCEPTIONS(csp, props), *pe2; 1058 uint16_t excWord=*pe++; 1059 int32_t full; 1060 1061 pe2=pe; 1062 1063 if(excWord&UCASE_EXC_CONDITIONAL_SPECIAL) { 1064 /* use hardcoded conditions and mappings */ 1065 int32_t loc=ucase_getCaseLocale(locale, locCache); 1066 1067 /* 1068 * Test for conditional mappings first 1069 * (otherwise the unconditional default mappings are always taken), 1070 * then test for characters that have unconditional mappings in SpecialCasing.txt, 1071 * then get the UnicodeData.txt mappings. 1072 */ 1073 if( loc==UCASE_LOC_LITHUANIAN && 1074 /* base characters, find accents above */ 1075 (((c==0x49 || c==0x4a || c==0x12e) && 1076 isFollowedByMoreAbove(csp, iter, context)) || 1077 /* precomposed with accent above, no need to find one */ 1078 (c==0xcc || c==0xcd || c==0x128)) 1079 ) { 1080 /* 1081 # Lithuanian 1082 1083 # Lithuanian retains the dot in a lowercase i when followed by accents. 1084 1085 # Introduce an explicit dot above when lowercasing capital I's and J's 1086 # whenever there are more accents above. 1087 # (of the accents used in Lithuanian: grave, acute, tilde above, and ogonek) 1088 1089 0049; 0069 0307; 0049; 0049; lt More_Above; # LATIN CAPITAL LETTER I 1090 004A; 006A 0307; 004A; 004A; lt More_Above; # LATIN CAPITAL LETTER J 1091 012E; 012F 0307; 012E; 012E; lt More_Above; # LATIN CAPITAL LETTER I WITH OGONEK 1092 00CC; 0069 0307 0300; 00CC; 00CC; lt; # LATIN CAPITAL LETTER I WITH GRAVE 1093 00CD; 0069 0307 0301; 00CD; 00CD; lt; # LATIN CAPITAL LETTER I WITH ACUTE 1094 0128; 0069 0307 0303; 0128; 0128; lt; # LATIN CAPITAL LETTER I WITH TILDE 1095 */ 1096 switch(c) { 1097 case 0x49: /* LATIN CAPITAL LETTER I */ 1098 *pString=iDot; 1099 return 2; 1100 case 0x4a: /* LATIN CAPITAL LETTER J */ 1101 *pString=jDot; 1102 return 2; 1103 case 0x12e: /* LATIN CAPITAL LETTER I WITH OGONEK */ 1104 *pString=iOgonekDot; 1105 return 2; 1106 case 0xcc: /* LATIN CAPITAL LETTER I WITH GRAVE */ 1107 *pString=iDotGrave; 1108 return 3; 1109 case 0xcd: /* LATIN CAPITAL LETTER I WITH ACUTE */ 1110 *pString=iDotAcute; 1111 return 3; 1112 case 0x128: /* LATIN CAPITAL LETTER I WITH TILDE */ 1113 *pString=iDotTilde; 1114 return 3; 1115 default: 1116 return 0; /* will not occur */ 1117 } 1118 /* # Turkish and Azeri */ 1119 } else if(loc==UCASE_LOC_TURKISH && c==0x130) { 1120 /* 1121 # I and i-dotless; I-dot and i are case pairs in Turkish and Azeri 1122 # The following rules handle those cases. 1123 1124 0130; 0069; 0130; 0130; tr # LATIN CAPITAL LETTER I WITH DOT ABOVE 1125 0130; 0069; 0130; 0130; az # LATIN CAPITAL LETTER I WITH DOT ABOVE 1126 */ 1127 return 0x69; 1128 } else if(loc==UCASE_LOC_TURKISH && c==0x307 && isPrecededBy_I(csp, iter, context)) { 1129 /* 1130 # When lowercasing, remove dot_above in the sequence I + dot_above, which will turn into i. 1131 # This matches the behavior of the canonically equivalent I-dot_above 1132 1133 0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE 1134 0307; ; 0307; 0307; az After_I; # COMBINING DOT ABOVE 1135 */ 1136 return 0; /* remove the dot (continue without output) */ 1137 } else if(loc==UCASE_LOC_TURKISH && c==0x49 && !isFollowedByDotAbove(csp, iter, context)) { 1138 /* 1139 # When lowercasing, unless an I is before a dot_above, it turns into a dotless i. 1140 1141 0049; 0131; 0049; 0049; tr Not_Before_Dot; # LATIN CAPITAL LETTER I 1142 0049; 0131; 0049; 0049; az Not_Before_Dot; # LATIN CAPITAL LETTER I 1143 */ 1144 return 0x131; 1145 } else if(c==0x130) { 1146 /* 1147 # Preserve canonical equivalence for I with dot. Turkic is handled below. 1148 1149 0130; 0069 0307; 0130; 0130; # LATIN CAPITAL LETTER I WITH DOT ABOVE 1150 */ 1151 *pString=iDot; 1152 return 2; 1153 } else if( c==0x3a3 && 1154 !isFollowedByCasedLetter(csp, iter, context, 1) && 1155 isFollowedByCasedLetter(csp, iter, context, -1) /* -1=preceded */ 1156 ) { 1157 /* greek capital sigma maps depending on surrounding cased letters (see SpecialCasing.txt) */ 1158 /* 1159 # Special case for final form of sigma 1160 1161 03A3; 03C2; 03A3; 03A3; Final_Sigma; # GREEK CAPITAL LETTER SIGMA 1162 */ 1163 return 0x3c2; /* greek small final sigma */ 1164 } else { 1165 /* no known conditional special case mapping, use a normal mapping */ 1166 } 1167 } else if(HAS_SLOT(excWord, UCASE_EXC_FULL_MAPPINGS)) { 1168 GET_SLOT_VALUE(excWord, UCASE_EXC_FULL_MAPPINGS, pe, full); 1169 full&=UCASE_FULL_LOWER; 1170 if(full!=0) { 1171 /* set the output pointer to the lowercase mapping */ 1172 *pString=pe+1; 1173 1174 /* return the string length */ 1175 return full; 1176 } 1177 } 1178 1179 if(HAS_SLOT(excWord, UCASE_EXC_LOWER)) { 1180 GET_SLOT_VALUE(excWord, UCASE_EXC_LOWER, pe2, result); 1181 } 1182 } 1183 1184 return (result==c) ? ~result : result; 1185 } 1186 1187 /* internal */ 1188 static int32_t 1189 toUpperOrTitle(const UCaseProps *csp, UChar32 c, 1190 UCaseContextIterator *iter, void *context, 1191 const UChar **pString, 1192 const char *locale, int32_t *locCache, 1193 UBool upperNotTitle) { 1194 UChar32 result=c; 1195 uint16_t props=UTRIE2_GET16(&csp->trie, c); 1196 if(!PROPS_HAS_EXCEPTION(props)) { 1197 if(UCASE_GET_TYPE(props)==UCASE_LOWER) { 1198 result=c+UCASE_GET_DELTA(props); 1199 } 1200 } else { 1201 const uint16_t *pe=GET_EXCEPTIONS(csp, props), *pe2; 1202 uint16_t excWord=*pe++; 1203 int32_t full, idx; 1204 1205 pe2=pe; 1206 1207 if(excWord&UCASE_EXC_CONDITIONAL_SPECIAL) { 1208 /* use hardcoded conditions and mappings */ 1209 int32_t loc=ucase_getCaseLocale(locale, locCache); 1210 1211 if(loc==UCASE_LOC_TURKISH && c==0x69) { 1212 /* 1213 # Turkish and Azeri 1214 1215 # I and i-dotless; I-dot and i are case pairs in Turkish and Azeri 1216 # The following rules handle those cases. 1217 1218 # When uppercasing, i turns into a dotted capital I 1219 1220 0069; 0069; 0130; 0130; tr; # LATIN SMALL LETTER I 1221 0069; 0069; 0130; 0130; az; # LATIN SMALL LETTER I 1222 */ 1223 return 0x130; 1224 } else if(loc==UCASE_LOC_LITHUANIAN && c==0x307 && isPrecededBySoftDotted(csp, iter, context)) { 1225 /* 1226 # Lithuanian 1227 1228 # Lithuanian retains the dot in a lowercase i when followed by accents. 1229 1230 # Remove DOT ABOVE after "i" with upper or titlecase 1231 1232 0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE 1233 */ 1234 return 0; /* remove the dot (continue without output) */ 1235 } else { 1236 /* no known conditional special case mapping, use a normal mapping */ 1237 } 1238 } else if(HAS_SLOT(excWord, UCASE_EXC_FULL_MAPPINGS)) { 1239 GET_SLOT_VALUE(excWord, UCASE_EXC_FULL_MAPPINGS, pe, full); 1240 1241 /* start of full case mapping strings */ 1242 ++pe; 1243 1244 /* skip the lowercase and case-folding result strings */ 1245 pe+=full&UCASE_FULL_LOWER; 1246 full>>=4; 1247 pe+=full&0xf; 1248 full>>=4; 1249 1250 if(upperNotTitle) { 1251 full&=0xf; 1252 } else { 1253 /* skip the uppercase result string */ 1254 pe+=full&0xf; 1255 full=(full>>4)&0xf; 1256 } 1257 1258 if(full!=0) { 1259 /* set the output pointer to the result string */ 1260 *pString=pe; 1261 1262 /* return the string length */ 1263 return full; 1264 } 1265 } 1266 1267 if(!upperNotTitle && HAS_SLOT(excWord, UCASE_EXC_TITLE)) { 1268 idx=UCASE_EXC_TITLE; 1269 } else if(HAS_SLOT(excWord, UCASE_EXC_UPPER)) { 1270 /* here, titlecase is same as uppercase */ 1271 idx=UCASE_EXC_UPPER; 1272 } else { 1273 return ~c; 1274 } 1275 GET_SLOT_VALUE(excWord, idx, pe2, result); 1276 } 1277 1278 return (result==c) ? ~result : result; 1279 } 1280 1281 U_CAPI int32_t U_EXPORT2 1282 ucase_toFullUpper(const UCaseProps *csp, UChar32 c, 1283 UCaseContextIterator *iter, void *context, 1284 const UChar **pString, 1285 const char *locale, int32_t *locCache) { 1286 return toUpperOrTitle(csp, c, iter, context, pString, locale, locCache, TRUE); 1287 } 1288 1289 U_CAPI int32_t U_EXPORT2 1290 ucase_toFullTitle(const UCaseProps *csp, UChar32 c, 1291 UCaseContextIterator *iter, void *context, 1292 const UChar **pString, 1293 const char *locale, int32_t *locCache) { 1294 return toUpperOrTitle(csp, c, iter, context, pString, locale, locCache, FALSE); 1295 } 1296 1297 /* case folding ------------------------------------------------------------- */ 1298 1299 /* 1300 * Case folding is similar to lowercasing. 1301 * The result may be a simple mapping, i.e., a single code point, or 1302 * a full mapping, i.e., a string. 1303 * If the case folding for a code point is the same as its simple (1:1) lowercase mapping, 1304 * then only the lowercase mapping is stored. 1305 * 1306 * Some special cases are hardcoded because their conditions cannot be 1307 * parsed and processed from CaseFolding.txt. 1308 * 1309 * Unicode 3.2 CaseFolding.txt specifies for its status field: 1310 1311 # C: common case folding, common mappings shared by both simple and full mappings. 1312 # F: full case folding, mappings that cause strings to grow in length. Multiple characters are separated by spaces. 1313 # S: simple case folding, mappings to single characters where different from F. 1314 # T: special case for uppercase I and dotted uppercase I 1315 # - For non-Turkic languages, this mapping is normally not used. 1316 # - For Turkic languages (tr, az), this mapping can be used instead of the normal mapping for these characters. 1317 # 1318 # Usage: 1319 # A. To do a simple case folding, use the mappings with status C + S. 1320 # B. To do a full case folding, use the mappings with status C + F. 1321 # 1322 # The mappings with status T can be used or omitted depending on the desired case-folding 1323 # behavior. (The default option is to exclude them.) 1324 1325 * Unicode 3.2 has 'T' mappings as follows: 1326 1327 0049; T; 0131; # LATIN CAPITAL LETTER I 1328 0130; T; 0069; # LATIN CAPITAL LETTER I WITH DOT ABOVE 1329 1330 * while the default mappings for these code points are: 1331 1332 0049; C; 0069; # LATIN CAPITAL LETTER I 1333 0130; F; 0069 0307; # LATIN CAPITAL LETTER I WITH DOT ABOVE 1334 1335 * U+0130 has no simple case folding (simple-case-folds to itself). 1336 */ 1337 1338 /* return the simple case folding mapping for c */ 1339 U_CAPI UChar32 U_EXPORT2 1340 ucase_fold(const UCaseProps *csp, UChar32 c, uint32_t options) { 1341 uint16_t props=UTRIE2_GET16(&csp->trie, c); 1342 if(!PROPS_HAS_EXCEPTION(props)) { 1343 if(UCASE_GET_TYPE(props)>=UCASE_UPPER) { 1344 c+=UCASE_GET_DELTA(props); 1345 } 1346 } else { 1347 const uint16_t *pe=GET_EXCEPTIONS(csp, props); 1348 uint16_t excWord=*pe++; 1349 int32_t idx; 1350 if(excWord&UCASE_EXC_CONDITIONAL_FOLD) { 1351 /* special case folding mappings, hardcoded */ 1352 if((options&_FOLD_CASE_OPTIONS_MASK)==U_FOLD_CASE_DEFAULT) { 1353 /* default mappings */ 1354 if(c==0x49) { 1355 /* 0049; C; 0069; # LATIN CAPITAL LETTER I */ 1356 return 0x69; 1357 } else if(c==0x130) { 1358 /* no simple case folding for U+0130 */ 1359 return c; 1360 } 1361 } else { 1362 /* Turkic mappings */ 1363 if(c==0x49) { 1364 /* 0049; T; 0131; # LATIN CAPITAL LETTER I */ 1365 return 0x131; 1366 } else if(c==0x130) { 1367 /* 0130; T; 0069; # LATIN CAPITAL LETTER I WITH DOT ABOVE */ 1368 return 0x69; 1369 } 1370 } 1371 } 1372 if(HAS_SLOT(excWord, UCASE_EXC_FOLD)) { 1373 idx=UCASE_EXC_FOLD; 1374 } else if(HAS_SLOT(excWord, UCASE_EXC_LOWER)) { 1375 idx=UCASE_EXC_LOWER; 1376 } else { 1377 return c; 1378 } 1379 GET_SLOT_VALUE(excWord, idx, pe, c); 1380 } 1381 return c; 1382 } 1383 1384 /* 1385 * Issue for canonical caseless match (UAX #21): 1386 * Turkic casefolding (using "T" mappings in CaseFolding.txt) does not preserve 1387 * canonical equivalence, unlike default-option casefolding. 1388 * For example, I-grave and I + grave fold to strings that are not canonically 1389 * equivalent. 1390 * For more details, see the comment in unorm_compare() in unorm.cpp 1391 * and the intermediate prototype changes for Jitterbug 2021. 1392 * (For example, revision 1.104 of uchar.c and 1.4 of CaseFolding.txt.) 1393 * 1394 * This did not get fixed because it appears that it is not possible to fix 1395 * it for uppercase and lowercase characters (I-grave vs. i-grave) 1396 * together in a way that they still fold to common result strings. 1397 */ 1398 1399 U_CAPI int32_t U_EXPORT2 1400 ucase_toFullFolding(const UCaseProps *csp, UChar32 c, 1401 const UChar **pString, 1402 uint32_t options) 1403 { 1404 UChar32 result=c; 1405 uint16_t props=UTRIE2_GET16(&csp->trie, c); 1406 if(!PROPS_HAS_EXCEPTION(props)) { 1407 if(UCASE_GET_TYPE(props)>=UCASE_UPPER) { 1408 result=c+UCASE_GET_DELTA(props); 1409 } 1410 } else { 1411 const uint16_t *pe=GET_EXCEPTIONS(csp, props), *pe2; 1412 uint16_t excWord=*pe++; 1413 int32_t full, idx; 1414 1415 pe2=pe; 1416 1417 if(excWord&UCASE_EXC_CONDITIONAL_FOLD) { 1418 /* use hardcoded conditions and mappings */ 1419 if((options&_FOLD_CASE_OPTIONS_MASK)==U_FOLD_CASE_DEFAULT) { 1420 /* default mappings */ 1421 if(c==0x49) { 1422 /* 0049; C; 0069; # LATIN CAPITAL LETTER I */ 1423 return 0x69; 1424 } else if(c==0x130) { 1425 /* 0130; F; 0069 0307; # LATIN CAPITAL LETTER I WITH DOT ABOVE */ 1426 *pString=iDot; 1427 return 2; 1428 } 1429 } else { 1430 /* Turkic mappings */ 1431 if(c==0x49) { 1432 /* 0049; T; 0131; # LATIN CAPITAL LETTER I */ 1433 return 0x131; 1434 } else if(c==0x130) { 1435 /* 0130; T; 0069; # LATIN CAPITAL LETTER I WITH DOT ABOVE */ 1436 return 0x69; 1437 } 1438 } 1439 } else if(HAS_SLOT(excWord, UCASE_EXC_FULL_MAPPINGS)) { 1440 GET_SLOT_VALUE(excWord, UCASE_EXC_FULL_MAPPINGS, pe, full); 1441 1442 /* start of full case mapping strings */ 1443 ++pe; 1444 1445 /* skip the lowercase result string */ 1446 pe+=full&UCASE_FULL_LOWER; 1447 full=(full>>4)&0xf; 1448 1449 if(full!=0) { 1450 /* set the output pointer to the result string */ 1451 *pString=pe; 1452 1453 /* return the string length */ 1454 return full; 1455 } 1456 } 1457 1458 if(HAS_SLOT(excWord, UCASE_EXC_FOLD)) { 1459 idx=UCASE_EXC_FOLD; 1460 } else if(HAS_SLOT(excWord, UCASE_EXC_LOWER)) { 1461 idx=UCASE_EXC_LOWER; 1462 } else { 1463 return ~c; 1464 } 1465 GET_SLOT_VALUE(excWord, idx, pe2, result); 1466 } 1467 1468 return (result==c) ? ~result : result; 1469 } 1470 1471 /* case mapping properties API ---------------------------------------------- */ 1472 1473 /* get the UCaseProps singleton, or else its dummy, once and for all */ 1474 #if !UCASE_HARDCODE_DATA 1475 static const UCaseProps * 1476 getCaseProps() { 1477 /* 1478 * This lazy intialization with double-checked locking (without mutex protection for 1479 * the initial check) is transiently unsafe under certain circumstances. 1480 * Check the readme and use u_init() if necessary. 1481 */ 1482 1483 /* the initial check is performed by the GET_CASE_PROPS() macro */ 1484 const UCaseProps *csp; 1485 UErrorCode errorCode=U_ZERO_ERROR; 1486 1487 csp=ucase_getSingleton(&errorCode); 1488 if(U_FAILURE(errorCode)) { 1489 errorCode=U_ZERO_ERROR; 1490 csp=ucase_getDummy(&errorCode); 1491 if(U_FAILURE(errorCode)) { 1492 return NULL; 1493 } 1494 } 1495 1496 return csp; 1497 } 1498 #endif 1499 1500 /* 1501 * In ICU 3.0, most Unicode properties were loaded from uprops.icu. 1502 * ICU 3.2 adds ucase.icu for case mapping properties. 1503 * ICU 3.4 adds ubidi.icu for bidi/shaping properties and 1504 * removes case/bidi/shaping properties from uprops.icu. 1505 * 1506 * Loading of uprops.icu was never mutex-protected and required u_init() 1507 * for thread safety. 1508 * In order to maintain performance for all such properties, 1509 * ucase.icu and ubidi.icu are loaded lazily, without mutexing. 1510 * u_init() will try to load them for thread safety, 1511 * but u_init() will not fail if they are missing. 1512 * 1513 * uchar.c maintains a tri-state flag for (not loaded/loaded/failed to load) 1514 * and an error code for load failure. 1515 * Instead, here we try to load at most once. 1516 * If it works, we use the resulting singleton object. 1517 * If it fails, then we get a dummy object, which always works unless 1518 * we are seriously out of memory. 1519 * After the first try, we have a never-changing pointer to either the 1520 * real singleton or the dummy. 1521 * 1522 * This method is used in Unicode properties APIs (uchar.h) that 1523 * do not have a service object and also do not have an error code parameter. 1524 * Other API implementations get the singleton themselves 1525 * (with mutexing), store it in the service object, and report errors. 1526 */ 1527 #if !UCASE_HARDCODE_DATA 1528 #define GET_CASE_PROPS() (gCsp!=NULL ? gCsp : getCaseProps()) 1529 #else 1530 #define GET_CASE_PROPS() &ucase_props_singleton 1531 #endif 1532 1533 /* public API (see uchar.h) */ 1534 1535 U_CAPI UBool U_EXPORT2 1536 u_isULowercase(UChar32 c) { 1537 return (UBool)(UCASE_LOWER==ucase_getType(GET_CASE_PROPS(), c)); 1538 } 1539 1540 U_CAPI UBool U_EXPORT2 1541 u_isUUppercase(UChar32 c) { 1542 return (UBool)(UCASE_UPPER==ucase_getType(GET_CASE_PROPS(), c)); 1543 } 1544 1545 /* Transforms the Unicode character to its lower case equivalent.*/ 1546 U_CAPI UChar32 U_EXPORT2 1547 u_tolower(UChar32 c) { 1548 return ucase_tolower(GET_CASE_PROPS(), c); 1549 } 1550 1551 /* Transforms the Unicode character to its upper case equivalent.*/ 1552 U_CAPI UChar32 U_EXPORT2 1553 u_toupper(UChar32 c) { 1554 return ucase_toupper(GET_CASE_PROPS(), c); 1555 } 1556 1557 /* Transforms the Unicode character to its title case equivalent.*/ 1558 U_CAPI UChar32 U_EXPORT2 1559 u_totitle(UChar32 c) { 1560 return ucase_totitle(GET_CASE_PROPS(), c); 1561 } 1562 1563 /* return the simple case folding mapping for c */ 1564 U_CAPI UChar32 U_EXPORT2 1565 u_foldCase(UChar32 c, uint32_t options) { 1566 return ucase_fold(GET_CASE_PROPS(), c, options); 1567 } 1568 1569 U_CFUNC int32_t U_EXPORT2 1570 ucase_hasBinaryProperty(UChar32 c, UProperty which) { 1571 /* case mapping properties */ 1572 const UCaseProps *csp=GET_CASE_PROPS(); 1573 if(csp==NULL) { 1574 return FALSE; 1575 } 1576 switch(which) { 1577 case UCHAR_LOWERCASE: 1578 return (UBool)(UCASE_LOWER==ucase_getType(csp, c)); 1579 case UCHAR_UPPERCASE: 1580 return (UBool)(UCASE_UPPER==ucase_getType(csp, c)); 1581 case UCHAR_SOFT_DOTTED: 1582 return ucase_isSoftDotted(csp, c); 1583 case UCHAR_CASE_SENSITIVE: 1584 return ucase_isCaseSensitive(csp, c); 1585 default: 1586 return FALSE; 1587 } 1588 } 1589