]>
git.saurik.com Git - apple/icu.git/blob - icuSources/common/unistr_case.cpp
2 *******************************************************************************
4 * Copyright (C) 1999-2007, 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"
34 //========================================
35 // Read-only implementation
36 //========================================
39 UnicodeString::doCaseCompare(int32_t start
,
41 const UChar
*srcChars
,
44 uint32_t options
) const
46 // compare illegal string values
47 // treat const UChar *srcChars==NULL as an empty string
52 // pin indices to legal values
53 pinIndices(start
, length
);
55 if(srcChars
== NULL
) {
56 srcStart
= srcLength
= 0;
59 // get the correct pointer
60 const UChar
*chars
= getArrayStart();
65 if(chars
!= srcChars
) {
66 UErrorCode errorCode
=U_ZERO_ERROR
;
67 int32_t result
=u_strcmpFold(chars
, length
, srcChars
, srcLength
,
68 options
|U_COMPARE_IGNORE_CASE
, &errorCode
);
70 return (int8_t)(result
>> 24 | 1);
73 // get the srcLength if necessary
75 srcLength
= u_strlen(srcChars
+ srcStart
);
77 if(length
!= srcLength
) {
78 return (int8_t)((length
- srcLength
) >> 24 | 1);
84 //========================================
85 // Write implementation
86 //========================================
89 * Implement argument checking and buffer handling
90 * for string case mapping as a common function.
94 UnicodeString::caseMap(BreakIterator
*titleIter
,
97 int32_t toWhichCase
) {
98 if(isEmpty() || !isWritable()) {
103 UErrorCode errorCode
;
105 errorCode
= U_ZERO_ERROR
;
106 const UCaseProps
*csp
=ucase_getSingleton(&errorCode
);
107 if(U_FAILURE(errorCode
)) {
112 // We need to allocate a new buffer for the internal string case mapping function.
113 // This is very similar to how doReplace() keeps the old array pointer
114 // and deletes the old array itself after it is done.
115 // In addition, we are forcing cloneArrayIfNeeded() to always allocate a new array.
116 UChar oldStackBuffer
[US_STACKBUF_SIZE
];
120 if(fFlags
&kUsingStackBuffer
) {
121 // copy the stack buffer contents because it will be overwritten
122 u_memcpy(oldStackBuffer
, fUnion
.fStackBuffer
, fShortLength
);
123 oldArray
= oldStackBuffer
;
124 oldLength
= fShortLength
;
126 oldArray
= getArrayStart();
127 oldLength
= length();
131 if(oldLength
<= US_STACKBUF_SIZE
) {
132 capacity
= US_STACKBUF_SIZE
;
134 capacity
= oldLength
+ 20;
136 int32_t *bufferToDelete
= 0;
137 if(!cloneArrayIfNeeded(capacity
, capacity
, FALSE
, &bufferToDelete
, TRUE
)) {
141 // Case-map, and if the result is too long, then reallocate and repeat.
144 errorCode
= U_ZERO_ERROR
;
145 if(toWhichCase
==TO_LOWER
) {
146 newLength
= ustr_toLower(csp
, getArrayStart(), getCapacity(),
149 } else if(toWhichCase
==TO_UPPER
) {
150 newLength
= ustr_toUpper(csp
, getArrayStart(), getCapacity(),
153 } else if(toWhichCase
==TO_TITLE
) {
154 #if UCONFIG_NO_BREAK_ITERATION
155 errorCode
=U_UNSUPPORTED_ERROR
;
157 newLength
= ustr_toTitle(csp
, getArrayStart(), getCapacity(),
159 (UBreakIterator
*)titleIter
, locale
, options
, &errorCode
);
162 newLength
= ustr_foldCase(csp
, getArrayStart(), getCapacity(),
167 setLength(newLength
);
168 } while(errorCode
==U_BUFFER_OVERFLOW_ERROR
&& cloneArrayIfNeeded(newLength
, newLength
, FALSE
));
170 if (bufferToDelete
) {
171 uprv_free(bufferToDelete
);
173 if(U_FAILURE(errorCode
)) {
180 UnicodeString::toLower() {
181 return caseMap(0, Locale::getDefault().getName(), 0, TO_LOWER
);
185 UnicodeString::toLower(const Locale
&locale
) {
186 return caseMap(0, locale
.getName(), 0, TO_LOWER
);
190 UnicodeString::toUpper() {
191 return caseMap(0, Locale::getDefault().getName(), 0, TO_UPPER
);
195 UnicodeString::toUpper(const Locale
&locale
) {
196 return caseMap(0, locale
.getName(), 0, TO_UPPER
);
199 #if !UCONFIG_NO_BREAK_ITERATION
202 UnicodeString::toTitle(BreakIterator
*titleIter
) {
203 return caseMap(titleIter
, Locale::getDefault().getName(), 0, TO_TITLE
);
207 UnicodeString::toTitle(BreakIterator
*titleIter
, const Locale
&locale
) {
208 return caseMap(titleIter
, locale
.getName(), 0, TO_TITLE
);
212 UnicodeString::toTitle(BreakIterator
*titleIter
, const Locale
&locale
, uint32_t options
) {
213 return caseMap(titleIter
, locale
.getName(), options
, TO_TITLE
);
219 UnicodeString::foldCase(uint32_t options
) {
220 /* The Locale parameter isn't used. Use "" instead. */
221 return caseMap(0, "", options
, FOLD_CASE
);
226 // Defined here to reduce dependencies on break iterator
227 U_CAPI
int32_t U_EXPORT2
228 uhash_hashCaselessUnicodeString(const UHashTok key
) {
230 const UnicodeString
*str
= (const UnicodeString
*) key
.pointer
;
234 // Inefficient; a better way would be to have a hash function in
235 // UnicodeString that does case folding on the fly.
236 UnicodeString
copy(*str
);
237 return copy
.foldCase().hashCode();
240 // Defined here to reduce dependencies on break iterator
241 U_CAPI UBool U_EXPORT2
242 uhash_compareCaselessUnicodeString(const UHashTok key1
, const UHashTok key2
) {
244 const UnicodeString
*str1
= (const UnicodeString
*) key1
.pointer
;
245 const UnicodeString
*str2
= (const UnicodeString
*) key2
.pointer
;
249 if (str1
== NULL
|| str2
== NULL
) {
252 return str1
->caseCompare(*str2
, U_FOLD_CASE_DEFAULT
) == 0;