1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*******************************************************************************
3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*
4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   Copyright (C) 2001-2010, International Business Machines
5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   Corporation and others.  All Rights Reserved.
6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*
7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*******************************************************************************
8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   file name:  ustrcase.c
9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   encoding:   US-ASCII
10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   tab size:   8 (not used)
11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   indentation:4
12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*
13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   created on: 2002feb20
14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   created by: Markus W. Scherer
15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*
16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   Implementation file for string casing C API functions.
17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   Uses functions from uchar.c for basic functionality that requires access
18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   to the Unicode Character Database (uprops.dat).
19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*/
20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/utypes.h"
22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/uloc.h"
23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/ustring.h"
24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/ucasemap.h"
25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/ubrk.h"
26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "cmemory.h"
27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "ucase.h"
28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "ustr_imp.h"
29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* string casing ------------------------------------------------------------ */
31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* append a full case mapping result, see UCASE_MAX_STRING_LENGTH */
33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static U_INLINE int32_t
34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)appendResult(UChar *dest, int32_t destIndex, int32_t destCapacity,
35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             int32_t result, const UChar *s) {
36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar32 c;
37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t length;
38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* decode the result */
40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(result<0) {
41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* (not) original code point */
42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        c=~result;
43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        length=-1;
44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else if(result<=UCASE_MAX_STRING_LENGTH) {
45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        c=U_SENTINEL;
46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        length=result;
47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        c=result;
49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        length=-1;
50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(destIndex<destCapacity) {
53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* append the result */
54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(length<0) {
55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* code point */
56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            UBool isError=FALSE;
57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            U16_APPEND(dest, destIndex, destCapacity, c, isError);
58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(isError) {
59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* overflow, nothing written */
60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                destIndex+=U16_LENGTH(c);
61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else {
63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* string */
64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if((destIndex+length)<=destCapacity) {
65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                while(length>0) {
66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    dest[destIndex++]=*s++;
67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    --length;
68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            } else {
70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* overflow */
71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                destIndex+=length;
72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* preflight */
76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(length<0) {
77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            destIndex+=U16_LENGTH(c);
78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else {
79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            destIndex+=length;
80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return destIndex;
83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static UChar32 U_CALLCONV
86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)utf16_caseContextIterator(void *context, int8_t dir) {
87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UCaseContext *csc=(UCaseContext *)context;
88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar32 c;
89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(dir<0) {
91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* reset for backward iteration */
92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        csc->index=csc->cpStart;
93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        csc->dir=dir;
94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else if(dir>0) {
95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* reset for forward iteration */
96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        csc->index=csc->cpLimit;
97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        csc->dir=dir;
98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* continue current iteration direction */
100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        dir=csc->dir;
101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(dir<0) {
104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(csc->start<csc->index) {
105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            U16_PREV((const UChar *)csc->p, csc->start, csc->index, c);
106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return c;
107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(csc->index<csc->limit) {
110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            U16_NEXT((const UChar *)csc->p, csc->index, csc->limit, c);
111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return c;
112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return U_SENTINEL;
115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Case-maps [srcStart..srcLimit[ but takes
119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * context [0..srcLength[ into account.
120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)_caseMap(const UCaseMap *csm, UCaseMapFull *map,
123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         UChar *dest, int32_t destCapacity,
124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         const UChar *src, UCaseContext *csc,
125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         int32_t srcStart, int32_t srcLimit,
126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         UErrorCode *pErrorCode) {
127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *s;
128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar32 c, c2 = 0;
129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t srcIndex, destIndex;
130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t locCache;
131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    locCache=csm->locCache;
133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* case mapping loop */
135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    srcIndex=srcStart;
136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    destIndex=0;
137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while(srcIndex<srcLimit) {
138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        csc->cpStart=srcIndex;
139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        U16_NEXT(src, srcIndex, srcLimit, c);
140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        csc->cpLimit=srcIndex;
141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        c=map(csm->csp, c, utf16_caseContextIterator, csc, &s, csm->locale, &locCache);
142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if((destIndex<destCapacity) && (c<0 ? (c2=~c)<=0xffff : UCASE_MAX_STRING_LENGTH<c && (c2=c)<=0xffff)) {
143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* fast path version of appendResult() for BMP results */
144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            dest[destIndex++]=(UChar)c2;
145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else {
146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            destIndex=appendResult(dest, destIndex, destCapacity, c, s);
147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(destIndex>destCapacity) {
151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return destIndex;
154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void
157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)setTempCaseMapLocale(UCaseMap *csm, const char *locale, UErrorCode *pErrorCode) {
158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /*
159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     * We could call ucasemap_setLocale(), but here we really only care about
160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     * the initial language subtag, we need not return the real string via
161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     * ucasemap_getLocale(), and we don't care about only getting "x" from
162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     * "x-some-thing" etc.
163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     *
164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     * We ignore locales with a longer-than-3 initial subtag.
165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     *
166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     * We also do not fill in the locCache because it is rarely used,
167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     * and not worth setting unless we reuse it for many case mapping operations.
168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     * (That's why UCaseMap was created.)
169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     */
170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int i;
171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    char c;
172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* the internal functions require locale!=NULL */
174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(locale==NULL) {
175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        locale=uloc_getDefault();
176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for(i=0; i<4 && (c=locale[i])!=0 && c!='-' && c!='_'; ++i) {
178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        csm->locale[i]=c;
179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(i<=3) {
181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        csm->locale[i]=0;  /* Up to 3 non-separator characters. */
182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        csm->locale[0]=0;  /* Longer-than-3 initial subtag: Ignore. */
184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Set parameters on an empty UCaseMap, for UCaseMap-less API functions.
189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Do this fast because it is called with every function call.
190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static U_INLINE void
192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)setTempCaseMap(UCaseMap *csm, const char *locale, UErrorCode *pErrorCode) {
193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(csm->csp==NULL) {
194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        csm->csp=ucase_getSingleton();
195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(locale!=NULL && locale[0]==0) {
197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        csm->locale[0]=0;
198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        setTempCaseMapLocale(csm, locale, pErrorCode);
200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#if !UCONFIG_NO_BREAK_ITERATION
204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Internal titlecasing function.
207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)_toTitle(UCaseMap *csm,
210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         UChar *dest, int32_t destCapacity,
211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         const UChar *src, UCaseContext *csc,
212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         int32_t srcLength,
213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         UErrorCode *pErrorCode) {
214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *s;
215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar32 c;
216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t prev, titleStart, titleLimit, idx, destIndex, length;
217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool isFirstIndex;
218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(csm->iter!=NULL) {
220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ubrk_setText(csm->iter, src, srcLength, pErrorCode);
221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        csm->iter=ubrk_open(UBRK_WORD, csm->locale,
223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            src, srcLength,
224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            pErrorCode);
225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(U_FAILURE(*pErrorCode)) {
227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set up local variables */
231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    destIndex=0;
232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    prev=0;
233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    isFirstIndex=TRUE;
234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* titlecasing loop */
236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while(prev<srcLength) {
237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* find next index where to titlecase */
238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(isFirstIndex) {
239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            isFirstIndex=FALSE;
240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            idx=ubrk_first(csm->iter);
241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else {
242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            idx=ubrk_next(csm->iter);
243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(idx==UBRK_DONE || idx>srcLength) {
245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            idx=srcLength;
246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /*
249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * Unicode 4 & 5 section 3.13 Default Case Operations:
250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         *
251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * R3  toTitlecase(X): Find the word boundaries based on Unicode Standard Annex
252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * #29, "Text Boundaries." Between each pair of word boundaries, find the first
253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * cased character F. If F exists, map F to default_title(F); then map each
254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * subsequent character C to default_lower(C).
255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         *
256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * In this implementation, segment [prev..index[ into 3 parts:
257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * a) uncased characters (copy as-is) [prev..titleStart[
258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * b) first case letter (titlecase)         [titleStart..titleLimit[
259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * c) subsequent characters (lowercase)                 [titleLimit..index[
260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         */
261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(prev<idx) {
262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* find and copy uncased characters [prev..titleStart[ */
263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            titleStart=titleLimit=prev;
264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            U16_NEXT(src, titleLimit, idx, c);
265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if((csm->options&U_TITLECASE_NO_BREAK_ADJUSTMENT)==0 && UCASE_NONE==ucase_getType(csm->csp, c)) {
266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* Adjust the titlecasing index (titleStart) to the next cased character. */
267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                for(;;) {
268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    titleStart=titleLimit;
269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if(titleLimit==idx) {
270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        /*
271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         * only uncased characters in [prev..index[
272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         * stop with titleStart==titleLimit==index
273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         */
274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        break;
275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    U16_NEXT(src, titleLimit, idx, c);
277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if(UCASE_NONE!=ucase_getType(csm->csp, c)) {
278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        break; /* cased letter at [titleStart..titleLimit[ */
279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                length=titleStart-prev;
282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if(length>0) {
283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if((destIndex+length)<=destCapacity) {
284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        uprv_memcpy(dest+destIndex, src+prev, length*U_SIZEOF_UCHAR);
285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    destIndex+=length;
287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(titleStart<titleLimit) {
291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* titlecase c which is from [titleStart..titleLimit[ */
292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                csc->cpStart=titleStart;
293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                csc->cpLimit=titleLimit;
294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                c=ucase_toFullTitle(csm->csp, c, utf16_caseContextIterator, csc, &s, csm->locale, &csm->locCache);
295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                destIndex=appendResult(dest, destIndex, destCapacity, c, s);
296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* Special case Dutch IJ titlecasing */
298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if ( titleStart+1 < idx &&
299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     ucase_getCaseLocale(csm->locale,&csm->locCache) == UCASE_LOC_DUTCH &&
300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     ( src[titleStart] == (UChar32) 0x0049 || src[titleStart] == (UChar32) 0x0069 ) &&
301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     ( src[titleStart+1] == (UChar32) 0x004A || src[titleStart+1] == (UChar32) 0x006A )) {
302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            c=(UChar32) 0x004A;
303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            destIndex=appendResult(dest, destIndex, destCapacity, c, s);
304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            titleLimit++;
305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* lowercase [titleLimit..index[ */
308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if(titleLimit<idx) {
309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if((csm->options&U_TITLECASE_NO_LOWERCASE)==0) {
310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        /* Normal operation: Lowercase the rest of the word. */
311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        destIndex+=
312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            _caseMap(
313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                csm, ucase_toFullLower,
314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                dest+destIndex, destCapacity-destIndex,
315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                src, csc,
316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                titleLimit, idx,
317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                pErrorCode);
318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    } else {
319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        /* Optionally just copy the rest of the word unchanged. */
320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        length=idx-titleLimit;
321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        if((destIndex+length)<=destCapacity) {
322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            uprv_memcpy(dest+destIndex, src+titleLimit, length*U_SIZEOF_UCHAR);
323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        }
324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        destIndex+=length;
325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        prev=idx;
331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(destIndex>destCapacity) {
334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return destIndex;
337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif
340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* functions available in the common library (for unistr_case.cpp) */
342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CFUNC int32_t
344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ustr_toLower(const UCaseProps *csp,
345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             UChar *dest, int32_t destCapacity,
346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             const UChar *src, int32_t srcLength,
347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             const char *locale,
348f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             UErrorCode *pErrorCode) {
349f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UCaseMap csm={ NULL };
350f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UCaseContext csc={ NULL };
351f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
352f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csm.csp=csp;
353f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    setTempCaseMap(&csm, locale, pErrorCode);
354f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csc.p=(void *)src;
355f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csc.limit=srcLength;
356f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
357f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return _caseMap(&csm, ucase_toFullLower,
358f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    dest, destCapacity,
359f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    src, &csc, 0, srcLength,
360f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    pErrorCode);
361f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
362f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
363f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CFUNC int32_t
364f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ustr_toUpper(const UCaseProps *csp,
365f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             UChar *dest, int32_t destCapacity,
366f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             const UChar *src, int32_t srcLength,
367f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             const char *locale,
368f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             UErrorCode *pErrorCode) {
369f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UCaseMap csm={ NULL };
370f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UCaseContext csc={ NULL };
371f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
372f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csm.csp=csp;
373f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    setTempCaseMap(&csm, locale, pErrorCode);
374f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csc.p=(void *)src;
375f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csc.limit=srcLength;
376f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
377f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return _caseMap(&csm, ucase_toFullUpper,
378f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    dest, destCapacity,
379f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    src, &csc, 0, srcLength,
380f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    pErrorCode);
381f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
382f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
383f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#if !UCONFIG_NO_BREAK_ITERATION
384f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
385f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CFUNC int32_t
386f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ustr_toTitle(const UCaseProps *csp,
387f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             UChar *dest, int32_t destCapacity,
388f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             const UChar *src, int32_t srcLength,
389f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             UBreakIterator *titleIter,
390f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             const char *locale, uint32_t options,
391f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             UErrorCode *pErrorCode) {
392f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UCaseMap csm={ NULL };
393f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UCaseContext csc={ NULL };
394f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t length;
395f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
396f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csm.csp=csp;
397f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csm.iter=titleIter;
398f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csm.options=options;
399f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    setTempCaseMap(&csm, locale, pErrorCode);
400f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csc.p=(void *)src;
401f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csc.limit=srcLength;
402f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
403f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    length=_toTitle(&csm,
404f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    dest, destCapacity,
405f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    src, &csc, srcLength,
406f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    pErrorCode);
407f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(titleIter==NULL && csm.iter!=NULL) {
408f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ubrk_close(csm.iter);
409f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
410f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return length;
411f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
412f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
413f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif
414f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
415f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CFUNC int32_t
416f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ustr_foldCase(const UCaseProps *csp,
417f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              UChar *dest, int32_t destCapacity,
418f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              const UChar *src, int32_t srcLength,
419f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              uint32_t options,
420f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              UErrorCode *pErrorCode) {
421f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t srcIndex, destIndex;
422f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
423f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *s;
424f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar32 c, c2 = 0;
425f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
426f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* case mapping loop */
427f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    srcIndex=destIndex=0;
428f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while(srcIndex<srcLength) {
429f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        U16_NEXT(src, srcIndex, srcLength, c);
430f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        c=ucase_toFullFolding(csp, c, &s, options);
431f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if((destIndex<destCapacity) && (c<0 ? (c2=~c)<=0xffff : UCASE_MAX_STRING_LENGTH<c && (c2=c)<=0xffff)) {
432f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* fast path version of appendResult() for BMP results */
433f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            dest[destIndex++]=(UChar)c2;
434f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else {
435f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            destIndex=appendResult(dest, destIndex, destCapacity, c, s);
436f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
437f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
438f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
439f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(destIndex>destCapacity) {
440f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *pErrorCode=U_BUFFER_OVERFLOW_ERROR;
441f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
442f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return destIndex;
443f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
444f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
445f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
446f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Implement argument checking and buffer handling
447f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * for string case mapping as a common function.
448f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
449f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
450f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* common internal function for public API functions */
451f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
452f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
453f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)caseMap(const UCaseMap *csm,
454f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UChar *dest, int32_t destCapacity,
455f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        const UChar *src, int32_t srcLength,
456f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        int32_t toWhichCase,
457f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UErrorCode *pErrorCode) {
458f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar buffer[300];
459f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar *temp;
460f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
461f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t destLength;
462f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
463f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* check argument values */
464f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) {
465f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
466f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
467f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if( destCapacity<0 ||
468f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        (dest==NULL && destCapacity>0) ||
469f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        src==NULL ||
470f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        srcLength<-1
471f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ) {
472f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
473f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
474f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
475f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
476f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* get the string length */
477f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(srcLength==-1) {
478f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        srcLength=u_strlen(src);
479f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
480f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
481f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* check for overlapping source and destination */
482f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if( dest!=NULL &&
483f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ((src>=dest && src<(dest+destCapacity)) ||
484f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         (dest>=src && dest<(src+srcLength)))
485f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ) {
486f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* overlap: provide a temporary destination buffer and later copy the result */
487f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(destCapacity<=(sizeof(buffer)/U_SIZEOF_UCHAR)) {
488f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* the stack buffer is large enough */
489f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            temp=buffer;
490f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else {
491f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* allocate a buffer */
492f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            temp=(UChar *)uprv_malloc(destCapacity*U_SIZEOF_UCHAR);
493f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(temp==NULL) {
494f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
495f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                return 0;
496f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
497f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
498f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
499f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        temp=dest;
500f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
501f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
502f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    destLength=0;
503f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
504f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(toWhichCase==FOLD_CASE) {
505f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        destLength=ustr_foldCase(csm->csp, temp, destCapacity, src, srcLength,
506f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                 csm->options, pErrorCode);
507f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
508f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UCaseContext csc={ NULL };
509f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
510f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        csc.p=(void *)src;
511f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        csc.limit=srcLength;
512f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
513f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(toWhichCase==TO_LOWER) {
514f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            destLength=_caseMap(csm, ucase_toFullLower,
515f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                temp, destCapacity,
516f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                src, &csc,
517f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                0, srcLength,
518f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                pErrorCode);
519f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else if(toWhichCase==TO_UPPER) {
520f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            destLength=_caseMap(csm, ucase_toFullUpper,
521f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                temp, destCapacity,
522f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                src, &csc,
523f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                0, srcLength,
524f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                pErrorCode);
525f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else /* if(toWhichCase==TO_TITLE) */ {
526f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#if UCONFIG_NO_BREAK_ITERATION
527f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *pErrorCode=U_UNSUPPORTED_ERROR;
528f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#else
529f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* UCaseMap is actually non-const in toTitle() APIs. */
530f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            destLength=_toTitle((UCaseMap *)csm, temp, destCapacity,
531f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                src, &csc, srcLength,
532f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                pErrorCode);
533f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif
534f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
535f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
536f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(temp!=dest) {
537f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* copy the result string to the destination buffer */
538f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(destLength>0) {
539f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            int32_t copyLength= destLength<=destCapacity ? destLength : destCapacity;
540f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(copyLength>0) {
541f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                uprv_memmove(dest, temp, copyLength*U_SIZEOF_UCHAR);
542f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
543f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
544f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(temp!=buffer) {
545f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uprv_free(temp);
546f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
547f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
548f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
549f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return u_terminateUChars(dest, destCapacity, destLength, pErrorCode);
550f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
551f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
552f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* public API functions */
553f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
554f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2
555f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_strToLower(UChar *dest, int32_t destCapacity,
556f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             const UChar *src, int32_t srcLength,
557f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             const char *locale,
558f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             UErrorCode *pErrorCode) {
559f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UCaseMap csm={ NULL };
560f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    setTempCaseMap(&csm, locale, pErrorCode);
561f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return caseMap(&csm,
562f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   dest, destCapacity,
563f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   src, srcLength,
564f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   TO_LOWER, pErrorCode);
565f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
566f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
567f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2
568f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_strToUpper(UChar *dest, int32_t destCapacity,
569f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             const UChar *src, int32_t srcLength,
570f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             const char *locale,
571f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             UErrorCode *pErrorCode) {
572f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UCaseMap csm={ NULL };
573f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    setTempCaseMap(&csm, locale, pErrorCode);
574f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return caseMap(&csm,
575f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   dest, destCapacity,
576f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   src, srcLength,
577f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   TO_UPPER, pErrorCode);
578f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
579f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
580f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#if !UCONFIG_NO_BREAK_ITERATION
581f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
582f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2
583f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_strToTitle(UChar *dest, int32_t destCapacity,
584f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             const UChar *src, int32_t srcLength,
585f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             UBreakIterator *titleIter,
586f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             const char *locale,
587f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             UErrorCode *pErrorCode) {
588f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UCaseMap csm={ NULL };
589f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t length;
590f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
591f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csm.iter=titleIter;
592f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    setTempCaseMap(&csm, locale, pErrorCode);
593f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    length=caseMap(&csm,
594f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   dest, destCapacity,
595f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   src, srcLength,
596f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   TO_TITLE, pErrorCode);
597f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(titleIter==NULL && csm.iter!=NULL) {
598f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ubrk_close(csm.iter);
599f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
600f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return length;
601f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
602f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
603f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2
604f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)ucasemap_toTitle(UCaseMap *csm,
605f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 UChar *dest, int32_t destCapacity,
606f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 const UChar *src, int32_t srcLength,
607f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 UErrorCode *pErrorCode) {
608f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return caseMap(csm,
609f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   dest, destCapacity,
610f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   src, srcLength,
611f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   TO_TITLE, pErrorCode);
612f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
613f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
614f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif
615f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
616f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2
617f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_strFoldCase(UChar *dest, int32_t destCapacity,
618f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              const UChar *src, int32_t srcLength,
619f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              uint32_t options,
620f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)              UErrorCode *pErrorCode) {
621f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UCaseMap csm={ NULL };
622f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csm.csp=ucase_getSingleton();
623f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csm.options=options;
624f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return caseMap(&csm,
625f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   dest, destCapacity,
626f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   src, srcLength,
627f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   FOLD_CASE, pErrorCode);
628f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
629f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
630f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* case-insensitive string comparisons -------------------------------------- */
631f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
632f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
633f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * This function is a copy of unorm_cmpEquivFold() minus the parts for
634f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * canonical equivalence.
635f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Keep the functions in sync, and see there for how this works.
636f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * The duplication is for modularization:
637f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * It makes caseless (but not canonical caseless) matches independent of
638f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * the normalization code.
639f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
640f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
641f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* stack element for previous-level source/decomposition pointers */
642f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)struct CmpEquivLevel {
643f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *start, *s, *limit;
644f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)};
645f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)typedef struct CmpEquivLevel CmpEquivLevel;
646f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
647f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* internal function */
648f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CFUNC int32_t
649f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_strcmpFold(const UChar *s1, int32_t length1,
650f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             const UChar *s2, int32_t length2,
651f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             uint32_t options,
652f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)             UErrorCode *pErrorCode) {
653f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UCaseProps *csp;
654f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
655f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* current-level start/limit - s1/s2 as current */
656f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *start1, *start2, *limit1, *limit2;
657f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
658f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* case folding variables */
659f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *p;
660f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t length;
661f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
662f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* stacks of previous-level start/current/limit */
663f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    CmpEquivLevel stack1[2], stack2[2];
664f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
665f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* case folding buffers, only use current-level start/limit */
666f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar fold1[UCASE_MAX_STRING_LENGTH+1], fold2[UCASE_MAX_STRING_LENGTH+1];
667f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
668f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* track which is the current level per string */
669f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t level1, level2;
670f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
671f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* current code units, and code points for lookups */
672f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar32 c1, c2, cp1, cp2;
673f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
674f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* no argument error checking because this itself is not an API */
675f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
676f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /*
677f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     * assume that at least the option U_COMPARE_IGNORE_CASE is set
678f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     * otherwise this function would have to behave exactly as uprv_strCompare()
679f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)     */
680f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    csp=ucase_getSingleton();
681f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(U_FAILURE(*pErrorCode)) {
682f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
683f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
684f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
685f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* initialize */
686f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    start1=s1;
687f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(length1==-1) {
688f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        limit1=NULL;
689f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
690f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        limit1=s1+length1;
691f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
692f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
693f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    start2=s2;
694f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(length2==-1) {
695f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        limit2=NULL;
696f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    } else {
697f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        limit2=s2+length2;
698f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
699f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
700f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    level1=level2=0;
701f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    c1=c2=-1;
702f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
703f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* comparison loop */
704f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for(;;) {
705f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /*
706f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * here a code unit value of -1 means "get another code unit"
707f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * below it will mean "this source is finished"
708f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         */
709f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
710f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(c1<0) {
711f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* get next code unit from string 1, post-increment */
712f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            for(;;) {
713f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if(s1==limit1 || ((c1=*s1)==0 && (limit1==NULL || (options&_STRNCMP_STYLE)))) {
714f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if(level1==0) {
715f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        c1=-1;
716f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        break;
717f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
718f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } else {
719f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    ++s1;
720f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
721f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
722f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
723f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* reached end of level buffer, pop one level */
724f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                do {
725f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    --level1;
726f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    start1=stack1[level1].start;
727f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } while(start1==NULL);
728f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                s1=stack1[level1].s;
729f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                limit1=stack1[level1].limit;
730f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
731f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
732f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
733f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(c2<0) {
734f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* get next code unit from string 2, post-increment */
735f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            for(;;) {
736f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if(s2==limit2 || ((c2=*s2)==0 && (limit2==NULL || (options&_STRNCMP_STYLE)))) {
737f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if(level2==0) {
738f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        c2=-1;
739f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        break;
740f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
741f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } else {
742f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    ++s2;
743f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
744f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
745f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
746f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* reached end of level buffer, pop one level */
747f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                do {
748f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    --level2;
749f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    start2=stack2[level2].start;
750f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } while(start2==NULL);
751f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                s2=stack2[level2].s;
752f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                limit2=stack2[level2].limit;
753f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
754f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
755f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
756f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /*
757f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * compare c1 and c2
758f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * either variable c1, c2 is -1 only if the corresponding string is finished
759f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         */
760f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(c1==c2) {
761f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(c1<0) {
762f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                return 0;   /* c1==c2==-1 indicating end of strings */
763f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
764f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            c1=c2=-1;       /* make us fetch new code units */
765f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            continue;
766f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else if(c1<0) {
767f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return -1;      /* string 1 ends before string 2 */
768f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else if(c2<0) {
769f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return 1;       /* string 2 ends before string 1 */
770f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
771f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* c1!=c2 && c1>=0 && c2>=0 */
772f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
773f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* get complete code points for c1, c2 for lookups if either is a surrogate */
774f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        cp1=c1;
775f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(U_IS_SURROGATE(c1)) {
776f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            UChar c;
777f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
778f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(U_IS_SURROGATE_LEAD(c1)) {
779f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if(s1!=limit1 && U16_IS_TRAIL(c=*s1)) {
780f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    /* advance ++s1; only below if cp1 decomposes/case-folds */
781f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    cp1=U16_GET_SUPPLEMENTARY(c1, c);
782f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
783f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            } else /* isTrail(c1) */ {
784f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if(start1<=(s1-2) && U16_IS_LEAD(c=*(s1-2))) {
785f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    cp1=U16_GET_SUPPLEMENTARY(c, c1);
786f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
787f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
788f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
789f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
790f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        cp2=c2;
791f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(U_IS_SURROGATE(c2)) {
792f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            UChar c;
793f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
794f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(U_IS_SURROGATE_LEAD(c2)) {
795f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if(s2!=limit2 && U16_IS_TRAIL(c=*s2)) {
796f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    /* advance ++s2; only below if cp2 decomposes/case-folds */
797f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    cp2=U16_GET_SUPPLEMENTARY(c2, c);
798f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
799f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            } else /* isTrail(c2) */ {
800f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if(start2<=(s2-2) && U16_IS_LEAD(c=*(s2-2))) {
801f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    cp2=U16_GET_SUPPLEMENTARY(c, c2);
802f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
803f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
804f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
805f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
806f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /*
807f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * go down one level for each string
808f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * continue with the main loop as soon as there is a real change
809f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         */
810f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
811f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if( level1==0 &&
812f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (length=ucase_toFullFolding(csp, (UChar32)cp1, &p, options))>=0
813f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ) {
814f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* cp1 case-folds to the code point "length" or to p[length] */
815f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(U_IS_SURROGATE(c1)) {
816f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if(U_IS_SURROGATE_LEAD(c1)) {
817f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    /* advance beyond source surrogate pair if it case-folds */
818f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    ++s1;
819f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } else /* isTrail(c1) */ {
820f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    /*
821f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     * we got a supplementary code point when hitting its trail surrogate,
822f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     * therefore the lead surrogate must have been the same as in the other string;
823f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     * compare this decomposition with the lead surrogate in the other string
824f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     * remember that this simulates bulk text replacement:
825f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     * the decomposition would replace the entire code point
826f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     */
827f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    --s2;
828f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    c2=*(s2-1);
829f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
830f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
831f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
832f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* push current level pointers */
833f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            stack1[0].start=start1;
834f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            stack1[0].s=s1;
835f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            stack1[0].limit=limit1;
836f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            ++level1;
837f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
838f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* copy the folding result to fold1[] */
839f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(length<=UCASE_MAX_STRING_LENGTH) {
840f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                u_memcpy(fold1, p, length);
841f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            } else {
842f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                int32_t i=0;
843f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                U16_APPEND_UNSAFE(fold1, i, length);
844f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                length=i;
845f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
846f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
847f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* set next level pointers to case folding */
848f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            start1=s1=fold1;
849f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            limit1=fold1+length;
850f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
851f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* get ready to read from decomposition, continue with loop */
852f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            c1=-1;
853f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            continue;
854f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
855f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
856f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if( level2==0 &&
857f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (length=ucase_toFullFolding(csp, (UChar32)cp2, &p, options))>=0
858f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        ) {
859f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* cp2 case-folds to the code point "length" or to p[length] */
860f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(U_IS_SURROGATE(c2)) {
861f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if(U_IS_SURROGATE_LEAD(c2)) {
862f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    /* advance beyond source surrogate pair if it case-folds */
863f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    ++s2;
864f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                } else /* isTrail(c2) */ {
865f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    /*
866f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     * we got a supplementary code point when hitting its trail surrogate,
867f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     * therefore the lead surrogate must have been the same as in the other string;
868f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     * compare this decomposition with the lead surrogate in the other string
869f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     * remember that this simulates bulk text replacement:
870f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     * the decomposition would replace the entire code point
871f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     */
872f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    --s1;
873f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    c1=*(s1-1);
874f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
875f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
876f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
877f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* push current level pointers */
878f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            stack2[0].start=start2;
879f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            stack2[0].s=s2;
880f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            stack2[0].limit=limit2;
881f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            ++level2;
882f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
883f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* copy the folding result to fold2[] */
884f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(length<=UCASE_MAX_STRING_LENGTH) {
885f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                u_memcpy(fold2, p, length);
886f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            } else {
887f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                int32_t i=0;
888f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                U16_APPEND_UNSAFE(fold2, i, length);
889f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                length=i;
890f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
891f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
892f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* set next level pointers to case folding */
893f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            start2=s2=fold2;
894f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            limit2=fold2+length;
895f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
896f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* get ready to read from decomposition, continue with loop */
897f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            c2=-1;
898f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            continue;
899f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
900f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
901f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /*
902f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * no decomposition/case folding, max level for both sides:
903f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * return difference result
904f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         *
905f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * code point order comparison must not just return cp1-cp2
906f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * because when single surrogates are present then the surrogate pairs
907f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * that formed cp1 and cp2 may be from different string indexes
908f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         *
909f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * example: { d800 d800 dc01 } vs. { d800 dc00 }, compare at second code units
910f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * c1=d800 cp1=10001 c2=dc00 cp2=10000
911f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * cp1-cp2>0 but c1-c2<0 and in fact in UTF-32 it is { d800 10001 } < { 10000 }
912f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         *
913f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * therefore, use same fix-up as in ustring.c/uprv_strCompare()
914f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * except: uprv_strCompare() fetches c=*s while this functions fetches c=*s++
915f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         * so we have slightly different pointer/start/limit comparisons here
916f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)         */
917f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
918f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(c1>=0xd800 && c2>=0xd800 && (options&U_COMPARE_CODE_POINT_ORDER)) {
919f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* subtract 0x2800 from BMP code points to make them smaller than supplementary ones */
920f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(
921f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                (c1<=0xdbff && s1!=limit1 && U16_IS_TRAIL(*s1)) ||
922f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                (U16_IS_TRAIL(c1) && start1!=(s1-1) && U16_IS_LEAD(*(s1-2)))
923f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            ) {
924f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* part of a surrogate pair, leave >=d800 */
925f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            } else {
926f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* BMP code point - may be surrogate code point - make <d800 */
927f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                c1-=0x2800;
928f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
929f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
930f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(
931f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                (c2<=0xdbff && s2!=limit2 && U16_IS_TRAIL(*s2)) ||
932f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                (U16_IS_TRAIL(c2) && start2!=(s2-1) && U16_IS_LEAD(*(s2-2)))
933f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            ) {
934f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* part of a surrogate pair, leave >=d800 */
935f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            } else {
936f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* BMP code point - may be surrogate code point - make <d800 */
937f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                c2-=0x2800;
938f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
939f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
940f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
941f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return c1-c2;
942f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
943f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
944f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
945f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* public API functions */
946f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
947f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2
948f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_strCaseCompare(const UChar *s1, int32_t length1,
949f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 const UChar *s2, int32_t length2,
950f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 uint32_t options,
951f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 UErrorCode *pErrorCode) {
952f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* argument checking */
953f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(pErrorCode==0 || U_FAILURE(*pErrorCode)) {
954f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
955f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
956f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(s1==NULL || length1<-1 || s2==NULL || length2<-1) {
957f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR;
958f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
959f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
960f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return u_strcmpFold(s1, length1, s2, length2,
961f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        options|U_COMPARE_IGNORE_CASE,
962f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        pErrorCode);
963f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
964f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
965f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2
966f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_strcasecmp(const UChar *s1, const UChar *s2, uint32_t options) {
967f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode errorCode=U_ZERO_ERROR;
968f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return u_strcmpFold(s1, -1, s2, -1,
969f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        options|U_COMPARE_IGNORE_CASE,
970f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        &errorCode);
971f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
972f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
973f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2
974f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_memcasecmp(const UChar *s1, const UChar *s2, int32_t length, uint32_t options) {
975f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode errorCode=U_ZERO_ERROR;
976f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return u_strcmpFold(s1, length, s2, length,
977f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        options|U_COMPARE_IGNORE_CASE,
978f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        &errorCode);
979f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
980f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
981f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CAPI int32_t U_EXPORT2
982f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_strncasecmp(const UChar *s1, const UChar *s2, int32_t n, uint32_t options) {
983f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode errorCode=U_ZERO_ERROR;
984f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return u_strcmpFold(s1, n, s2, n,
985f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        options|(U_COMPARE_IGNORE_CASE|_STRNCMP_STYLE),
986f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        &errorCode);
987f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
988