]>
git.saurik.com Git - apple/icu.git/blob - icuSources/common/unistr_case.cpp
2 *******************************************************************************
4 * Copyright (C) 1999-2011, 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"
23 #include "unicode/ustring.h"
24 #include "unicode/unistr.h"
25 #include "unicode/uchar.h"
31 //========================================
32 // Read-only implementation
33 //========================================
36 UnicodeString::doCaseCompare(int32_t start
,
38 const UChar
*srcChars
,
41 uint32_t options
) const
43 // compare illegal string values
44 // treat const UChar *srcChars==NULL as an empty string
49 // pin indices to legal values
50 pinIndices(start
, length
);
52 if(srcChars
== NULL
) {
53 srcStart
= srcLength
= 0;
56 // get the correct pointer
57 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 UnicodeString::caseMap(const UCaseMap
*csm
,
89 UStringCaseMapper
*stringCaseMapper
) {
90 if(isEmpty() || !isWritable()) {
95 // We need to allocate a new buffer for the internal string case mapping function.
96 // This is very similar to how doReplace() keeps the old array pointer
97 // and deletes the old array itself after it is done.
98 // In addition, we are forcing cloneArrayIfNeeded() to always allocate a new array.
99 UChar oldStackBuffer
[US_STACKBUF_SIZE
];
103 if(fFlags
&kUsingStackBuffer
) {
104 // copy the stack buffer contents because it will be overwritten
105 u_memcpy(oldStackBuffer
, fUnion
.fStackBuffer
, fShortLength
);
106 oldArray
= oldStackBuffer
;
107 oldLength
= fShortLength
;
109 oldArray
= getArrayStart();
110 oldLength
= length();
114 if(oldLength
<= US_STACKBUF_SIZE
) {
115 capacity
= US_STACKBUF_SIZE
;
117 capacity
= oldLength
+ 20;
119 int32_t *bufferToDelete
= 0;
120 if(!cloneArrayIfNeeded(capacity
, capacity
, FALSE
, &bufferToDelete
, TRUE
)) {
124 // Case-map, and if the result is too long, then reallocate and repeat.
125 UErrorCode errorCode
;
128 errorCode
= U_ZERO_ERROR
;
129 newLength
= stringCaseMapper(csm
, getArrayStart(), getCapacity(),
130 oldArray
, oldLength
, &errorCode
);
131 setLength(newLength
);
132 } while(errorCode
==U_BUFFER_OVERFLOW_ERROR
&& cloneArrayIfNeeded(newLength
, newLength
, FALSE
));
134 if (bufferToDelete
) {
135 uprv_free(bufferToDelete
);
137 if(U_FAILURE(errorCode
)) {
144 UnicodeString::foldCase(uint32_t options
) {
145 UCaseMap csm
=UCASEMAP_INITIALIZER
;
146 csm
.csp
=ucase_getSingleton();
148 return caseMap(&csm
, ustrcase_internalFold
);
153 // Defined here to reduce dependencies on break iterator
154 U_CAPI
int32_t U_EXPORT2
155 uhash_hashCaselessUnicodeString(const UElement key
) {
157 const UnicodeString
*str
= (const UnicodeString
*) key
.pointer
;
161 // Inefficient; a better way would be to have a hash function in
162 // UnicodeString that does case folding on the fly.
163 UnicodeString
copy(*str
);
164 return copy
.foldCase().hashCode();
167 // Defined here to reduce dependencies on break iterator
168 U_CAPI UBool U_EXPORT2
169 uhash_compareCaselessUnicodeString(const UElement key1
, const UElement key2
) {
171 const UnicodeString
*str1
= (const UnicodeString
*) key1
.pointer
;
172 const UnicodeString
*str2
= (const UnicodeString
*) key2
.pointer
;
176 if (str1
== NULL
|| str2
== NULL
) {
179 return str1
->caseCompare(*str2
, U_FOLD_CASE_DEFAULT
) == 0;