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