2 * Copyright 2010-2011, Oliver Tappe, zooey@hirschkaefer.de.
3 * Distributed under the terms of the MIT License.
7 #include "ICUCollateData.h"
13 #include <unicode/unistr.h>
15 #include <AutoDeleter.h>
22 ICUCollateData::ICUCollateData(pthread_key_t tlsKey
)
30 ICUCollateData::~ICUCollateData()
37 ICUCollateData::SetTo(const Locale
& locale
, const char* posixLocaleName
)
39 status_t result
= inherited::SetTo(locale
, posixLocaleName
);
42 UErrorCode icuStatus
= U_ZERO_ERROR
;
44 fCollator
= Collator::createInstance(fLocale
, icuStatus
);
45 if (!U_SUCCESS(icuStatus
))
54 ICUCollateData::SetToPosix()
56 status_t result
= inherited::SetToPosix();
68 ICUCollateData::Strcoll(const char* a
, const char* b
, int& result
)
70 if (fCollator
== NULL
|| strcmp(fPosixLocaleName
, "POSIX") == 0) {
71 // handle POSIX here as the collator ICU uses for that (english) is
72 // incompatible in too many ways
73 result
= strcmp(a
, b
);
74 for (const char* aIter
= a
; *aIter
!= 0; ++aIter
) {
78 for (const char* bIter
= b
; *bIter
!= 0; ++bIter
) {
85 status_t status
= B_OK
;
86 UErrorCode icuStatus
= U_ZERO_ERROR
;
88 if (strcasecmp(fGivenCharset
, "utf-8") == 0) {
89 UCharIterator aIter
, bIter
;
90 uiter_setUTF8(&aIter
, a
, -1);
91 uiter_setUTF8(&bIter
, b
, -1);
93 result
= fCollator
->compare(aIter
, bIter
, icuStatus
);
95 UnicodeString unicodeA
;
96 UnicodeString unicodeB
;
98 if (_ToUnicodeString(a
, unicodeA
) != B_OK
99 || _ToUnicodeString(b
, unicodeB
) != B_OK
) {
100 status
= B_BAD_VALUE
;
103 result
= fCollator
->compare(unicodeA
, unicodeB
, icuStatus
);
106 if (!U_SUCCESS(icuStatus
))
107 status
= B_BAD_VALUE
;
114 ICUCollateData::Strxfrm(char* out
, const char* in
, size_t size
, size_t& outSize
)
116 if (fCollator
== NULL
|| strcmp(fPosixLocaleName
, "POSIX") == 0) {
117 // handle POSIX here as the collator ICU uses for that (english) is
118 // incompatible in too many ways
119 outSize
= strlcpy(out
, in
, size
);
120 for (const char* inIter
= in
; *inIter
!= 0; ++inIter
) {
132 UnicodeString unicodeIn
;
133 if (_ToUnicodeString(in
, unicodeIn
) != B_OK
)
136 outSize
= fCollator
->getSortKey(unicodeIn
, (uint8_t*)out
, size
);
143 ICUCollateData::Wcscoll(const wchar_t* a
, const wchar_t* b
, int& result
)
145 if (fCollator
== NULL
|| strcmp(fPosixLocaleName
, "POSIX") == 0) {
146 // handle POSIX here as the collator ICU uses for that (english) is
147 // incompatible in too many ways
148 result
= wcscmp(a
, b
);
149 for (const wchar_t* aIter
= a
; *aIter
!= 0; ++aIter
) {
153 for (const wchar_t* bIter
= b
; *bIter
!= 0; ++bIter
) {
160 UnicodeString unicodeA
= UnicodeString::fromUTF32((UChar32
*)a
, -1);
161 UnicodeString unicodeB
= UnicodeString::fromUTF32((UChar32
*)b
, -1);
163 UErrorCode icuStatus
= U_ZERO_ERROR
;
164 result
= fCollator
->compare(unicodeA
, unicodeB
, icuStatus
);
166 if (!U_SUCCESS(icuStatus
))
174 ICUCollateData::Wcsxfrm(wchar_t* out
, const wchar_t* in
, size_t size
,
182 if (fCollator
== NULL
|| strcmp(fPosixLocaleName
, "POSIX") == 0) {
183 // handle POSIX here as the collator ICU uses for that (english) is
184 // incompatible in too many ways
185 outSize
= wcslcpy(out
, in
, size
);
186 for (const wchar_t* inIter
= in
; *inIter
!= 0; ++inIter
) {
193 UnicodeString unicodeIn
= UnicodeString::fromUTF32((UChar32
*)in
, -1);
194 size_t requiredSize
= fCollator
->getSortKey(unicodeIn
, NULL
, 0);
196 uint8_t* buffer
= (uint8_t*)out
;
197 outSize
= fCollator
->getSortKey(unicodeIn
, buffer
, requiredSize
);
199 // convert 1-byte characters to 4-byte wide characters:
200 for (size_t i
= 0; i
< outSize
; ++i
)
201 out
[outSize
- 1 - i
] = buffer
[outSize
- 1 - i
];
208 ICUCollateData::_ToUnicodeString(const char* in
, UnicodeString
& out
)
215 size_t inLen
= strlen(in
);
219 UConverter
* converter
;
220 status_t result
= _GetConverter(converter
);
224 UErrorCode icuStatus
= U_ZERO_ERROR
;
225 int32_t outLen
= ucnv_toUChars(converter
, NULL
, 0, in
, inLen
, &icuStatus
);
226 if (icuStatus
!= U_BUFFER_OVERFLOW_ERROR
)
233 UChar
* outBuf
= out
.getBuffer(outLen
+ 1);
234 icuStatus
= U_ZERO_ERROR
;
236 = ucnv_toUChars(converter
, outBuf
, outLen
+ 1, in
, inLen
, &icuStatus
);
237 if (!U_SUCCESS(icuStatus
)) {
238 out
.releaseBuffer(0);
242 out
.releaseBuffer(outLen
);
248 } // namespace Libroot
249 } // namespace BPrivate