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