16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Copyright (C) 2001-2011, International Business Machines
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Corporation and others.  All Rights Reserved.
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   file name:  ustrcase.cpp
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   encoding:   US-ASCII
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   tab size:   8 (not used)
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   indentation:4
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created on: 2002feb20
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   created by: Markus W. Scherer
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Implementation file for string casing C API functions.
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Uses functions from uchar.c for basic functionality that requires access
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   to the Unicode Character Database (uprops.dat).
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h"
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/brkiter.h"
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ustring.h"
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ucasemap.h"
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ubrk.h"
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utf.h"
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utf16.h"
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h"
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ucase.h"
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ustr_imp.h"
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_USE
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* string casing ------------------------------------------------------------ */
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* Appends a full case mapping result, see UCASE_MAX_STRING_LENGTH. */
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic inline int32_t
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgappendResult(UChar *dest, int32_t destIndex, int32_t destCapacity,
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             int32_t result, const UChar *s) {
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 c;
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length;
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* decode the result */
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(result<0) {
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* (not) original code point */
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        c=~result;
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=-1;
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(result<=UCASE_MAX_STRING_LENGTH) {
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        c=U_SENTINEL;
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=result;
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        c=result;
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        length=-1;
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(destIndex<destCapacity) {
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* append the result */
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length<0) {
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* code point */
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UBool isError=FALSE;
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            U16_APPEND(dest, destIndex, destCapacity, c, isError);
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(isError) {
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* overflow, nothing written */
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                destIndex+=U16_LENGTH(c);
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* string */
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if((destIndex+length)<=destCapacity) {
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                while(length>0) {
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    dest[destIndex++]=*s++;
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    --length;
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* overflow */
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                destIndex+=length;
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* preflight */
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(length<0) {
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            destIndex+=U16_LENGTH(c);
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            destIndex+=length;
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return destIndex;
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UChar32 U_CALLCONV
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgutf16_caseContextIterator(void *context, int8_t dir) {
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UCaseContext *csc=(UCaseContext *)context;
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 c;
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(dir<0) {
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* reset for backward iteration */
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        csc->index=csc->cpStart;
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        csc->dir=dir;
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if(dir>0) {
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* reset for forward iteration */
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        csc->index=csc->cpLimit;
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        csc->dir=dir;
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* continue current iteration direction */
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        dir=csc->dir;
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(dir<0) {
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(csc->start<csc->index) {
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            U16_PREV((const UChar *)csc->p, csc->start, csc->index, c);
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return c;
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(csc->index<csc->limit) {
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            U16_NEXT((const UChar *)csc->p, csc->index, csc->limit, c);
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return c;
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return U_SENTINEL;
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Case-maps [srcStart..srcLimit[ but takes
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * context [0..srcLength[ into account.
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org_caseMap(const UCaseMap *csm, UCaseMapFull *map,
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         UChar *dest, int32_t destCapacity,
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         const UChar *src, UCaseContext *csc,
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         int32_t srcStart, int32_t srcLimit,
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         UErrorCode *pErrorCode) {
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *s;
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 c, c2 = 0;
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t srcIndex, destIndex;
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t locCache;
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    locCache=csm->locCache;
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* case mapping loop */
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    srcIndex=srcStart;
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    destIndex=0;
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(srcIndex<srcLimit) {
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        csc->cpStart=srcIndex;
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        U16_NEXT(src, srcIndex, srcLimit, c);
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        csc->cpLimit=srcIndex;
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        c=map(csm->csp, c, utf16_caseContextIterator, csc, &s, csm->locale, &locCache);
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((destIndex<destCapacity) && (c<0 ? (c2=~c)<=0xffff : UCASE_MAX_STRING_LENGTH<c && (c2=c)<=0xffff)) {
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* fast path version of appendResult() for BMP results */
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            dest[destIndex++]=(UChar)c2;
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            destIndex=appendResult(dest, destIndex, destCapacity, c, s);
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(destIndex>destCapacity) {
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return destIndex;
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if !UCONFIG_NO_BREAK_ITERATION
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC int32_t U_CALLCONV
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgustrcase_internalToTitle(const UCaseMap *csm,
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UChar *dest, int32_t destCapacity,
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         const UChar *src, int32_t srcLength,
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UErrorCode *pErrorCode) {
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *s;
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 c;
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t prev, titleStart, titleLimit, idx, destIndex, length;
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool isFirstIndex;
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(*pErrorCode)) {
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Use the C++ abstract base class to minimize dependencies.
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // TODO: Change UCaseMap.iter to store a BreakIterator directly.
1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    BreakIterator *bi=reinterpret_cast<BreakIterator *>(csm->iter);
1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* set up local variables */
1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t locCache=csm->locCache;
1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UCaseContext csc=UCASECONTEXT_INITIALIZER;
1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    csc.p=(void *)src;
1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    csc.limit=srcLength;
1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    destIndex=0;
1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    prev=0;
1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    isFirstIndex=TRUE;
1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* titlecasing loop */
1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(prev<srcLength) {
1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* find next index where to titlecase */
1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(isFirstIndex) {
1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            isFirstIndex=FALSE;
1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            idx=bi->first();
1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            idx=bi->next();
1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(idx==UBRK_DONE || idx>srcLength) {
2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            idx=srcLength;
2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * Unicode 4 & 5 section 3.13 Default Case Operations:
2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * R3  toTitlecase(X): Find the word boundaries based on Unicode Standard Annex
2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * #29, "Text Boundaries." Between each pair of word boundaries, find the first
2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * cased character F. If F exists, map F to default_title(F); then map each
2106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * subsequent character C to default_lower(C).
2116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
2126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * In this implementation, segment [prev..index[ into 3 parts:
2136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * a) uncased characters (copy as-is) [prev..titleStart[
2146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * b) first case letter (titlecase)         [titleStart..titleLimit[
2156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * c) subsequent characters (lowercase)                 [titleLimit..index[
2166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
2176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(prev<idx) {
2186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* find and copy uncased characters [prev..titleStart[ */
2196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            titleStart=titleLimit=prev;
2206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            U16_NEXT(src, titleLimit, idx, c);
2216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if((csm->options&U_TITLECASE_NO_BREAK_ADJUSTMENT)==0 && UCASE_NONE==ucase_getType(csm->csp, c)) {
2226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* Adjust the titlecasing index (titleStart) to the next cased character. */
2236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                for(;;) {
2246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    titleStart=titleLimit;
2256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(titleLimit==idx) {
2266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        /*
2276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         * only uncased characters in [prev..index[
2286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         * stop with titleStart==titleLimit==index
2296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         */
2306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        break;
2316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
2326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    U16_NEXT(src, titleLimit, idx, c);
2336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(UCASE_NONE!=ucase_getType(csm->csp, c)) {
2346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        break; /* cased letter at [titleStart..titleLimit[ */
2356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
2366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
2376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                length=titleStart-prev;
2386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(length>0) {
2396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if((destIndex+length)<=destCapacity) {
2406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        uprv_memcpy(dest+destIndex, src+prev, length*U_SIZEOF_UCHAR);
2416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
2426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    destIndex+=length;
2436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
2446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
2456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(titleStart<titleLimit) {
2476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* titlecase c which is from [titleStart..titleLimit[ */
2486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                csc.cpStart=titleStart;
2496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                csc.cpLimit=titleLimit;
2506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                c=ucase_toFullTitle(csm->csp, c, utf16_caseContextIterator, &csc, &s, csm->locale, &locCache);
2516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                destIndex=appendResult(dest, destIndex, destCapacity, c, s);
2526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* Special case Dutch IJ titlecasing */
2546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if ( titleStart+1 < idx &&
2556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     ucase_getCaseLocale(csm->locale,&locCache) == UCASE_LOC_DUTCH &&
2566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     ( src[titleStart] == (UChar32) 0x0049 || src[titleStart] == (UChar32) 0x0069 ) &&
2576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     ( src[titleStart+1] == (UChar32) 0x004A || src[titleStart+1] == (UChar32) 0x006A )) {
2586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            c=(UChar32) 0x004A;
2596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            destIndex=appendResult(dest, destIndex, destCapacity, c, s);
2606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            titleLimit++;
2616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
2626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* lowercase [titleLimit..index[ */
2646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(titleLimit<idx) {
2656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if((csm->options&U_TITLECASE_NO_LOWERCASE)==0) {
2666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        /* Normal operation: Lowercase the rest of the word. */
2676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        destIndex+=
2686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            _caseMap(
2696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                csm, ucase_toFullLower,
2706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                dest+destIndex, destCapacity-destIndex,
2716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                src, &csc,
2726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                titleLimit, idx,
2736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                pErrorCode);
2746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    } else {
2756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        /* Optionally just copy the rest of the word unchanged. */
2766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        length=idx-titleLimit;
2776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if((destIndex+length)<=destCapacity) {
2786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            uprv_memcpy(dest+destIndex, src+titleLimit, length*U_SIZEOF_UCHAR);
2796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
2806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        destIndex+=length;
2816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
2826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
2836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
2846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        prev=idx;
2876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(destIndex>destCapacity) {
2906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
2916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return destIndex;
2936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif  // !UCONFIG_NO_BREAK_ITERATION
2966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* functions available in the common library (for unistr_case.cpp) */
2986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC int32_t U_CALLCONV
3006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgustrcase_internalToLower(const UCaseMap *csm,
3016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UChar *dest, int32_t destCapacity,
3026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         const UChar *src, int32_t srcLength,
3036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UErrorCode *pErrorCode) {
3046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UCaseContext csc=UCASECONTEXT_INITIALIZER;
3056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    csc.p=(void *)src;
3066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    csc.limit=srcLength;
3076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return _caseMap(
3086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        csm, ucase_toFullLower,
3096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        dest, destCapacity,
3106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        src, &csc, 0, srcLength,
3116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pErrorCode);
3126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC int32_t U_CALLCONV
3156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgustrcase_internalToUpper(const UCaseMap *csm,
3166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UChar *dest, int32_t destCapacity,
3176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         const UChar *src, int32_t srcLength,
3186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UErrorCode *pErrorCode) {
3196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UCaseContext csc=UCASECONTEXT_INITIALIZER;
3206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    csc.p=(void *)src;
3216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    csc.limit=srcLength;
3226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return _caseMap(
3236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        csm, ucase_toFullUpper,
3246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        dest, destCapacity,
3256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        src, &csc, 0, srcLength,
3266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        pErrorCode);
3276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int32_t
3306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgustr_foldCase(const UCaseProps *csp,
3316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              UChar *dest, int32_t destCapacity,
3326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              const UChar *src, int32_t srcLength,
3336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              uint32_t options,
3346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              UErrorCode *pErrorCode) {
3356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t srcIndex, destIndex;
3366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *s;
3386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 c, c2 = 0;
3396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* case mapping loop */
3416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    srcIndex=destIndex=0;
3426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while(srcIndex<srcLength) {
3436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        U16_NEXT(src, srcIndex, srcLength, c);
3446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        c=ucase_toFullFolding(csp, c, &s, options);
3456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if((destIndex<destCapacity) && (c<0 ? (c2=~c)<=0xffff : UCASE_MAX_STRING_LENGTH<c && (c2=c)<=0xffff)) {
3466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* fast path version of appendResult() for BMP results */
3476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            dest[destIndex++]=(UChar)c2;
3486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
3496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            destIndex=appendResult(dest, destIndex, destCapacity, c, s);
3506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(destIndex>destCapacity) {
3546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
3556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return destIndex;
3576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC int32_t U_CALLCONV
3606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgustrcase_internalFold(const UCaseMap *csm,
3616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                      UChar *dest, int32_t destCapacity,
3626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                      const UChar *src, int32_t srcLength,
3636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                      UErrorCode *pErrorCode) {
3646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return ustr_foldCase(csm->csp, dest, destCapacity, src, srcLength, csm->options, pErrorCode);
3656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC int32_t
3686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgustrcase_map(const UCaseMap *csm,
3696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             UChar *dest, int32_t destCapacity,
3706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             const UChar *src, int32_t srcLength,
3716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             UStringCaseMapper *stringCaseMapper,
3726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             UErrorCode *pErrorCode) {
3736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar buffer[300];
3746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar *temp;
3756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t destLength;
3776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* check argument values */
3796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(*pErrorCode)) {
3806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
3816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if( destCapacity<0 ||
3836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        (dest==NULL && destCapacity>0) ||
3846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        src==NULL ||
3856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        srcLength<-1
3866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
3876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
3886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
3896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* get the string length */
3926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(srcLength==-1) {
3936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        srcLength=u_strlen(src);
3946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* check for overlapping source and destination */
3976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if( dest!=NULL &&
3986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ((src>=dest && src<(dest+destCapacity)) ||
3996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         (dest>=src && dest<(src+srcLength)))
4006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ) {
4016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* overlap: provide a temporary destination buffer and later copy the result */
4026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(destCapacity<=LENGTHOF(buffer)) {
4036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* the stack buffer is large enough */
4046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            temp=buffer;
4056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
4066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* allocate a buffer */
4076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            temp=(UChar *)uprv_malloc(destCapacity*U_SIZEOF_UCHAR);
4086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(temp==NULL) {
4096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
4106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;
4116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
4146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        temp=dest;
4156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    destLength=stringCaseMapper(csm, temp, destCapacity, src, srcLength, pErrorCode);
4186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(temp!=dest) {
4196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* copy the result string to the destination buffer */
4206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(destLength>0) {
4216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t copyLength= destLength<=destCapacity ? destLength : destCapacity;
4226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(copyLength>0) {
4236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                uprv_memmove(dest, temp, copyLength*U_SIZEOF_UCHAR);
4246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(temp!=buffer) {
4276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_free(temp);
4286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return u_terminateUChars(dest, destCapacity, destLength, pErrorCode);
4326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* public API functions */
4356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t U_EXPORT2
4376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_strFoldCase(UChar *dest, int32_t destCapacity,
4386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              const UChar *src, int32_t srcLength,
4396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              uint32_t options,
4406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              UErrorCode *pErrorCode) {
4416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UCaseMap csm=UCASEMAP_INITIALIZER;
4426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    csm.csp=ucase_getSingleton();
4436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    csm.options=options;
4446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return ustrcase_map(
4456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        &csm,
4466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        dest, destCapacity,
4476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        src, srcLength,
4486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ustrcase_internalFold, pErrorCode);
4496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* case-insensitive string comparisons -------------------------------------- */
4526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
4546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * This function is a copy of unorm_cmpEquivFold() minus the parts for
4556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * canonical equivalence.
4566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Keep the functions in sync, and see there for how this works.
4576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * The duplication is for modularization:
4586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * It makes caseless (but not canonical caseless) matches independent of
4596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * the normalization code.
4606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
4616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* stack element for previous-level source/decomposition pointers */
4636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstruct CmpEquivLevel {
4646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *start, *s, *limit;
4656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
4666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgtypedef struct CmpEquivLevel CmpEquivLevel;
4676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* internal function */
4696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC int32_t
4706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_strcmpFold(const UChar *s1, int32_t length1,
4716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             const UChar *s2, int32_t length2,
4726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             uint32_t options,
4736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org             UErrorCode *pErrorCode) {
4746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UCaseProps *csp;
4756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* current-level start/limit - s1/s2 as current */
4776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *start1, *start2, *limit1, *limit2;
4786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* case folding variables */
4806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar *p;
4816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length;
4826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* stacks of previous-level start/current/limit */
4846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    CmpEquivLevel stack1[2], stack2[2];
4856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* case folding buffers, only use current-level start/limit */
4876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar fold1[UCASE_MAX_STRING_LENGTH+1], fold2[UCASE_MAX_STRING_LENGTH+1];
4886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* track which is the current level per string */
4906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t level1, level2;
4916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* current code units, and code points for lookups */
4936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar32 c1, c2, cp1, cp2;
4946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* no argument error checking because this itself is not an API */
4966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
4986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * assume that at least the option U_COMPARE_IGNORE_CASE is set
4996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     * otherwise this function would have to behave exactly as uprv_strCompare()
5006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org     */
5016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    csp=ucase_getSingleton();
5026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(U_FAILURE(*pErrorCode)) {
5036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
5046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* initialize */
5076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    start1=s1;
5086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(length1==-1) {
5096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        limit1=NULL;
5106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
5116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        limit1=s1+length1;
5126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    start2=s2;
5156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(length2==-1) {
5166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        limit2=NULL;
5176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
5186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        limit2=s2+length2;
5196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    level1=level2=0;
5226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    c1=c2=-1;
5236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* comparison loop */
5256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for(;;) {
5266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
5276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * here a code unit value of -1 means "get another code unit"
5286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * below it will mean "this source is finished"
5296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
5306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(c1<0) {
5326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* get next code unit from string 1, post-increment */
5336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            for(;;) {
5346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(s1==limit1 || ((c1=*s1)==0 && (limit1==NULL || (options&_STRNCMP_STYLE)))) {
5356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(level1==0) {
5366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        c1=-1;
5376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        break;
5386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
5396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
5406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ++s1;
5416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
5426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
5436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* reached end of level buffer, pop one level */
5456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                do {
5466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    --level1;
5476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    start1=stack1[level1].start;    /*Not uninitialized*/
5486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } while(start1==NULL);
5496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                s1=stack1[level1].s;                /*Not uninitialized*/
5506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                limit1=stack1[level1].limit;        /*Not uninitialized*/
5516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(c2<0) {
5556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* get next code unit from string 2, post-increment */
5566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            for(;;) {
5576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(s2==limit2 || ((c2=*s2)==0 && (limit2==NULL || (options&_STRNCMP_STYLE)))) {
5586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if(level2==0) {
5596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        c2=-1;
5606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        break;
5616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
5626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
5636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ++s2;
5646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
5656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
5666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* reached end of level buffer, pop one level */
5686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                do {
5696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    --level2;
5706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    start2=stack2[level2].start;    /*Not uninitialized*/
5716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } while(start2==NULL);
5726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                s2=stack2[level2].s;                /*Not uninitialized*/
5736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                limit2=stack2[level2].limit;        /*Not uninitialized*/
5746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
5786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * compare c1 and c2
5796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * either variable c1, c2 is -1 only if the corresponding string is finished
5806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
5816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(c1==c2) {
5826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(c1<0) {
5836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return 0;   /* c1==c2==-1 indicating end of strings */
5846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            c1=c2=-1;       /* make us fetch new code units */
5866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            continue;
5876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(c1<0) {
5886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return -1;      /* string 1 ends before string 2 */
5896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if(c2<0) {
5906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return 1;       /* string 2 ends before string 1 */
5916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* c1!=c2 && c1>=0 && c2>=0 */
5936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /* get complete code points for c1, c2 for lookups if either is a surrogate */
5956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cp1=c1;
5966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_IS_SURROGATE(c1)) {
5976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UChar c;
5986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(U_IS_SURROGATE_LEAD(c1)) {
6006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(s1!=limit1 && U16_IS_TRAIL(c=*s1)) {
6016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* advance ++s1; only below if cp1 decomposes/case-folds */
6026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    cp1=U16_GET_SUPPLEMENTARY(c1, c);
6036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
6046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else /* isTrail(c1) */ {
6056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(start1<=(s1-2) && U16_IS_LEAD(c=*(s1-2))) {
6066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    cp1=U16_GET_SUPPLEMENTARY(c, c1);
6076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
6086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cp2=c2;
6126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(U_IS_SURROGATE(c2)) {
6136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UChar c;
6146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(U_IS_SURROGATE_LEAD(c2)) {
6166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(s2!=limit2 && U16_IS_TRAIL(c=*s2)) {
6176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* advance ++s2; only below if cp2 decomposes/case-folds */
6186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    cp2=U16_GET_SUPPLEMENTARY(c2, c);
6196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
6206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else /* isTrail(c2) */ {
6216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(start2<=(s2-2) && U16_IS_LEAD(c=*(s2-2))) {
6226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    cp2=U16_GET_SUPPLEMENTARY(c, c2);
6236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
6246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
6286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * go down one level for each string
6296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * continue with the main loop as soon as there is a real change
6306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
6316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if( level1==0 &&
6336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            (length=ucase_toFullFolding(csp, (UChar32)cp1, &p, options))>=0
6346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ) {
6356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* cp1 case-folds to the code point "length" or to p[length] */
6366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(U_IS_SURROGATE(c1)) {
6376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(U_IS_SURROGATE_LEAD(c1)) {
6386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* advance beyond source surrogate pair if it case-folds */
6396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ++s1;
6406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else /* isTrail(c1) */ {
6416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /*
6426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * we got a supplementary code point when hitting its trail surrogate,
6436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * therefore the lead surrogate must have been the same as in the other string;
6446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * compare this decomposition with the lead surrogate in the other string
6456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * remember that this simulates bulk text replacement:
6466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * the decomposition would replace the entire code point
6476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     */
6486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    --s2;
6496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    c2=*(s2-1);
6506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
6516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* push current level pointers */
6546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            stack1[0].start=start1;
6556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            stack1[0].s=s1;
6566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            stack1[0].limit=limit1;
6576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++level1;
6586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* copy the folding result to fold1[] */
6606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(length<=UCASE_MAX_STRING_LENGTH) {
6616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                u_memcpy(fold1, p, length);
6626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
6636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                int32_t i=0;
6646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                U16_APPEND_UNSAFE(fold1, i, length);
6656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                length=i;
6666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* set next level pointers to case folding */
6696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start1=s1=fold1;
6706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            limit1=fold1+length;
6716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* get ready to read from decomposition, continue with loop */
6736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            c1=-1;
6746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            continue;
6756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
6766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if( level2==0 &&
6786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            (length=ucase_toFullFolding(csp, (UChar32)cp2, &p, options))>=0
6796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ) {
6806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* cp2 case-folds to the code point "length" or to p[length] */
6816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(U_IS_SURROGATE(c2)) {
6826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if(U_IS_SURROGATE_LEAD(c2)) {
6836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /* advance beyond source surrogate pair if it case-folds */
6846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ++s2;
6856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else /* isTrail(c2) */ {
6866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    /*
6876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * we got a supplementary code point when hitting its trail surrogate,
6886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * therefore the lead surrogate must have been the same as in the other string;
6896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * compare this decomposition with the lead surrogate in the other string
6906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * remember that this simulates bulk text replacement:
6916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     * the decomposition would replace the entire code point
6926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     */
6936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    --s1;
6946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    c1=*(s1-1);
6956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
6966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
6976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* push current level pointers */
6996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            stack2[0].start=start2;
7006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            stack2[0].s=s2;
7016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            stack2[0].limit=limit2;
7026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++level2;
7036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* copy the folding result to fold2[] */
7056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(length<=UCASE_MAX_STRING_LENGTH) {
7066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                u_memcpy(fold2, p, length);
7076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
7086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                int32_t i=0;
7096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                U16_APPEND_UNSAFE(fold2, i, length);
7106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                length=i;
7116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
7126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* set next level pointers to case folding */
7146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start2=s2=fold2;
7156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            limit2=fold2+length;
7166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* get ready to read from decomposition, continue with loop */
7186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            c2=-1;
7196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            continue;
7206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        /*
7236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * no decomposition/case folding, max level for both sides:
7246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * return difference result
7256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
7266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * code point order comparison must not just return cp1-cp2
7276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * because when single surrogates are present then the surrogate pairs
7286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * that formed cp1 and cp2 may be from different string indexes
7296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
7306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * example: { d800 d800 dc01 } vs. { d800 dc00 }, compare at second code units
7316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * c1=d800 cp1=10001 c2=dc00 cp2=10000
7326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * cp1-cp2>0 but c1-c2<0 and in fact in UTF-32 it is { d800 10001 } < { 10000 }
7336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         *
7346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * therefore, use same fix-up as in ustring.c/uprv_strCompare()
7356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * except: uprv_strCompare() fetches c=*s while this functions fetches c=*s++
7366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         * so we have slightly different pointer/start/limit comparisons here
7376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org         */
7386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if(c1>=0xd800 && c2>=0xd800 && (options&U_COMPARE_CODE_POINT_ORDER)) {
7406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* subtract 0x2800 from BMP code points to make them smaller than supplementary ones */
7416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(
7426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                (c1<=0xdbff && s1!=limit1 && U16_IS_TRAIL(*s1)) ||
7436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                (U16_IS_TRAIL(c1) && start1!=(s1-1) && U16_IS_LEAD(*(s1-2)))
7446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ) {
7456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* part of a surrogate pair, leave >=d800 */
7466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
7476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* BMP code point - may be surrogate code point - make <d800 */
7486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                c1-=0x2800;
7496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
7506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if(
7526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                (c2<=0xdbff && s2!=limit2 && U16_IS_TRAIL(*s2)) ||
7536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                (U16_IS_TRAIL(c2) && start2!=(s2-1) && U16_IS_LEAD(*(s2-2)))
7546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ) {
7556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* part of a surrogate pair, leave >=d800 */
7566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
7576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                /* BMP code point - may be surrogate code point - make <d800 */
7586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                c2-=0x2800;
7596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
7606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return c1-c2;
7636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* public API functions */
7676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t U_EXPORT2
7696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_strCaseCompare(const UChar *s1, int32_t length1,
7706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 const UChar *s2, int32_t length2,
7716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 uint32_t options,
7726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 UErrorCode *pErrorCode) {
7736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* argument checking */
7746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(pErrorCode==0 || U_FAILURE(*pErrorCode)) {
7756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
7766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(s1==NULL || length1<-1 || s2==NULL || length2<-1) {
7786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
7796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
7806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return u_strcmpFold(s1, length1, s2, length2,
7826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        options|U_COMPARE_IGNORE_CASE,
7836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        pErrorCode);
7846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t U_EXPORT2
7876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_strcasecmp(const UChar *s1, const UChar *s2, uint32_t options) {
7886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode errorCode=U_ZERO_ERROR;
7896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return u_strcmpFold(s1, -1, s2, -1,
7906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        options|U_COMPARE_IGNORE_CASE,
7916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        &errorCode);
7926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t U_EXPORT2
7956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_memcasecmp(const UChar *s1, const UChar *s2, int32_t length, uint32_t options) {
7966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode errorCode=U_ZERO_ERROR;
7976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return u_strcmpFold(s1, length, s2, length,
7986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        options|U_COMPARE_IGNORE_CASE,
7996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        &errorCode);
8006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
8016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI int32_t U_EXPORT2
8036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_strncasecmp(const UChar *s1, const UChar *s2, int32_t n, uint32_t options) {
8046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode errorCode=U_ZERO_ERROR;
8056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return u_strcmpFold(s1, n, s2, n,
8066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        options|(U_COMPARE_IGNORE_CASE|_STRNCMP_STYLE),
8076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        &errorCode);
8086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
809