]>
git.saurik.com Git - apple/icu.git/blob - icuSources/common/unistr_case.cpp
2 *******************************************************************************
4 * Copyright (C) 1999-2004, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * file name: unistr_case.cpp
10 * tab size: 8 (not used)
13 * created on: 2004aug19
14 * created by: Markus W. Scherer
16 * Case-mapping functions moved here from unistr.cpp
19 #include "unicode/utypes.h"
20 #include "unicode/putil.h"
21 #include "unicode/locid.h"
24 #include "unicode/ustring.h"
25 #include "unicode/unistr.h"
26 #include "unicode/uchar.h"
27 #include "unicode/ubrk.h"
33 //========================================
34 // Read-only implementation
35 //========================================
38 UnicodeString::doCaseCompare(int32_t start
,
40 const UChar
*srcChars
,
43 uint32_t options
) const
45 // compare illegal string values
46 // treat const UChar *srcChars==NULL as an empty string
51 // pin indices to legal values
52 pinIndices(start
, length
);
54 if(srcChars
== NULL
) {
55 srcStart
= srcLength
= 0;
58 // get the correct pointer
59 const UChar
*chars
= getArrayStart();
64 if(chars
!= srcChars
) {
65 UErrorCode errorCode
=U_ZERO_ERROR
;
66 int32_t result
=u_strcmpFold(chars
, length
, srcChars
, srcLength
,
67 options
|U_COMPARE_IGNORE_CASE
, &errorCode
);
69 return (int8_t)(result
>> 24 | 1);
72 // get the srcLength if necessary
74 srcLength
= u_strlen(srcChars
+ srcStart
);
76 if(length
!= srcLength
) {
77 return (int8_t)((length
- srcLength
) >> 24 | 1);
83 //========================================
84 // Write implementation
85 //========================================
88 * Implement argument checking and buffer handling
89 * for string case mapping as a common function.
99 UnicodeString::caseMap(BreakIterator
*titleIter
,
102 int32_t toWhichCase
) {
108 UErrorCode errorCode
;
110 errorCode
= U_ZERO_ERROR
;
111 UCaseProps
*csp
=ucase_getSingleton(&errorCode
);
112 if(U_FAILURE(errorCode
)) {
117 // We need to allocate a new buffer for the internal string case mapping function.
118 // This is very similar to how doReplace() below keeps the old array pointer
119 // and deletes the old array itself after it is done.
120 // In addition, we are forcing cloneArrayIfNeeded() to always allocate a new array.
121 UChar
*oldArray
= fArray
;
122 int32_t oldLength
= fLength
;
123 int32_t *bufferToDelete
= 0;
125 // Make sure that if the string is in fStackBuffer we do not overwrite it!
127 if(fLength
<= US_STACKBUF_SIZE
) {
128 if(fArray
== fStackBuffer
) {
129 capacity
= 2 * US_STACKBUF_SIZE
; // make sure that cloneArrayIfNeeded() allocates a new buffer
131 capacity
= US_STACKBUF_SIZE
;
134 capacity
= fLength
+ 20;
136 if(!cloneArrayIfNeeded(capacity
, capacity
, FALSE
, &bufferToDelete
, TRUE
)) {
140 #if !UCONFIG_NO_BREAK_ITERATION
141 // set up the titlecasing break iterator
142 UBreakIterator
*cTitleIter
= 0;
144 if(toWhichCase
== TO_TITLE
) {
145 errorCode
= U_ZERO_ERROR
;
147 cTitleIter
= (UBreakIterator
*)titleIter
;
148 ubrk_setText(cTitleIter
, oldArray
, oldLength
, &errorCode
);
150 cTitleIter
= ubrk_open(UBRK_WORD
, locale
,
154 if(U_FAILURE(errorCode
)) {
155 uprv_free(bufferToDelete
);
162 // Case-map, and if the result is too long, then reallocate and repeat.
164 errorCode
= U_ZERO_ERROR
;
165 if(toWhichCase
==TO_LOWER
) {
166 fLength
= ustr_toLower(csp
, fArray
, fCapacity
,
169 } else if(toWhichCase
==TO_UPPER
) {
170 fLength
= ustr_toUpper(csp
, fArray
, fCapacity
,
173 } else if(toWhichCase
==TO_TITLE
) {
174 #if UCONFIG_NO_BREAK_ITERATION
175 errorCode
=U_UNSUPPORTED_ERROR
;
177 fLength
= ustr_toTitle(csp
, fArray
, fCapacity
,
179 cTitleIter
, locale
, &errorCode
);
182 fLength
= ustr_foldCase(csp
, fArray
, fCapacity
,
187 } while(errorCode
==U_BUFFER_OVERFLOW_ERROR
&& cloneArrayIfNeeded(fLength
, fLength
, FALSE
));
189 #if !UCONFIG_NO_BREAK_ITERATION
190 if(cTitleIter
!= 0 && titleIter
== 0) {
191 ubrk_close(cTitleIter
);
195 if (bufferToDelete
) {
196 uprv_free(bufferToDelete
);
198 if(U_FAILURE(errorCode
)) {
205 UnicodeString::toLower() {
206 return caseMap(0, Locale::getDefault().getName(), 0, TO_LOWER
);
210 UnicodeString::toLower(const Locale
&locale
) {
211 return caseMap(0, locale
.getName(), 0, TO_LOWER
);
215 UnicodeString::toUpper() {
216 return caseMap(0, Locale::getDefault().getName(), 0, TO_UPPER
);
220 UnicodeString::toUpper(const Locale
&locale
) {
221 return caseMap(0, locale
.getName(), 0, TO_UPPER
);
224 #if !UCONFIG_NO_BREAK_ITERATION
227 UnicodeString::toTitle(BreakIterator
*titleIter
) {
228 return caseMap(titleIter
, Locale::getDefault().getName(), 0, TO_TITLE
);
232 UnicodeString::toTitle(BreakIterator
*titleIter
, const Locale
&locale
) {
233 return caseMap(titleIter
, locale
.getName(), 0, TO_TITLE
);
239 UnicodeString::foldCase(uint32_t options
) {
240 /* The Locale parameter isn't used. Use "" instead. */
241 return caseMap(0, "", options
, FOLD_CASE
);