2 *******************************************************************************
4 * Copyright (C) 2001-2008, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * file name: ustrcase.c
10 * tab size: 8 (not used)
13 * created on: 2002feb20
14 * created by: Markus W. Scherer
16 * Implementation file for string casing C API functions.
17 * Uses functions from uchar.c for basic functionality that requires access
18 * to the Unicode Character Database (uprops.dat).
21 #include "unicode/utypes.h"
22 #include "unicode/uloc.h"
23 #include "unicode/ustring.h"
24 #include "unicode/ucasemap.h"
25 #include "unicode/ubrk.h"
31 /* string casing ------------------------------------------------------------ */
33 /* append a full case mapping result, see UCASE_MAX_STRING_LENGTH */
34 static U_INLINE
int32_t
35 appendResult(UChar
*dest
, int32_t destIndex
, int32_t destCapacity
,
36 int32_t result
, const UChar
*s
) {
40 /* decode the result */
42 /* (not) original code point */
45 } else if(result
<=UCASE_MAX_STRING_LENGTH
) {
53 if(destIndex
<destCapacity
) {
54 /* append the result */
58 U16_APPEND(dest
, destIndex
, destCapacity
, c
, isError
);
60 /* overflow, nothing written */
61 destIndex
+=U16_LENGTH(c
);
65 if((destIndex
+length
)<=destCapacity
) {
67 dest
[destIndex
++]=*s
++;
78 destIndex
+=U16_LENGTH(c
);
86 static UChar32 U_CALLCONV
87 utf16_caseContextIterator(void *context
, int8_t dir
) {
88 UCaseContext
*csc
=(UCaseContext
*)context
;
92 /* reset for backward iteration */
93 csc
->index
=csc
->cpStart
;
96 /* reset for forward iteration */
97 csc
->index
=csc
->cpLimit
;
100 /* continue current iteration direction */
105 if(csc
->start
<csc
->index
) {
106 U16_PREV((const UChar
*)csc
->p
, csc
->start
, csc
->index
, c
);
110 if(csc
->index
<csc
->limit
) {
111 U16_NEXT((const UChar
*)csc
->p
, csc
->index
, csc
->limit
, c
);
119 * Case-maps [srcStart..srcLimit[ but takes
120 * context [0..srcLength[ into account.
123 _caseMap(const UCaseMap
*csm
, UCaseMapFull
*map
,
124 UChar
*dest
, int32_t destCapacity
,
125 const UChar
*src
, UCaseContext
*csc
,
126 int32_t srcStart
, int32_t srcLimit
,
127 UErrorCode
*pErrorCode
) {
130 int32_t srcIndex
, destIndex
;
133 locCache
=csm
->locCache
;
135 /* case mapping loop */
138 while(srcIndex
<srcLimit
) {
139 csc
->cpStart
=srcIndex
;
140 U16_NEXT(src
, srcIndex
, srcLimit
, c
);
141 csc
->cpLimit
=srcIndex
;
142 c
=map(csm
->csp
, c
, utf16_caseContextIterator
, csc
, &s
, csm
->locale
, &locCache
);
143 if((destIndex
<destCapacity
) && (c
<0 ? (c2
=~c
)<=0xffff : UCASE_MAX_STRING_LENGTH
<c
&& (c2
=c
)<=0xffff)) {
144 /* fast path version of appendResult() for BMP results */
145 dest
[destIndex
++]=(UChar
)c2
;
147 destIndex
=appendResult(dest
, destIndex
, destCapacity
, c
, s
);
151 if(destIndex
>destCapacity
) {
152 *pErrorCode
=U_BUFFER_OVERFLOW_ERROR
;
158 setTempCaseMapLocale(UCaseMap
*csm
, const char *locale
, UErrorCode
*pErrorCode
) {
160 * We could call ucasemap_setLocale(), but here we really only care about
161 * the initial language subtag, we need not return the real string via
162 * ucasemap_getLocale(), and we don't care about only getting "x" from
163 * "x-some-thing" etc.
165 * We ignore locales with a longer-than-3 initial subtag.
167 * We also do not fill in the locCache because it is rarely used,
168 * and not worth setting unless we reuse it for many case mapping operations.
169 * (That's why UCaseMap was created.)
174 /* the internal functions require locale!=NULL */
176 locale
=uloc_getDefault();
178 for(i
=0; i
<4 && (c
=locale
[i
])!=0 && c
!='-' && c
!='_'; ++i
) {
182 csm
->locale
[i
]=0; /* Up to 3 non-separator characters. */
184 csm
->locale
[0]=0; /* Longer-than-3 initial subtag: Ignore. */
189 * Set parameters on an empty UCaseMap, for UCaseMap-less API functions.
190 * Do this fast because it is called with every function call.
193 setTempCaseMap(UCaseMap
*csm
, const char *locale
, UErrorCode
*pErrorCode
) {
195 csm
->csp
=ucase_getSingleton(pErrorCode
);
196 if(U_FAILURE(*pErrorCode
)) {
200 if(locale
!=NULL
&& locale
[0]==0) {
203 setTempCaseMapLocale(csm
, locale
, pErrorCode
);
207 #if !UCONFIG_NO_BREAK_ITERATION
210 * Internal titlecasing function.
213 _toTitle(UCaseMap
*csm
,
214 UChar
*dest
, int32_t destCapacity
,
215 const UChar
*src
, UCaseContext
*csc
,
217 UErrorCode
*pErrorCode
) {
220 int32_t prev
, titleStart
, titleLimit
, titleLimitSave
, index
, indexSave
, destIndex
, length
;
223 if(csm
->iter
!=NULL
) {
224 ubrk_setText(csm
->iter
, src
, srcLength
, pErrorCode
);
226 csm
->iter
=ubrk_open(UBRK_WORD
, csm
->locale
,
230 if(U_FAILURE(*pErrorCode
)) {
234 /* set up local variables */
239 /* titlecasing loop */
240 while(prev
<srcLength
) {
241 /* find next index where to titlecase */
244 index
=ubrk_first(csm
->iter
);
246 index
=ubrk_next(csm
->iter
);
248 if(index
==UBRK_DONE
|| index
>srcLength
) {
253 * Unicode 4 & 5 section 3.13 Default Case Operations:
255 * R3 toTitlecase(X): Find the word boundaries based on Unicode Standard Annex
256 * #29, "Text Boundaries." Between each pair of word boundaries, find the first
257 * cased character F. If F exists, map F to default_title(F); then map each
258 * subsequent character C to default_lower(C).
260 * In this implementation, segment [prev..index[ into 3 parts:
261 * a) uncased characters (copy as-is) [prev..titleStart[
262 * b) first case letter (titlecase) [titleStart..titleLimit[
263 * c) subsequent characters (lowercase) [titleLimit..index[
266 /* find and copy uncased characters [prev..titleStart[ */
267 titleStart
=titleLimit
=prev
;
268 U16_NEXT(src
, titleLimit
, index
, c
);
269 if((csm
->options
&U_TITLECASE_NO_BREAK_ADJUSTMENT
)==0 && UCASE_NONE
==ucase_getType(csm
->csp
, c
)) {
270 /* Adjust the titlecasing index (titleStart) to the next cased character. */
272 titleStart
=titleLimit
;
273 if(titleLimit
==index
) {
275 * only uncased characters in [prev..index[
276 * stop with titleStart==titleLimit==index
280 U16_NEXT(src
, titleLimit
, index
, c
);
281 if(UCASE_NONE
!=ucase_getType(csm
->csp
, c
)) {
282 break; /* cased letter at [titleStart..titleLimit[ */
285 length
=titleStart
-prev
;
287 if((destIndex
+length
)<=destCapacity
) {
288 uprv_memcpy(dest
+destIndex
, src
+prev
, length
*U_SIZEOF_UCHAR
);
294 if(titleStart
<titleLimit
) {
295 /* titlecase c which is from [titleStart..titleLimit[ */
296 csc
->cpStart
=titleStart
;
297 csc
->cpLimit
=titleLimit
;
298 c
=ucase_toFullTitle(csm
->csp
, c
, utf16_caseContextIterator
, csc
, &s
, csm
->locale
, &csm
->locCache
);
299 destIndex
=appendResult(dest
, destIndex
, destCapacity
, c
, s
);
301 /* Special case Dutch IJ titlecasing */
302 if ( titleStart
+1 < index
&&
303 ucase_getCaseLocale(csm
->locale
,&csm
->locCache
) == UCASE_LOC_DUTCH
&&
304 ( src
[titleStart
] == (UChar32
) 0x0049 || src
[titleStart
] == (UChar32
) 0x0069 ) &&
305 ( src
[titleStart
+1] == (UChar32
) 0x004A || src
[titleStart
+1] == (UChar32
) 0x006A )) {
307 destIndex
=appendResult(dest
, destIndex
, destCapacity
, c
, s
);
311 /* lowercase [titleLimit..index[ */
312 if(titleLimit
<index
) {
313 if((csm
->options
&U_TITLECASE_NO_LOWERCASE
)==0) {
314 /* Normal operation: Lowercase the rest of the word. */
317 csm
, ucase_toFullLower
,
318 dest
+destIndex
, destCapacity
-destIndex
,
323 /* Optionally just copy the rest of the word unchanged. */
324 length
=index
-titleLimit
;
325 if((destIndex
+length
)<=destCapacity
) {
326 uprv_memcpy(dest
+destIndex
, src
+titleLimit
, length
*U_SIZEOF_UCHAR
);
337 if(destIndex
>destCapacity
) {
338 *pErrorCode
=U_BUFFER_OVERFLOW_ERROR
;
345 /* functions available in the common library (for unistr_case.cpp) */
348 ustr_toLower(const UCaseProps
*csp
,
349 UChar
*dest
, int32_t destCapacity
,
350 const UChar
*src
, int32_t srcLength
,
352 UErrorCode
*pErrorCode
) {
353 UCaseMap csm
={ NULL
};
354 UCaseContext csc
={ NULL
};
357 setTempCaseMap(&csm
, locale
, pErrorCode
);
361 return _caseMap(&csm
, ucase_toFullLower
,
363 src
, &csc
, 0, srcLength
,
368 ustr_toUpper(const UCaseProps
*csp
,
369 UChar
*dest
, int32_t destCapacity
,
370 const UChar
*src
, int32_t srcLength
,
372 UErrorCode
*pErrorCode
) {
373 UCaseMap csm
={ NULL
};
374 UCaseContext csc
={ NULL
};
377 setTempCaseMap(&csm
, locale
, pErrorCode
);
381 return _caseMap(&csm
, ucase_toFullUpper
,
383 src
, &csc
, 0, srcLength
,
387 #if !UCONFIG_NO_BREAK_ITERATION
390 ustr_toTitle(const UCaseProps
*csp
,
391 UChar
*dest
, int32_t destCapacity
,
392 const UChar
*src
, int32_t srcLength
,
393 UBreakIterator
*titleIter
,
394 const char *locale
, uint32_t options
,
395 UErrorCode
*pErrorCode
) {
396 UCaseMap csm
={ NULL
};
397 UCaseContext csc
={ NULL
};
403 setTempCaseMap(&csm
, locale
, pErrorCode
);
407 length
=_toTitle(&csm
,
409 src
, &csc
, srcLength
,
411 if(titleIter
==NULL
&& csm
.iter
!=NULL
) {
412 ubrk_close(csm
.iter
);
420 ustr_foldCase(const UCaseProps
*csp
,
421 UChar
*dest
, int32_t destCapacity
,
422 const UChar
*src
, int32_t srcLength
,
424 UErrorCode
*pErrorCode
) {
425 int32_t srcIndex
, destIndex
;
430 /* case mapping loop */
431 srcIndex
=destIndex
=0;
432 while(srcIndex
<srcLength
) {
433 U16_NEXT(src
, srcIndex
, srcLength
, c
);
434 c
=ucase_toFullFolding(csp
, c
, &s
, options
);
435 if((destIndex
<destCapacity
) && (c
<0 ? (c2
=~c
)<=0xffff : UCASE_MAX_STRING_LENGTH
<c
&& (c2
=c
)<=0xffff)) {
436 /* fast path version of appendResult() for BMP results */
437 dest
[destIndex
++]=(UChar
)c2
;
439 destIndex
=appendResult(dest
, destIndex
, destCapacity
, c
, s
);
443 if(destIndex
>destCapacity
) {
444 *pErrorCode
=U_BUFFER_OVERFLOW_ERROR
;
450 * Implement argument checking and buffer handling
451 * for string case mapping as a common function.
454 /* common internal function for public API functions */
457 caseMap(const UCaseMap
*csm
,
458 UChar
*dest
, int32_t destCapacity
,
459 const UChar
*src
, int32_t srcLength
,
461 UErrorCode
*pErrorCode
) {
467 /* check argument values */
468 if(pErrorCode
==NULL
|| U_FAILURE(*pErrorCode
)) {
471 if( destCapacity
<0 ||
472 (dest
==NULL
&& destCapacity
>0) ||
476 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
480 /* get the string length */
482 srcLength
=u_strlen(src
);
485 /* check for overlapping source and destination */
487 ((src
>=dest
&& src
<(dest
+destCapacity
)) ||
488 (dest
>=src
&& dest
<(src
+srcLength
)))
490 /* overlap: provide a temporary destination buffer and later copy the result */
491 if(destCapacity
<=(sizeof(buffer
)/U_SIZEOF_UCHAR
)) {
492 /* the stack buffer is large enough */
495 /* allocate a buffer */
496 temp
=(UChar
*)uprv_malloc(destCapacity
*U_SIZEOF_UCHAR
);
498 *pErrorCode
=U_MEMORY_ALLOCATION_ERROR
;
508 if(toWhichCase
==FOLD_CASE
) {
509 destLength
=ustr_foldCase(csm
->csp
, temp
, destCapacity
, src
, srcLength
,
510 csm
->options
, pErrorCode
);
512 UCaseContext csc
={ NULL
};
517 if(toWhichCase
==TO_LOWER
) {
518 destLength
=_caseMap(csm
, ucase_toFullLower
,
523 } else if(toWhichCase
==TO_UPPER
) {
524 destLength
=_caseMap(csm
, ucase_toFullUpper
,
529 } else /* if(toWhichCase==TO_TITLE) */ {
530 #if UCONFIG_NO_BREAK_ITERATION
531 *pErrorCode
=U_UNSUPPORTED_ERROR
;
533 /* UCaseMap is actually non-const in toTitle() APIs. */
534 destLength
=_toTitle((UCaseMap
*)csm
, temp
, destCapacity
,
535 src
, &csc
, srcLength
,
541 /* copy the result string to the destination buffer */
543 int32_t copyLength
= destLength
<=destCapacity
? destLength
: destCapacity
;
545 uprv_memmove(dest
, temp
, copyLength
*U_SIZEOF_UCHAR
);
553 return u_terminateUChars(dest
, destCapacity
, destLength
, pErrorCode
);
556 /* public API functions */
558 U_CAPI
int32_t U_EXPORT2
559 u_strToLower(UChar
*dest
, int32_t destCapacity
,
560 const UChar
*src
, int32_t srcLength
,
562 UErrorCode
*pErrorCode
) {
563 UCaseMap csm
={ NULL
};
564 setTempCaseMap(&csm
, locale
, pErrorCode
);
568 TO_LOWER
, pErrorCode
);
571 U_CAPI
int32_t U_EXPORT2
572 u_strToUpper(UChar
*dest
, int32_t destCapacity
,
573 const UChar
*src
, int32_t srcLength
,
575 UErrorCode
*pErrorCode
) {
576 UCaseMap csm
={ NULL
};
577 setTempCaseMap(&csm
, locale
, pErrorCode
);
581 TO_UPPER
, pErrorCode
);
584 #if !UCONFIG_NO_BREAK_ITERATION
586 U_CAPI
int32_t U_EXPORT2
587 u_strToTitle(UChar
*dest
, int32_t destCapacity
,
588 const UChar
*src
, int32_t srcLength
,
589 UBreakIterator
*titleIter
,
591 UErrorCode
*pErrorCode
) {
592 UCaseMap csm
={ NULL
};
596 setTempCaseMap(&csm
, locale
, pErrorCode
);
600 TO_TITLE
, pErrorCode
);
601 if(titleIter
==NULL
&& csm
.iter
!=NULL
) {
602 ubrk_close(csm
.iter
);
607 U_CAPI
int32_t U_EXPORT2
608 ucasemap_toTitle(UCaseMap
*csm
,
609 UChar
*dest
, int32_t destCapacity
,
610 const UChar
*src
, int32_t srcLength
,
611 UErrorCode
*pErrorCode
) {
615 TO_TITLE
, pErrorCode
);
620 U_CAPI
int32_t U_EXPORT2
621 u_strFoldCase(UChar
*dest
, int32_t destCapacity
,
622 const UChar
*src
, int32_t srcLength
,
624 UErrorCode
*pErrorCode
) {
625 UCaseMap csm
={ NULL
};
626 csm
.csp
=ucase_getSingleton(pErrorCode
);
631 FOLD_CASE
, pErrorCode
);
634 /* case-insensitive string comparisons -------------------------------------- */
637 * This function is a copy of unorm_cmpEquivFold() minus the parts for
638 * canonical equivalence.
639 * Keep the functions in sync, and see there for how this works.
640 * The duplication is for modularization:
641 * It makes caseless (but not canonical caseless) matches independent of
642 * the normalization code.
645 /* stack element for previous-level source/decomposition pointers */
646 struct CmpEquivLevel
{
647 const UChar
*start
, *s
, *limit
;
649 typedef struct CmpEquivLevel CmpEquivLevel
;
651 /* internal function */
653 u_strcmpFold(const UChar
*s1
, int32_t length1
,
654 const UChar
*s2
, int32_t length2
,
656 UErrorCode
*pErrorCode
) {
657 const UCaseProps
*csp
;
659 /* current-level start/limit - s1/s2 as current */
660 const UChar
*start1
, *start2
, *limit1
, *limit2
;
662 /* case folding variables */
666 /* stacks of previous-level start/current/limit */
667 CmpEquivLevel stack1
[2], stack2
[2];
669 /* case folding buffers, only use current-level start/limit */
670 UChar fold1
[UCASE_MAX_STRING_LENGTH
+1], fold2
[UCASE_MAX_STRING_LENGTH
+1];
672 /* track which is the current level per string */
673 int32_t level1
, level2
;
675 /* current code units, and code points for lookups */
676 UChar32 c1
, c2
, cp1
, cp2
;
678 /* no argument error checking because this itself is not an API */
681 * assume that at least the option U_COMPARE_IGNORE_CASE is set
682 * otherwise this function would have to behave exactly as uprv_strCompare()
684 csp
=ucase_getSingleton(pErrorCode
);
685 if(U_FAILURE(*pErrorCode
)) {
707 /* comparison loop */
710 * here a code unit value of -1 means "get another code unit"
711 * below it will mean "this source is finished"
715 /* get next code unit from string 1, post-increment */
717 if(s1
==limit1
|| ((c1
=*s1
)==0 && (limit1
==NULL
|| (options
&_STRNCMP_STYLE
)))) {
727 /* reached end of level buffer, pop one level */
730 start1
=stack1
[level1
].start
;
731 } while(start1
==NULL
);
733 limit1
=stack1
[level1
].limit
;
738 /* get next code unit from string 2, post-increment */
740 if(s2
==limit2
|| ((c2
=*s2
)==0 && (limit2
==NULL
|| (options
&_STRNCMP_STYLE
)))) {
750 /* reached end of level buffer, pop one level */
753 start2
=stack2
[level2
].start
;
754 } while(start2
==NULL
);
756 limit2
=stack2
[level2
].limit
;
762 * either variable c1, c2 is -1 only if the corresponding string is finished
766 return 0; /* c1==c2==-1 indicating end of strings */
768 c1
=c2
=-1; /* make us fetch new code units */
771 return -1; /* string 1 ends before string 2 */
773 return 1; /* string 2 ends before string 1 */
775 /* c1!=c2 && c1>=0 && c2>=0 */
777 /* get complete code points for c1, c2 for lookups if either is a surrogate */
779 if(U_IS_SURROGATE(c1
)) {
782 if(U_IS_SURROGATE_LEAD(c1
)) {
783 if(s1
!=limit1
&& U16_IS_TRAIL(c
=*s1
)) {
784 /* advance ++s1; only below if cp1 decomposes/case-folds */
785 cp1
=U16_GET_SUPPLEMENTARY(c1
, c
);
787 } else /* isTrail(c1) */ {
788 if(start1
<=(s1
-2) && U16_IS_LEAD(c
=*(s1
-2))) {
789 cp1
=U16_GET_SUPPLEMENTARY(c
, c1
);
795 if(U_IS_SURROGATE(c2
)) {
798 if(U_IS_SURROGATE_LEAD(c2
)) {
799 if(s2
!=limit2
&& U16_IS_TRAIL(c
=*s2
)) {
800 /* advance ++s2; only below if cp2 decomposes/case-folds */
801 cp2
=U16_GET_SUPPLEMENTARY(c2
, c
);
803 } else /* isTrail(c2) */ {
804 if(start2
<=(s2
-2) && U16_IS_LEAD(c
=*(s2
-2))) {
805 cp2
=U16_GET_SUPPLEMENTARY(c
, c2
);
811 * go down one level for each string
812 * continue with the main loop as soon as there is a real change
816 (length
=ucase_toFullFolding(csp
, (UChar32
)cp1
, &p
, options
))>=0
818 /* cp1 case-folds to the code point "length" or to p[length] */
819 if(U_IS_SURROGATE(c1
)) {
820 if(U_IS_SURROGATE_LEAD(c1
)) {
821 /* advance beyond source surrogate pair if it case-folds */
823 } else /* isTrail(c1) */ {
825 * we got a supplementary code point when hitting its trail surrogate,
826 * therefore the lead surrogate must have been the same as in the other string;
827 * compare this decomposition with the lead surrogate in the other string
828 * remember that this simulates bulk text replacement:
829 * the decomposition would replace the entire code point
836 /* push current level pointers */
837 stack1
[0].start
=start1
;
839 stack1
[0].limit
=limit1
;
842 /* copy the folding result to fold1[] */
843 if(length
<=UCASE_MAX_STRING_LENGTH
) {
844 u_memcpy(fold1
, p
, length
);
847 U16_APPEND_UNSAFE(fold1
, i
, length
);
851 /* set next level pointers to case folding */
855 /* get ready to read from decomposition, continue with loop */
861 (length
=ucase_toFullFolding(csp
, (UChar32
)cp2
, &p
, options
))>=0
863 /* cp2 case-folds to the code point "length" or to p[length] */
864 if(U_IS_SURROGATE(c2
)) {
865 if(U_IS_SURROGATE_LEAD(c2
)) {
866 /* advance beyond source surrogate pair if it case-folds */
868 } else /* isTrail(c2) */ {
870 * we got a supplementary code point when hitting its trail surrogate,
871 * therefore the lead surrogate must have been the same as in the other string;
872 * compare this decomposition with the lead surrogate in the other string
873 * remember that this simulates bulk text replacement:
874 * the decomposition would replace the entire code point
881 /* push current level pointers */
882 stack2
[0].start
=start2
;
884 stack2
[0].limit
=limit2
;
887 /* copy the folding result to fold2[] */
888 if(length
<=UCASE_MAX_STRING_LENGTH
) {
889 u_memcpy(fold2
, p
, length
);
892 U16_APPEND_UNSAFE(fold2
, i
, length
);
896 /* set next level pointers to case folding */
900 /* get ready to read from decomposition, continue with loop */
906 * no decomposition/case folding, max level for both sides:
907 * return difference result
909 * code point order comparison must not just return cp1-cp2
910 * because when single surrogates are present then the surrogate pairs
911 * that formed cp1 and cp2 may be from different string indexes
913 * example: { d800 d800 dc01 } vs. { d800 dc00 }, compare at second code units
914 * c1=d800 cp1=10001 c2=dc00 cp2=10000
915 * cp1-cp2>0 but c1-c2<0 and in fact in UTF-32 it is { d800 10001 } < { 10000 }
917 * therefore, use same fix-up as in ustring.c/uprv_strCompare()
918 * except: uprv_strCompare() fetches c=*s while this functions fetches c=*s++
919 * so we have slightly different pointer/start/limit comparisons here
922 if(c1
>=0xd800 && c2
>=0xd800 && (options
&U_COMPARE_CODE_POINT_ORDER
)) {
923 /* subtract 0x2800 from BMP code points to make them smaller than supplementary ones */
925 (c1
<=0xdbff && s1
!=limit1
&& U16_IS_TRAIL(*s1
)) ||
926 (U16_IS_TRAIL(c1
) && start1
!=(s1
-1) && U16_IS_LEAD(*(s1
-2)))
928 /* part of a surrogate pair, leave >=d800 */
930 /* BMP code point - may be surrogate code point - make <d800 */
935 (c2
<=0xdbff && s2
!=limit2
&& U16_IS_TRAIL(*s2
)) ||
936 (U16_IS_TRAIL(c2
) && start2
!=(s2
-1) && U16_IS_LEAD(*(s2
-2)))
938 /* part of a surrogate pair, leave >=d800 */
940 /* BMP code point - may be surrogate code point - make <d800 */
949 /* public API functions */
951 U_CAPI
int32_t U_EXPORT2
952 u_strCaseCompare(const UChar
*s1
, int32_t length1
,
953 const UChar
*s2
, int32_t length2
,
955 UErrorCode
*pErrorCode
) {
956 /* argument checking */
957 if(pErrorCode
==0 || U_FAILURE(*pErrorCode
)) {
960 if(s1
==NULL
|| length1
<-1 || s2
==NULL
|| length2
<-1) {
961 *pErrorCode
=U_ILLEGAL_ARGUMENT_ERROR
;
964 return u_strcmpFold(s1
, length1
, s2
, length2
,
965 options
|U_COMPARE_IGNORE_CASE
,
969 U_CAPI
int32_t U_EXPORT2
970 u_strcasecmp(const UChar
*s1
, const UChar
*s2
, uint32_t options
) {
971 UErrorCode errorCode
=U_ZERO_ERROR
;
972 return u_strcmpFold(s1
, -1, s2
, -1,
973 options
|U_COMPARE_IGNORE_CASE
,
977 U_CAPI
int32_t U_EXPORT2
978 u_memcasecmp(const UChar
*s1
, const UChar
*s2
, int32_t length
, uint32_t options
) {
979 UErrorCode errorCode
=U_ZERO_ERROR
;
980 return u_strcmpFold(s1
, length
, s2
, length
,
981 options
|U_COMPARE_IGNORE_CASE
,
985 U_CAPI
int32_t U_EXPORT2
986 u_strncasecmp(const UChar
*s1
, const UChar
*s2
, int32_t n
, uint32_t options
) {
987 UErrorCode errorCode
=U_ZERO_ERROR
;
988 return u_strcmpFold(s1
, n
, s2
, n
,
989 options
|(U_COMPARE_IGNORE_CASE
|_STRNCMP_STYLE
),