]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/coll.cpp
ICU-511.25.tar.gz
[apple/icu.git] / icuSources / i18n / coll.cpp
CommitLineData
b75a7d8f 1/*
46f4442e 2 ******************************************************************************
4388f060 3 * Copyright (C) 1996-2012, International Business Machines Corporation and
729e4ab9 4 * others. All Rights Reserved.
46f4442e
A
5 ******************************************************************************
6 */
b75a7d8f
A
7
8/**
46f4442e
A
9 * File coll.cpp
10 *
11 * Created by: Helena Shih
12 *
13 * Modification History:
14 *
15 * Date Name Description
16 * 2/5/97 aliu Modified createDefault to load collation data from
17 * binary files when possible. Added related methods
18 * createCollationFromFile, chopLocale, createPathName.
19 * 2/11/97 aliu Added methods addToCache, findInCache, which implement
20 * a Collation cache. Modified createDefault to look in
21 * cache first, and also to store newly created Collation
22 * objects in the cache. Modified to not use gLocPath.
23 * 2/12/97 aliu Modified to create objects from RuleBasedCollator cache.
24 * Moved cache out of Collation class.
25 * 2/13/97 aliu Moved several methods out of this class and into
26 * RuleBasedCollator, with modifications. Modified
27 * createDefault() to call new RuleBasedCollator(Locale&)
28 * constructor. General clean up and documentation.
29 * 2/20/97 helena Added clone, operator==, operator!=, operator=, and copy
30 * constructor.
31 * 05/06/97 helena Added memory allocation error detection.
32 * 05/08/97 helena Added createInstance().
33 * 6/20/97 helena Java class name change.
34 * 04/23/99 stephen Removed EDecompositionMode, merged with
35 * Normalizer::EMode
36 * 11/23/9 srl Inlining of some critical functions
37 * 01/29/01 synwee Modified into a C++ wrapper calling C APIs (ucol.h)
38 */
b75a7d8f 39
51004dcb
A
40#include "utypeinfo.h" // for 'typeid' to work
41
b75a7d8f
A
42#include "unicode/utypes.h"
43
44#if !UCONFIG_NO_COLLATION
45
46#include "unicode/coll.h"
47#include "unicode/tblcoll.h"
374ca955 48#include "ucol_imp.h"
46f4442e 49#include "cstring.h"
b75a7d8f 50#include "cmemory.h"
46f4442e 51#include "umutex.h"
73c04bcf 52#include "servloc.h"
374ca955 53#include "ustrenum.h"
46f4442e 54#include "uresimp.h"
b75a7d8f
A
55#include "ucln_in.h"
56
4388f060 57static icu::Locale* availableLocaleList = NULL;
46f4442e 58static int32_t availableLocaleListCount;
4388f060 59static icu::ICULocaleService* gService = NULL;
374ca955 60
374ca955
A
61/**
62 * Release all static memory held by collator.
63 */
64U_CDECL_BEGIN
65static UBool U_CALLCONV collator_cleanup(void) {
46f4442e 66#if !UCONFIG_NO_SERVICE
374ca955
A
67 if (gService) {
68 delete gService;
69 gService = NULL;
70 }
46f4442e
A
71#endif
72 if (availableLocaleList) {
73 delete []availableLocaleList;
74 availableLocaleList = NULL;
75 }
76 availableLocaleListCount = 0;
77
374ca955
A
78 return TRUE;
79}
46f4442e 80
374ca955
A
81U_CDECL_END
82
b75a7d8f
A
83U_NAMESPACE_BEGIN
84
46f4442e
A
85#if !UCONFIG_NO_SERVICE
86
b75a7d8f
A
87// ------------------------------------------
88//
89// Registration
90//
91
92//-------------------------------------------
93
374ca955
A
94CollatorFactory::~CollatorFactory() {}
95
96//-------------------------------------------
97
b75a7d8f
A
98UBool
99CollatorFactory::visible(void) const {
374ca955 100 return TRUE;
b75a7d8f
A
101}
102
103//-------------------------------------------
104
105UnicodeString&
106CollatorFactory::getDisplayName(const Locale& objectLocale,
107 const Locale& displayLocale,
108 UnicodeString& result)
109{
110 return objectLocale.getDisplayName(displayLocale, result);
111}
112
113// -------------------------------------
114
115class ICUCollatorFactory : public ICUResourceBundleFactory {
374ca955 116 public:
4388f060
A
117 ICUCollatorFactory() : ICUResourceBundleFactory(UnicodeString(U_ICUDATA_COLL, -1, US_INV)) { }
118 virtual ~ICUCollatorFactory();
374ca955
A
119 protected:
120 virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const;
b75a7d8f
A
121};
122
4388f060
A
123ICUCollatorFactory::~ICUCollatorFactory() {}
124
b75a7d8f
A
125UObject*
126ICUCollatorFactory::create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const {
127 if (handlesKey(key, status)) {
128 const LocaleKey& lkey = (const LocaleKey&)key;
129 Locale loc;
130 // make sure the requested locale is correct
131 // default LocaleFactory uses currentLocale since that's the one vetted by handlesKey
132 // but for ICU rb resources we use the actual one since it will fallback again
133 lkey.canonicalLocale(loc);
374ca955 134
b75a7d8f
A
135 return Collator::makeInstance(loc, status);
136 }
137 return NULL;
138}
139
140// -------------------------------------
141
142class ICUCollatorService : public ICULocaleService {
374ca955 143public:
b75a7d8f 144 ICUCollatorService()
73c04bcf 145 : ICULocaleService(UNICODE_STRING_SIMPLE("Collator"))
b75a7d8f
A
146 {
147 UErrorCode status = U_ZERO_ERROR;
148 registerFactory(new ICUCollatorFactory(), status);
149 }
4388f060
A
150
151 virtual ~ICUCollatorService();
152
b75a7d8f
A
153 virtual UObject* cloneInstance(UObject* instance) const {
154 return ((Collator*)instance)->clone();
155 }
374ca955 156
b75a7d8f
A
157 virtual UObject* handleDefault(const ICUServiceKey& key, UnicodeString* actualID, UErrorCode& status) const {
158 LocaleKey& lkey = (LocaleKey&)key;
374ca955
A
159 if (actualID) {
160 // Ugly Hack Alert! We return an empty actualID to signal
161 // to callers that this is a default object, not a "real"
162 // service-created object. (TODO remove in 3.0) [aliu]
163 actualID->truncate(0);
164 }
165 Locale loc("");
b75a7d8f
A
166 lkey.canonicalLocale(loc);
167 return Collator::makeInstance(loc, status);
168 }
374ca955
A
169
170 virtual UObject* getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode& status) const {
171 UnicodeString ar;
172 if (actualReturn == NULL) {
173 actualReturn = &ar;
174 }
175 Collator* result = (Collator*)ICULocaleService::getKey(key, actualReturn, status);
176 // Ugly Hack Alert! If the actualReturn length is zero, this
177 // means we got a default object, not a "real" service-created
178 // object. We don't call setLocales() on a default object,
179 // because that will overwrite its correct built-in locale
180 // metadata (valid & actual) with our incorrect data (all we
181 // have is the requested locale). (TODO remove in 3.0) [aliu]
182 if (result && actualReturn->length() > 0) {
183 const LocaleKey& lkey = (const LocaleKey&)key;
184 Locale canonicalLocale("");
185 Locale currentLocale("");
186
46f4442e
A
187 LocaleUtility::initLocaleFromName(*actualReturn, currentLocale);
188 result->setLocales(lkey.canonicalLocale(canonicalLocale), currentLocale, currentLocale);
374ca955
A
189 }
190 return result;
191 }
b75a7d8f
A
192
193 virtual UBool isDefault() const {
194 return countFactories() == 1;
195 }
196};
197
4388f060
A
198ICUCollatorService::~ICUCollatorService() {}
199
b75a7d8f
A
200// -------------------------------------
201
b75a7d8f
A
202static ICULocaleService*
203getService(void)
204{
374ca955 205 UBool needInit;
46f4442e 206 UMTX_CHECK(NULL, (UBool)(gService == NULL), needInit);
374ca955
A
207 if(needInit) {
208 ICULocaleService *newservice = new ICUCollatorService();
209 if(newservice) {
46f4442e 210 umtx_lock(NULL);
374ca955
A
211 if(gService == NULL) {
212 gService = newservice;
213 newservice = NULL;
214 }
46f4442e 215 umtx_unlock(NULL);
374ca955
A
216 }
217 if(newservice) {
218 delete newservice;
219 }
220 else {
374ca955 221 ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
374ca955 222 }
b75a7d8f 223 }
374ca955 224 return gService;
b75a7d8f
A
225}
226
227// -------------------------------------
228
46f4442e 229static inline UBool
b75a7d8f
A
230hasService(void)
231{
46f4442e
A
232 UBool retVal;
233 UMTX_CHECK(NULL, gService != NULL, retVal);
234 return retVal;
b75a7d8f
A
235}
236
237// -------------------------------------
238
239UCollator*
240Collator::createUCollator(const char *loc,
374ca955 241 UErrorCode *status)
b75a7d8f 242{
374ca955
A
243 UCollator *result = 0;
244 if (status && U_SUCCESS(*status) && hasService()) {
245 Locale desiredLocale(loc);
246 Collator *col = (Collator*)gService->get(desiredLocale, *status);
729e4ab9
A
247 RuleBasedCollator *rbc;
248 if (col && (rbc = dynamic_cast<RuleBasedCollator *>(col))) {
374ca955
A
249 if (!rbc->dataIsOwned) {
250 result = ucol_safeClone(rbc->ucollator, NULL, NULL, status);
251 } else {
252 result = rbc->ucollator;
253 rbc->ucollator = NULL; // to prevent free on delete
254 }
4388f060
A
255 } else {
256 // should go in a function- ucol_initDelegate(delegate)
257 result = (UCollator *)uprv_malloc(sizeof(UCollator));
258 if(result == NULL) {
259 *status = U_MEMORY_ALLOCATION_ERROR;
260 } else {
261 uprv_memset(result, 0, sizeof(UCollator));
262 result->delegate = col;
263 result->freeOnClose = TRUE; // do free on close.
264 col = NULL; // to prevent free on delete.
265 }
374ca955
A
266 }
267 delete col;
268 }
269 return result;
b75a7d8f 270}
374ca955 271#endif /* UCONFIG_NO_SERVICE */
b75a7d8f 272
46f4442e
A
273static UBool isAvailableLocaleListInitialized(UErrorCode &status) {
274 // for now, there is a hardcoded list, so just walk through that list and set it up.
275 UBool needInit;
276 UMTX_CHECK(NULL, availableLocaleList == NULL, needInit);
277
278 if (needInit) {
279 UResourceBundle *index = NULL;
280 UResourceBundle installed;
281 Locale * temp;
282 int32_t i = 0;
283 int32_t localeCount;
284
285 ures_initStackObject(&installed);
286 index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status);
287 ures_getByKey(index, "InstalledLocales", &installed, &status);
288
289 if(U_SUCCESS(status)) {
290 localeCount = ures_getSize(&installed);
291 temp = new Locale[localeCount];
292
293 if (temp != NULL) {
294 ures_resetIterator(&installed);
295 while(ures_hasNext(&installed)) {
296 const char *tempKey = NULL;
297 ures_getNextString(&installed, NULL, &tempKey, &status);
298 temp[i++] = Locale(tempKey);
299 }
300
301 umtx_lock(NULL);
302 if (availableLocaleList == NULL)
303 {
46f4442e 304 availableLocaleListCount = localeCount;
729e4ab9 305 availableLocaleList = temp;
46f4442e
A
306 temp = NULL;
307 ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
308 }
309 umtx_unlock(NULL);
310
311 needInit = FALSE;
312 if (temp) {
313 delete []temp;
314 }
315 }
316
317 ures_close(&installed);
318 }
319 ures_close(index);
320 }
321 return !needInit;
322}
323
b75a7d8f
A
324// Collator public methods -----------------------------------------------
325
374ca955 326Collator* U_EXPORT2 Collator::createInstance(UErrorCode& success)
b75a7d8f 327{
374ca955 328 return createInstance(Locale::getDefault(), success);
b75a7d8f
A
329}
330
374ca955 331Collator* U_EXPORT2 Collator::createInstance(const Locale& desiredLocale,
b75a7d8f
A
332 UErrorCode& status)
333{
374ca955
A
334 if (U_FAILURE(status))
335 return 0;
336
337#if !UCONFIG_NO_SERVICE
338 if (hasService()) {
339 Locale actualLoc;
340 Collator *result =
341 (Collator*)gService->get(desiredLocale, &actualLoc, status);
4388f060 342
374ca955
A
343 // Ugly Hack Alert! If the returned locale is empty (not root,
344 // but empty -- getName() == "") then that means the service
345 // returned a default object, not a "real" service object. In
346 // that case, the locale metadata (valid & actual) is setup
347 // correctly already, and we don't want to overwrite it. (TODO
348 // remove in 3.0) [aliu]
349 if (*actualLoc.getName() != 0) {
46f4442e 350 result->setLocales(desiredLocale, actualLoc, actualLoc);
374ca955
A
351 }
352 return result;
353 }
354#endif
355 return makeInstance(desiredLocale, status);
b75a7d8f
A
356}
357
358
359Collator* Collator::makeInstance(const Locale& desiredLocale,
360 UErrorCode& status)
361{
374ca955
A
362 // A bit of explanation is required here. Although in the current
363 // implementation
364 // Collator::createInstance() is just turning around and calling
365 // RuleBasedCollator(Locale&), this will not necessarily always be the
366 // case. For example, suppose we modify this code to handle a
367 // non-table-based Collator, such as that for Thai. In this case,
368 // createInstance() will have to be modified to somehow determine this fact
369 // (perhaps a field in the resource bundle). Then it can construct the
370 // non-table-based Collator in some other way, when it sees that it needs
371 // to.
372 // The specific caution is this: RuleBasedCollator(Locale&) will ALWAYS
46f4442e 373 // return a valid collation object, if the system is functioning properly.
374ca955
A
374 // The reason is that it will fall back, use the default locale, and even
375 // use the built-in default collation rules. THEREFORE, createInstance()
376 // should in general ONLY CALL RuleBasedCollator(Locale&) IF IT KNOWS IN
377 // ADVANCE that the given locale's collation is properly implemented as a
378 // RuleBasedCollator.
379 // Currently, we don't do this...we always return a RuleBasedCollator,
380 // whether it is strictly correct to do so or not, without checking, because
381 // we currently have no way of checking.
382
383 RuleBasedCollator* collation = new RuleBasedCollator(desiredLocale,
384 status);
385 /* test for NULL */
386 if (collation == 0) {
387 status = U_MEMORY_ALLOCATION_ERROR;
388 return 0;
389 }
390 if (U_FAILURE(status))
391 {
392 delete collation;
393 collation = 0;
394 }
395 return collation;
b75a7d8f
A
396}
397
374ca955 398#ifdef U_USE_COLLATION_OBSOLETE_2_6
b75a7d8f
A
399// !!! dlf the following is obsolete, ignore registration for this
400
401Collator *
402Collator::createInstance(const Locale &loc,
403 UVersionInfo version,
374ca955
A
404 UErrorCode &status)
405{
406 Collator *collator;
407 UVersionInfo info;
408
409 collator=new RuleBasedCollator(loc, status);
410 /* test for NULL */
411 if (collator == 0) {
412 status = U_MEMORY_ALLOCATION_ERROR;
413 return 0;
b75a7d8f 414 }
374ca955
A
415
416 if(U_SUCCESS(status)) {
417 collator->getVersion(info);
418 if(0!=uprv_memcmp(version, info, sizeof(UVersionInfo))) {
419 delete collator;
420 status=U_MISSING_RESOURCE_ERROR;
421 return 0;
422 }
423 }
424 return collator;
b75a7d8f 425}
374ca955 426#endif
b75a7d8f 427
51004dcb
A
428Collator *
429Collator::safeClone() const {
430 return clone();
431}
432
b75a7d8f
A
433// implement deprecated, previously abstract method
434Collator::EComparisonResult Collator::compare(const UnicodeString& source,
435 const UnicodeString& target) const
436{
374ca955 437 UErrorCode ec = U_ZERO_ERROR;
51004dcb 438 return (EComparisonResult)compare(source, target, ec);
b75a7d8f
A
439}
440
441// implement deprecated, previously abstract method
442Collator::EComparisonResult Collator::compare(const UnicodeString& source,
443 const UnicodeString& target,
444 int32_t length) const
445{
374ca955 446 UErrorCode ec = U_ZERO_ERROR;
51004dcb 447 return (EComparisonResult)compare(source, target, length, ec);
b75a7d8f
A
448}
449
450// implement deprecated, previously abstract method
451Collator::EComparisonResult Collator::compare(const UChar* source, int32_t sourceLength,
452 const UChar* target, int32_t targetLength)
453 const
454{
374ca955 455 UErrorCode ec = U_ZERO_ERROR;
51004dcb 456 return (EComparisonResult)compare(source, sourceLength, target, targetLength, ec);
b75a7d8f
A
457}
458
729e4ab9
A
459UCollationResult Collator::compare(UCharIterator &/*sIter*/,
460 UCharIterator &/*tIter*/,
461 UErrorCode &status) const {
462 if(U_SUCCESS(status)) {
463 // Not implemented in the base class.
464 status = U_UNSUPPORTED_ERROR;
465 }
466 return UCOL_EQUAL;
467}
468
469UCollationResult Collator::compareUTF8(const StringPiece &source,
470 const StringPiece &target,
471 UErrorCode &status) const {
472 if(U_FAILURE(status)) {
473 return UCOL_EQUAL;
474 }
475 UCharIterator sIter, tIter;
476 uiter_setUTF8(&sIter, source.data(), source.length());
477 uiter_setUTF8(&tIter, target.data(), target.length());
478 return compare(sIter, tIter, status);
479}
480
b75a7d8f 481UBool Collator::equals(const UnicodeString& source,
374ca955 482 const UnicodeString& target) const
b75a7d8f 483{
374ca955
A
484 UErrorCode ec = U_ZERO_ERROR;
485 return (compare(source, target, ec) == UCOL_EQUAL);
b75a7d8f
A
486}
487
488UBool Collator::greaterOrEqual(const UnicodeString& source,
374ca955 489 const UnicodeString& target) const
b75a7d8f 490{
374ca955
A
491 UErrorCode ec = U_ZERO_ERROR;
492 return (compare(source, target, ec) != UCOL_LESS);
b75a7d8f
A
493}
494
495UBool Collator::greater(const UnicodeString& source,
374ca955 496 const UnicodeString& target) const
b75a7d8f 497{
374ca955
A
498 UErrorCode ec = U_ZERO_ERROR;
499 return (compare(source, target, ec) == UCOL_GREATER);
b75a7d8f
A
500}
501
502// this API ignores registered collators, since it returns an
503// array of indefinite lifetime
374ca955 504const Locale* U_EXPORT2 Collator::getAvailableLocales(int32_t& count)
b75a7d8f 505{
46f4442e
A
506 UErrorCode status = U_ZERO_ERROR;
507 Locale *result = NULL;
508 count = 0;
509 if (isAvailableLocaleListInitialized(status))
510 {
511 result = availableLocaleList;
512 count = availableLocaleListCount;
513 }
514 return result;
b75a7d8f
A
515}
516
374ca955
A
517UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale,
518 const Locale& displayLocale,
519 UnicodeString& name)
b75a7d8f 520{
374ca955
A
521#if !UCONFIG_NO_SERVICE
522 if (hasService()) {
73c04bcf
A
523 UnicodeString locNameStr;
524 LocaleUtility::initNameFromLocale(objectLocale, locNameStr);
525 return gService->getDisplayName(locNameStr, name, displayLocale);
374ca955
A
526 }
527#endif
528 return objectLocale.getDisplayName(displayLocale, name);
b75a7d8f
A
529}
530
374ca955
A
531UnicodeString& U_EXPORT2 Collator::getDisplayName(const Locale& objectLocale,
532 UnicodeString& name)
b75a7d8f 533{
374ca955 534 return getDisplayName(objectLocale, Locale::getDefault(), name);
b75a7d8f
A
535}
536
537/* This is useless information */
538/*void Collator::getVersion(UVersionInfo versionInfo) const
539{
540 if (versionInfo!=NULL)
541 uprv_memcpy(versionInfo, fVersion, U_MAX_VERSION_LENGTH);
542}
543*/
544
545// UCollator protected constructor destructor ----------------------------
546
547/**
548* Default constructor.
549* Constructor is different from the old default Collator constructor.
550* The task for determing the default collation strength and normalization mode
551* is left to the child class.
552*/
553Collator::Collator()
374ca955 554: UObject()
b75a7d8f
A
555{
556}
557
558/**
559* Constructor.
560* Empty constructor, does not handle the arguments.
561* This constructor is done for backward compatibility with 1.7 and 1.8.
562* The task for handling the argument collation strength and normalization
563* mode is left to the child class.
564* @param collationStrength collation strength
565* @param decompositionMode
566* @deprecated 2.4 use the default constructor instead
567*/
568Collator::Collator(UCollationStrength, UNormalizationMode )
374ca955 569: UObject()
b75a7d8f
A
570{
571}
572
573Collator::~Collator()
574{
575}
576
577Collator::Collator(const Collator &other)
578 : UObject(other)
579{
580}
581
374ca955
A
582UBool Collator::operator==(const Collator& other) const
583{
51004dcb
A
584 // Subclasses: Call this method and then add more specific checks.
585 return typeid(*this) == typeid(other);
374ca955
A
586}
587
588UBool Collator::operator!=(const Collator& other) const
589{
590 return (UBool)!(*this == other);
591}
592
593int32_t U_EXPORT2 Collator::getBound(const uint8_t *source,
594 int32_t sourceLength,
595 UColBoundMode boundType,
596 uint32_t noOfLevels,
597 uint8_t *result,
598 int32_t resultLength,
599 UErrorCode &status)
600{
601 return ucol_getBound(source, sourceLength, boundType, noOfLevels, result, resultLength, &status);
b75a7d8f
A
602}
603
604void
46f4442e 605Collator::setLocales(const Locale& /* requestedLocale */, const Locale& /* validLocale */, const Locale& /*actualLocale*/) {
b75a7d8f
A
606}
607
374ca955
A
608UnicodeSet *Collator::getTailoredSet(UErrorCode &status) const
609{
610 if(U_FAILURE(status)) {
611 return NULL;
612 }
613 // everything can be changed
614 return new UnicodeSet(0, 0x10FFFF);
615}
616
b75a7d8f
A
617// -------------------------------------
618
374ca955
A
619#if !UCONFIG_NO_SERVICE
620URegistryKey U_EXPORT2
b75a7d8f
A
621Collator::registerInstance(Collator* toAdopt, const Locale& locale, UErrorCode& status)
622{
623 if (U_SUCCESS(status)) {
624 return getService()->registerInstance(toAdopt, locale, status);
625 }
626 return NULL;
627}
628
629// -------------------------------------
630
631class CFactory : public LocaleKeyFactory {
632private:
633 CollatorFactory* _delegate;
634 Hashtable* _ids;
374ca955 635
b75a7d8f
A
636public:
637 CFactory(CollatorFactory* delegate, UErrorCode& status)
638 : LocaleKeyFactory(delegate->visible() ? VISIBLE : INVISIBLE)
639 , _delegate(delegate)
640 , _ids(NULL)
641 {
374ca955
A
642 if (U_SUCCESS(status)) {
643 int32_t count = 0;
644 _ids = new Hashtable(status);
645 if (_ids) {
646 const UnicodeString * idlist = _delegate->getSupportedIDs(count, status);
647 for (int i = 0; i < count; ++i) {
648 _ids->put(idlist[i], (void*)this, status);
649 if (U_FAILURE(status)) {
650 delete _ids;
651 _ids = NULL;
652 return;
653 }
654 }
655 } else {
656 status = U_MEMORY_ALLOCATION_ERROR;
657 }
b75a7d8f
A
658 }
659 }
4388f060
A
660
661 virtual ~CFactory();
662
b75a7d8f 663 virtual UObject* create(const ICUServiceKey& key, const ICUService* service, UErrorCode& status) const;
374ca955
A
664
665protected:
b75a7d8f
A
666 virtual const Hashtable* getSupportedIDs(UErrorCode& status) const
667 {
668 if (U_SUCCESS(status)) {
669 return _ids;
670 }
671 return NULL;
672 }
374ca955 673
b75a7d8f
A
674 virtual UnicodeString&
675 getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const;
676};
677
4388f060
A
678CFactory::~CFactory()
679{
680 delete _delegate;
681 delete _ids;
682}
683
b75a7d8f
A
684UObject*
685CFactory::create(const ICUServiceKey& key, const ICUService* /* service */, UErrorCode& status) const
686{
687 if (handlesKey(key, status)) {
688 const LocaleKey& lkey = (const LocaleKey&)key;
689 Locale validLoc;
690 lkey.currentLocale(validLoc);
374ca955 691 return _delegate->createCollator(validLoc);
b75a7d8f
A
692 }
693 return NULL;
694}
695
696UnicodeString&
697CFactory::getDisplayName(const UnicodeString& id, const Locale& locale, UnicodeString& result) const
698{
699 if ((_coverage & 0x1) == 0) {
700 UErrorCode status = U_ZERO_ERROR;
701 const Hashtable* ids = getSupportedIDs(status);
702 if (ids && (ids->get(id) != NULL)) {
703 Locale loc;
704 LocaleUtility::initLocaleFromName(id, loc);
705 return _delegate->getDisplayName(loc, locale, result);
706 }
707 }
708 result.setToBogus();
709 return result;
710}
711
374ca955 712URegistryKey U_EXPORT2
b75a7d8f
A
713Collator::registerFactory(CollatorFactory* toAdopt, UErrorCode& status)
714{
715 if (U_SUCCESS(status)) {
716 CFactory* f = new CFactory(toAdopt, status);
717 if (f) {
718 return getService()->registerFactory(f, status);
719 }
720 status = U_MEMORY_ALLOCATION_ERROR;
721 }
722 return NULL;
723}
724
725// -------------------------------------
726
374ca955 727UBool U_EXPORT2
b75a7d8f
A
728Collator::unregister(URegistryKey key, UErrorCode& status)
729{
374ca955
A
730 if (U_SUCCESS(status)) {
731 if (hasService()) {
732 return gService->unregister(key, status);
733 }
734 status = U_ILLEGAL_ARGUMENT_ERROR;
b75a7d8f 735 }
374ca955 736 return FALSE;
b75a7d8f 737}
46f4442e
A
738#endif /* UCONFIG_NO_SERVICE */
739
740class CollationLocaleListEnumeration : public StringEnumeration {
741private:
742 int32_t index;
743public:
744 static UClassID U_EXPORT2 getStaticClassID(void);
745 virtual UClassID getDynamicClassID(void) const;
746public:
747 CollationLocaleListEnumeration()
748 : index(0)
749 {
750 // The global variables should already be initialized.
751 //isAvailableLocaleListInitialized(status);
752 }
753
4388f060 754 virtual ~CollationLocaleListEnumeration();
46f4442e
A
755
756 virtual StringEnumeration * clone() const
757 {
758 CollationLocaleListEnumeration *result = new CollationLocaleListEnumeration();
759 if (result) {
760 result->index = index;
761 }
762 return result;
763 }
764
765 virtual int32_t count(UErrorCode &/*status*/) const {
766 return availableLocaleListCount;
767 }
768
769 virtual const char* next(int32_t* resultLength, UErrorCode& /*status*/) {
770 const char* result;
771 if(index < availableLocaleListCount) {
772 result = availableLocaleList[index++].getName();
773 if(resultLength != NULL) {
729e4ab9 774 *resultLength = (int32_t)uprv_strlen(result);
46f4442e
A
775 }
776 } else {
777 if(resultLength != NULL) {
778 *resultLength = 0;
779 }
780 result = NULL;
781 }
782 return result;
783 }
784
785 virtual const UnicodeString* snext(UErrorCode& status) {
786 int32_t resultLength = 0;
787 const char *s = next(&resultLength, status);
788 return setChars(s, resultLength, status);
789 }
790
791 virtual void reset(UErrorCode& /*status*/) {
792 index = 0;
793 }
794};
795
4388f060
A
796CollationLocaleListEnumeration::~CollationLocaleListEnumeration() {}
797
46f4442e
A
798UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CollationLocaleListEnumeration)
799
b75a7d8f
A
800
801// -------------------------------------
802
374ca955 803StringEnumeration* U_EXPORT2
b75a7d8f
A
804Collator::getAvailableLocales(void)
805{
46f4442e
A
806#if !UCONFIG_NO_SERVICE
807 if (hasService()) {
808 return getService()->getAvailableLocales();
809 }
374ca955 810#endif /* UCONFIG_NO_SERVICE */
46f4442e
A
811 UErrorCode status = U_ZERO_ERROR;
812 if (isAvailableLocaleListInitialized(status)) {
813 return new CollationLocaleListEnumeration();
814 }
815 return NULL;
816}
374ca955
A
817
818StringEnumeration* U_EXPORT2
819Collator::getKeywords(UErrorCode& status) {
820 // This is a wrapper over ucol_getKeywords
821 UEnumeration* uenum = ucol_getKeywords(&status);
822 if (U_FAILURE(status)) {
823 uenum_close(uenum);
824 return NULL;
825 }
826 return new UStringEnumeration(uenum);
827}
828
829StringEnumeration* U_EXPORT2
830Collator::getKeywordValues(const char *keyword, UErrorCode& status) {
831 // This is a wrapper over ucol_getKeywordValues
832 UEnumeration* uenum = ucol_getKeywordValues(keyword, &status);
833 if (U_FAILURE(status)) {
834 uenum_close(uenum);
835 return NULL;
836 }
837 return new UStringEnumeration(uenum);
838}
839
729e4ab9
A
840StringEnumeration* U_EXPORT2
841Collator::getKeywordValuesForLocale(const char* key, const Locale& locale,
842 UBool commonlyUsed, UErrorCode& status) {
843 // This is a wrapper over ucol_getKeywordValuesForLocale
844 UEnumeration *uenum = ucol_getKeywordValuesForLocale(key, locale.getName(),
845 commonlyUsed, &status);
846 if (U_FAILURE(status)) {
847 uenum_close(uenum);
848 return NULL;
849 }
850 return new UStringEnumeration(uenum);
851}
852
374ca955
A
853Locale U_EXPORT2
854Collator::getFunctionalEquivalent(const char* keyword, const Locale& locale,
855 UBool& isAvailable, UErrorCode& status) {
856 // This is a wrapper over ucol_getFunctionalEquivalent
857 char loc[ULOC_FULLNAME_CAPACITY];
858 /*int32_t len =*/ ucol_getFunctionalEquivalent(loc, sizeof(loc),
859 keyword, locale.getName(), &isAvailable, &status);
860 if (U_FAILURE(status)) {
861 *loc = 0; // root
862 }
863 return Locale::createFromName(loc);
b75a7d8f
A
864}
865
51004dcb
A
866Collator::ECollationStrength
867Collator::getStrength(void) const {
868 UErrorCode intStatus = U_ZERO_ERROR;
869 return (ECollationStrength)getAttribute(UCOL_STRENGTH, intStatus);
870}
871
872void
873Collator::setStrength(ECollationStrength newStrength) {
874 UErrorCode intStatus = U_ZERO_ERROR;
875 setAttribute(UCOL_STRENGTH, (UColAttributeValue)newStrength, intStatus);
876}
877
878int32_t
4388f060
A
879Collator::getReorderCodes(int32_t* /* dest*/,
880 int32_t /* destCapacity*/,
881 UErrorCode& status) const
729e4ab9
A
882{
883 if (U_SUCCESS(status)) {
884 status = U_UNSUPPORTED_ERROR;
885 }
886 return 0;
887}
888
51004dcb 889void
4388f060
A
890Collator::setReorderCodes(const int32_t* /* reorderCodes */,
891 int32_t /* reorderCodesLength */,
892 UErrorCode& status)
729e4ab9
A
893{
894 if (U_SUCCESS(status)) {
895 status = U_UNSUPPORTED_ERROR;
896 }
897}
898
4388f060
A
899int32_t U_EXPORT2
900Collator::getEquivalentReorderCodes(int32_t /* reorderCode */,
901 int32_t* /* dest */,
902 int32_t /* destCapacity */,
903 UErrorCode& status)
904{
905 if (U_SUCCESS(status)) {
906 status = U_UNSUPPORTED_ERROR;
907 }
908 return 0;
909}
910
911int32_t
912Collator::internalGetShortDefinitionString(const char * /*locale*/,
913 char * /*buffer*/,
914 int32_t /*capacity*/,
915 UErrorCode &status) const {
916 if(U_SUCCESS(status)) {
917 status = U_UNSUPPORTED_ERROR; /* Shouldn't happen, internal function */
918 }
919 return 0;
920}
921
b75a7d8f
A
922// UCollator private data members ----------------------------------------
923
924/* This is useless information */
925/*const UVersionInfo Collator::fVersion = {1, 1, 0, 0};*/
926
927// -------------------------------------
928
929U_NAMESPACE_END
930
b75a7d8f
A
931#endif /* #if !UCONFIG_NO_COLLATION */
932
933/* eof */