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