Home | History | Annotate | Download | only in common
      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