• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  ******************************************************************************
3  * Copyright (C) 1996-2012, International Business Machines Corporation and
4  * others. All Rights Reserved.
5  ******************************************************************************
6  */
7 
8 /**
9  * File tblcoll.cpp
10  *
11  * Created by: Helena Shih
12  *
13  * Modification History:
14  *
15  *  Date        Name        Description
16  *  2/5/97      aliu        Added streamIn and streamOut methods.  Added
17  *                          constructor which reads RuleBasedCollator object from
18  *                          a binary file.  Added writeToFile method which streams
19  *                          RuleBasedCollator out to a binary file.  The streamIn
20  *                          and streamOut methods use istream and ostream objects
21  *                          in binary mode.
22  *  2/11/97     aliu        Moved declarations out of for loop initializer.
23  *                          Added Mac compatibility #ifdef for ios::nocreate.
24  *  2/12/97     aliu        Modified to use TableCollationData sub-object to
25  *                          hold invariant data.
26  *  2/13/97     aliu        Moved several methods into this class from Collation.
27  *                          Added a private RuleBasedCollator(Locale&) constructor,
28  *                          to be used by Collator::getInstance().  General
29  *                          clean up.  Made use of UErrorCode variables consistent.
30  *  2/20/97     helena      Added clone, operator==, operator!=, operator=, and copy
31  *                          constructor and getDynamicClassID.
32  *  3/5/97      aliu        Changed compaction cycle to improve performance.  We
33  *                          use the maximum allowable value which is kBlockCount.
34  *                          Modified getRules() to load rules dynamically.  Changed
35  *                          constructFromFile() call to accomodate this (added
36  *                          parameter to specify whether binary loading is to
37  *                          take place).
38  * 05/06/97     helena      Added memory allocation error check.
39  *  6/20/97     helena      Java class name change.
40  *  6/23/97     helena      Adding comments to make code more readable.
41  * 09/03/97     helena      Added createCollationKeyValues().
42  * 06/26/98     erm         Changes for CollationKeys using byte arrays.
43  * 08/10/98     erm         Synched with 1.2 version of RuleBasedCollator.java
44  * 04/23/99     stephen     Removed EDecompositionMode, merged with
45  *                          Normalizer::EMode
46  * 06/14/99     stephen     Removed kResourceBundleSuffix
47  * 06/22/99     stephen     Fixed logic in constructFromFile() since .ctx
48  *                          files are no longer used.
49  * 11/02/99     helena      Collator performance enhancements.  Special case
50  *                          for NO_OP situations.
51  * 11/17/99     srl         More performance enhancements. Inlined some internal functions.
52  * 12/15/99     aliu        Update to support Thai collation.  Move NormalizerIterator
53  *                          to implementation file.
54  * 01/29/01     synwee      Modified into a C++ wrapper calling C APIs (ucol.h)
55  */
56 
57 #include "unicode/utypes.h"
58 
59 #if !UCONFIG_NO_COLLATION
60 
61 #include "unicode/tblcoll.h"
62 #include "unicode/coleitr.h"
63 #include "unicode/ures.h"
64 #include "unicode/uset.h"
65 #include "ucol_imp.h"
66 #include "uresimp.h"
67 #include "uhash.h"
68 #include "cmemory.h"
69 #include "cstring.h"
70 #include "putilimp.h"
71 #include "ustr_imp.h"
72 
73 /* public RuleBasedCollator constructor ---------------------------------- */
74 
75 U_NAMESPACE_BEGIN
76 
77 /**
78 * Copy constructor, aliasing, not write-through
79 */
RuleBasedCollator(const RuleBasedCollator & that)80 RuleBasedCollator::RuleBasedCollator(const RuleBasedCollator& that)
81 : Collator(that)
82 , dataIsOwned(FALSE)
83 , isWriteThroughAlias(FALSE)
84 , ucollator(NULL)
85 {
86     RuleBasedCollator::operator=(that);
87 }
88 
RuleBasedCollator(const UnicodeString & rules,UErrorCode & status)89 RuleBasedCollator::RuleBasedCollator(const UnicodeString& rules,
90                                      UErrorCode& status) :
91 dataIsOwned(FALSE)
92 {
93     construct(rules,
94         UCOL_DEFAULT_STRENGTH,
95         UCOL_DEFAULT,
96         status);
97 }
98 
RuleBasedCollator(const UnicodeString & rules,ECollationStrength collationStrength,UErrorCode & status)99 RuleBasedCollator::RuleBasedCollator(const UnicodeString& rules,
100                                      ECollationStrength collationStrength,
101                                      UErrorCode& status) : dataIsOwned(FALSE)
102 {
103     construct(rules,
104         (UColAttributeValue)collationStrength,
105         UCOL_DEFAULT,
106         status);
107 }
108 
RuleBasedCollator(const UnicodeString & rules,UColAttributeValue decompositionMode,UErrorCode & status)109 RuleBasedCollator::RuleBasedCollator(const UnicodeString& rules,
110                                      UColAttributeValue decompositionMode,
111                                      UErrorCode& status) :
112 dataIsOwned(FALSE)
113 {
114     construct(rules,
115         UCOL_DEFAULT_STRENGTH,
116         decompositionMode,
117         status);
118 }
119 
RuleBasedCollator(const UnicodeString & rules,ECollationStrength collationStrength,UColAttributeValue decompositionMode,UErrorCode & status)120 RuleBasedCollator::RuleBasedCollator(const UnicodeString& rules,
121                                      ECollationStrength collationStrength,
122                                      UColAttributeValue decompositionMode,
123                                      UErrorCode& status) : dataIsOwned(FALSE)
124 {
125     construct(rules,
126         (UColAttributeValue)collationStrength,
127         decompositionMode,
128         status);
129 }
RuleBasedCollator(const uint8_t * bin,int32_t length,const RuleBasedCollator * base,UErrorCode & status)130 RuleBasedCollator::RuleBasedCollator(const uint8_t *bin, int32_t length,
131                     const RuleBasedCollator *base,
132                     UErrorCode &status) :
133 dataIsOwned(TRUE),
134 isWriteThroughAlias(FALSE)
135 {
136   ucollator = ucol_openBinary(bin, length, base->ucollator, &status);
137 }
138 
139 void
setRuleStringFromCollator()140 RuleBasedCollator::setRuleStringFromCollator()
141 {
142     int32_t length;
143     const UChar *r = ucol_getRules(ucollator, &length);
144 
145     if (r && length > 0) {
146         // alias the rules string
147         urulestring.setTo(TRUE, r, length);
148     }
149     else {
150         urulestring.truncate(0); // Clear string.
151     }
152 }
153 
154 // not aliasing, not write-through
155 void
construct(const UnicodeString & rules,UColAttributeValue collationStrength,UColAttributeValue decompositionMode,UErrorCode & status)156 RuleBasedCollator::construct(const UnicodeString& rules,
157                              UColAttributeValue collationStrength,
158                              UColAttributeValue decompositionMode,
159                              UErrorCode& status)
160 {
161     ucollator = ucol_openRules(rules.getBuffer(), rules.length(),
162         decompositionMode, collationStrength,
163         NULL, &status);
164 
165     dataIsOwned = TRUE; // since we own a collator now, we need to get rid of it
166     isWriteThroughAlias = FALSE;
167 
168     if(ucollator == NULL) {
169         if(U_SUCCESS(status)) {
170             status = U_MEMORY_ALLOCATION_ERROR;
171         }
172         return; // Failure
173     }
174 
175     setRuleStringFromCollator();
176 }
177 
178 /* RuleBasedCollator public destructor ----------------------------------- */
179 
~RuleBasedCollator()180 RuleBasedCollator::~RuleBasedCollator()
181 {
182     if (dataIsOwned)
183     {
184         ucol_close(ucollator);
185     }
186     ucollator = 0;
187 }
188 
189 /* RuleBaseCollator public methods --------------------------------------- */
190 
operator ==(const Collator & that) const191 UBool RuleBasedCollator::operator==(const Collator& that) const
192 {
193   /* only checks for address equals here */
194   if (this == &that) {
195     return TRUE;
196   }
197   if (!Collator::operator==(that)) {
198     return FALSE;  /* not the same class */
199   }
200 
201   RuleBasedCollator& thatAlias = (RuleBasedCollator&)that;
202 
203   return ucol_equals(this->ucollator, thatAlias.ucollator);
204 }
205 
206 // aliasing, not write-through
operator =(const RuleBasedCollator & that)207 RuleBasedCollator& RuleBasedCollator::operator=(const RuleBasedCollator& that)
208 {
209     if (this == &that) { return *this; }
210 
211     UErrorCode intStatus = U_ZERO_ERROR;
212     int32_t buffersize = U_COL_SAFECLONE_BUFFERSIZE;
213     UCollator *ucol = ucol_safeClone(that.ucollator, NULL, &buffersize, &intStatus);
214     if (U_FAILURE(intStatus)) { return *this; }
215 
216     if (dataIsOwned) {
217         ucol_close(ucollator);
218     }
219     ucollator = ucol;
220     dataIsOwned = TRUE;
221     isWriteThroughAlias = FALSE;
222     setRuleStringFromCollator();
223     return *this;
224 }
225 
226 // aliasing, not write-through
clone() const227 Collator* RuleBasedCollator::clone() const
228 {
229     RuleBasedCollator* coll = new RuleBasedCollator(*this);
230     // There is a small chance that the internal ucol_safeClone() call fails.
231     if (coll != NULL && coll->ucollator == NULL) {
232         delete coll;
233         return NULL;
234     }
235     return coll;
236 }
237 
238 
createCollationElementIterator(const UnicodeString & source) const239 CollationElementIterator* RuleBasedCollator::createCollationElementIterator
240                                            (const UnicodeString& source) const
241 {
242     UErrorCode status = U_ZERO_ERROR;
243     CollationElementIterator *result = new CollationElementIterator(source, this,
244                                                                     status);
245     if (U_FAILURE(status)) {
246         delete result;
247         return NULL;
248     }
249 
250     return result;
251 }
252 
253 /**
254 * Create a CollationElementIterator object that will iterate over the
255 * elements in a string, using the collation rules defined in this
256 * RuleBasedCollator
257 */
createCollationElementIterator(const CharacterIterator & source) const258 CollationElementIterator* RuleBasedCollator::createCollationElementIterator
259                                        (const CharacterIterator& source) const
260 {
261     UErrorCode status = U_ZERO_ERROR;
262     CollationElementIterator *result = new CollationElementIterator(source, this,
263                                                                     status);
264 
265     if (U_FAILURE(status)) {
266         delete result;
267         return NULL;
268     }
269 
270     return result;
271 }
272 
273 /**
274 * Return a string representation of this collator's rules. The string can
275 * later be passed to the constructor that takes a UnicodeString argument,
276 * which will construct a collator that's functionally identical to this one.
277 * You can also allow users to edit the string in order to change the collation
278 * data, or you can print it out for inspection, or whatever.
279 */
getRules() const280 const UnicodeString& RuleBasedCollator::getRules() const
281 {
282     return urulestring;
283 }
284 
getRules(UColRuleOption delta,UnicodeString & buffer)285 void RuleBasedCollator::getRules(UColRuleOption delta, UnicodeString &buffer)
286 {
287     int32_t rulesize = ucol_getRulesEx(ucollator, delta, NULL, -1);
288 
289     if (rulesize > 0) {
290         UChar *rules = (UChar*) uprv_malloc( sizeof(UChar) * (rulesize) );
291         if(rules != NULL) {
292             ucol_getRulesEx(ucollator, delta, rules, rulesize);
293             buffer.setTo(rules, rulesize);
294             uprv_free(rules);
295         } else { // couldn't allocate
296             buffer.remove();
297         }
298     }
299     else {
300         buffer.remove();
301     }
302 }
303 
304 UnicodeSet *
getTailoredSet(UErrorCode & status) const305 RuleBasedCollator::getTailoredSet(UErrorCode &status) const
306 {
307     if(U_FAILURE(status)) {
308         return NULL;
309     }
310     return (UnicodeSet *)ucol_getTailoredSet(this->ucollator, &status);
311 }
312 
313 
getVersion(UVersionInfo versionInfo) const314 void RuleBasedCollator::getVersion(UVersionInfo versionInfo) const
315 {
316     if (versionInfo!=NULL){
317         ucol_getVersion(ucollator, versionInfo);
318     }
319 }
320 
321 /**
322 * Compare two strings using this collator
323 */
compare(const UnicodeString & source,const UnicodeString & target,int32_t length,UErrorCode & status) const324 UCollationResult RuleBasedCollator::compare(
325                                                const UnicodeString& source,
326                                                const UnicodeString& target,
327                                                int32_t length,
328                                                UErrorCode &status) const
329 {
330     return compare(source.getBuffer(), uprv_min(length,source.length()), target.getBuffer(), uprv_min(length,target.length()), status);
331 }
332 
compare(const UChar * source,int32_t sourceLength,const UChar * target,int32_t targetLength,UErrorCode & status) const333 UCollationResult RuleBasedCollator::compare(const UChar* source,
334                                                        int32_t sourceLength,
335                                                        const UChar* target,
336                                                        int32_t targetLength,
337                                                        UErrorCode &status) const
338 {
339     if(U_SUCCESS(status)) {
340         return  ucol_strcoll(ucollator, source, sourceLength, target, targetLength);
341     } else {
342         return UCOL_EQUAL;
343     }
344 }
345 
compare(const UnicodeString & source,const UnicodeString & target,UErrorCode & status) const346 UCollationResult RuleBasedCollator::compare(
347                                              const UnicodeString& source,
348                                              const UnicodeString& target,
349                                              UErrorCode &status) const
350 {
351     if(U_SUCCESS(status)) {
352         return ucol_strcoll(ucollator, source.getBuffer(), source.length(),
353                                        target.getBuffer(), target.length());
354     } else {
355         return UCOL_EQUAL;
356     }
357 }
358 
compare(UCharIterator & sIter,UCharIterator & tIter,UErrorCode & status) const359 UCollationResult RuleBasedCollator::compare(UCharIterator &sIter,
360                                             UCharIterator &tIter,
361                                             UErrorCode &status) const {
362     if(U_SUCCESS(status)) {
363         return ucol_strcollIter(ucollator, &sIter, &tIter, &status);
364     } else {
365         return UCOL_EQUAL;
366     }
367 }
368 
369 /**
370 * Retrieve a collation key for the specified string. The key can be compared
371 * with other collation keys using a bitwise comparison (e.g. memcmp) to find
372 * the ordering of their respective source strings. This is handy when doing a
373 * sort, where each sort key must be compared many times.
374 *
375 * The basic algorithm here is to find all of the collation elements for each
376 * character in the source string, convert them to an ASCII representation, and
377 * put them into the collation key.  But it's trickier than that. Each
378 * collation element in a string has three components: primary ('A' vs 'B'),
379 * secondary ('u' vs '\u00FC'), and tertiary ('A' vs 'a'), and a primary difference
380 * at the end of a string takes precedence over a secondary or tertiary
381 * difference earlier in the string.
382 *
383 * To account for this, we put all of the primary orders at the beginning of
384 * the string, followed by the secondary and tertiary orders. Each set of
385 * orders is terminated by nulls so that a key for a string which is a initial
386 * substring of another key will compare less without any special case.
387 *
388 * Here's a hypothetical example, with the collation element represented as a
389 * three-digit number, one digit for primary, one for secondary, etc.
390 *
391 * String:              A     a     B    \u00C9
392 * Collation Elements: 101   100   201  511
393 * Collation Key:      1125<null>0001<null>1011<null>
394 *
395 * To make things even trickier, secondary differences (accent marks) are
396 * compared starting at the *end* of the string in languages with French
397 * secondary ordering. But when comparing the accent marks on a single base
398 * character, they are compared from the beginning. To handle this, we reverse
399 * all of the accents that belong to each base character, then we reverse the
400 * entire string of secondary orderings at the end.
401 */
getCollationKey(const UnicodeString & source,CollationKey & sortkey,UErrorCode & status) const402 CollationKey& RuleBasedCollator::getCollationKey(
403                                                   const UnicodeString& source,
404                                                   CollationKey& sortkey,
405                                                   UErrorCode& status) const
406 {
407     return getCollationKey(source.getBuffer(), source.length(), sortkey, status);
408 }
409 
getCollationKey(const UChar * source,int32_t sourceLen,CollationKey & sortkey,UErrorCode & status) const410 CollationKey& RuleBasedCollator::getCollationKey(const UChar* source,
411                                                     int32_t sourceLen,
412                                                     CollationKey& sortkey,
413                                                     UErrorCode& status) const
414 {
415     if (U_FAILURE(status)) {
416         return sortkey.setToBogus();
417     }
418     if (sourceLen < -1 || (source == NULL && sourceLen != 0)) {
419         status = U_ILLEGAL_ARGUMENT_ERROR;
420         return sortkey.setToBogus();
421     }
422 
423     if (sourceLen < 0) {
424         sourceLen = u_strlen(source);
425     }
426     if (sourceLen == 0) {
427         return sortkey.reset();
428     }
429 
430     int32_t resultLen = ucol_getCollationKey(ucollator, source, sourceLen, sortkey, status);
431 
432     if (U_SUCCESS(status)) {
433         sortkey.setLength(resultLen);
434     } else {
435         sortkey.setToBogus();
436     }
437     return sortkey;
438 }
439 
440 /**
441  * Return the maximum length of any expansion sequences that end with the
442  * specified comparison order.
443  * @param order a collation order returned by previous or next.
444  * @return the maximum length of any expansion seuences ending with the
445  *         specified order or 1 if collation order does not occur at the end of any
446  *         expansion sequence.
447  * @see CollationElementIterator#getMaxExpansion
448  */
getMaxExpansion(int32_t order) const449 int32_t RuleBasedCollator::getMaxExpansion(int32_t order) const
450 {
451     uint8_t result;
452     UCOL_GETMAXEXPANSION(ucollator, (uint32_t)order, result);
453     return result;
454 }
455 
cloneRuleData(int32_t & length,UErrorCode & status)456 uint8_t* RuleBasedCollator::cloneRuleData(int32_t &length,
457                                               UErrorCode &status)
458 {
459     return ucol_cloneRuleData(ucollator, &length, &status);
460 }
461 
462 
cloneBinary(uint8_t * buffer,int32_t capacity,UErrorCode & status)463 int32_t RuleBasedCollator::cloneBinary(uint8_t *buffer, int32_t capacity, UErrorCode &status)
464 {
465   return ucol_cloneBinary(ucollator, buffer, capacity, &status);
466 }
467 
setAttribute(UColAttribute attr,UColAttributeValue value,UErrorCode & status)468 void RuleBasedCollator::setAttribute(UColAttribute attr,
469                                      UColAttributeValue value,
470                                      UErrorCode &status)
471 {
472     if (U_FAILURE(status))
473         return;
474     checkOwned();
475     ucol_setAttribute(ucollator, attr, value, &status);
476 }
477 
getAttribute(UColAttribute attr,UErrorCode & status) const478 UColAttributeValue RuleBasedCollator::getAttribute(UColAttribute attr,
479                                                       UErrorCode &status) const
480 {
481     if (U_FAILURE(status))
482         return UCOL_DEFAULT;
483     return ucol_getAttribute(ucollator, attr, &status);
484 }
485 
setVariableTop(const UChar * varTop,int32_t len,UErrorCode & status)486 uint32_t RuleBasedCollator::setVariableTop(const UChar *varTop, int32_t len, UErrorCode &status) {
487     checkOwned();
488     return ucol_setVariableTop(ucollator, varTop, len, &status);
489 }
490 
setVariableTop(const UnicodeString & varTop,UErrorCode & status)491 uint32_t RuleBasedCollator::setVariableTop(const UnicodeString &varTop, UErrorCode &status) {
492     checkOwned();
493     return ucol_setVariableTop(ucollator, varTop.getBuffer(), varTop.length(), &status);
494 }
495 
setVariableTop(uint32_t varTop,UErrorCode & status)496 void RuleBasedCollator::setVariableTop(uint32_t varTop, UErrorCode &status) {
497     checkOwned();
498     ucol_restoreVariableTop(ucollator, varTop, &status);
499 }
500 
getVariableTop(UErrorCode & status) const501 uint32_t RuleBasedCollator::getVariableTop(UErrorCode &status) const {
502   return ucol_getVariableTop(ucollator, &status);
503 }
504 
getSortKey(const UnicodeString & source,uint8_t * result,int32_t resultLength) const505 int32_t RuleBasedCollator::getSortKey(const UnicodeString& source,
506                                          uint8_t *result, int32_t resultLength)
507                                          const
508 {
509     return ucol_getSortKey(ucollator, source.getBuffer(), source.length(), result, resultLength);
510 }
511 
getSortKey(const UChar * source,int32_t sourceLength,uint8_t * result,int32_t resultLength) const512 int32_t RuleBasedCollator::getSortKey(const UChar *source,
513                                          int32_t sourceLength, uint8_t *result,
514                                          int32_t resultLength) const
515 {
516     return ucol_getSortKey(ucollator, source, sourceLength, result, resultLength);
517 }
518 
getReorderCodes(int32_t * dest,int32_t destCapacity,UErrorCode & status) const519 int32_t RuleBasedCollator::getReorderCodes(int32_t *dest,
520                                           int32_t destCapacity,
521                                           UErrorCode& status) const
522 {
523     return ucol_getReorderCodes(ucollator, dest, destCapacity, &status);
524 }
525 
setReorderCodes(const int32_t * reorderCodes,int32_t reorderCodesLength,UErrorCode & status)526 void RuleBasedCollator::setReorderCodes(const int32_t *reorderCodes,
527                                        int32_t reorderCodesLength,
528                                        UErrorCode& status)
529 {
530     checkOwned();
531     ucol_setReorderCodes(ucollator, reorderCodes, reorderCodesLength, &status);
532 }
533 
getEquivalentReorderCodes(int32_t reorderCode,int32_t * dest,int32_t destCapacity,UErrorCode & status)534 int32_t RuleBasedCollator::getEquivalentReorderCodes(int32_t reorderCode,
535                                 int32_t* dest,
536                                 int32_t destCapacity,
537                                 UErrorCode& status)
538 {
539     return ucol_getEquivalentReorderCodes(reorderCode, dest, destCapacity, &status);
540 }
541 
542 /**
543 * Create a hash code for this collation. Just hash the main rule table -- that
544 * should be good enough for almost any use.
545 */
hashCode() const546 int32_t RuleBasedCollator::hashCode() const
547 {
548     int32_t length;
549     const UChar *rules = ucol_getRules(ucollator, &length);
550     return ustr_hashUCharsN(rules, length);
551 }
552 
553 /**
554 * return the locale of this collator
555 */
getLocale(ULocDataLocaleType type,UErrorCode & status) const556 Locale RuleBasedCollator::getLocale(ULocDataLocaleType type, UErrorCode &status) const {
557     const char *result = ucol_getLocaleByType(ucollator, type, &status);
558     if(result == NULL) {
559         Locale res("");
560         res.setToBogus();
561         return res;
562     } else {
563         return Locale(result);
564     }
565 }
566 
567 void
setLocales(const Locale & requestedLocale,const Locale & validLocale,const Locale & actualLocale)568 RuleBasedCollator::setLocales(const Locale& requestedLocale, const Locale& validLocale, const Locale& actualLocale) {
569     checkOwned();
570     char* rloc  = uprv_strdup(requestedLocale.getName());
571     if (rloc) {
572         char* vloc = uprv_strdup(validLocale.getName());
573         if (vloc) {
574             char* aloc = uprv_strdup(actualLocale.getName());
575             if (aloc) {
576                 ucol_setReqValidLocales(ucollator, rloc, vloc, aloc);
577                 return;
578             }
579             uprv_free(vloc);
580         }
581         uprv_free(rloc);
582     }
583 }
584 
585 // RuleBaseCollatorNew private constructor ----------------------------------
586 
RuleBasedCollator()587 RuleBasedCollator::RuleBasedCollator()
588   : dataIsOwned(FALSE), isWriteThroughAlias(FALSE), ucollator(NULL)
589 {
590 }
591 
RuleBasedCollator(const Locale & desiredLocale,UErrorCode & status)592 RuleBasedCollator::RuleBasedCollator(const Locale& desiredLocale,
593                                            UErrorCode& status)
594  : dataIsOwned(FALSE), isWriteThroughAlias(FALSE), ucollator(NULL)
595 {
596     if (U_FAILURE(status))
597         return;
598 
599     /*
600     Try to load, in order:
601      1. The desired locale's collation.
602      2. A fallback of the desired locale.
603      3. The default locale's collation.
604      4. A fallback of the default locale.
605      5. The default collation rules, which contains en_US collation rules.
606 
607      To reiterate, we try:
608      Specific:
609       language+country+variant
610       language+country
611       language
612      Default:
613       language+country+variant
614       language+country
615       language
616      Root: (aka DEFAULTRULES)
617      steps 1-5 are handled by resource bundle fallback mechanism.
618      however, in a very unprobable situation that no resource bundle
619      data exists, step 5 is repeated with hardcoded default rules.
620     */
621 
622     setUCollator(desiredLocale, status);
623 
624     if (U_FAILURE(status))
625     {
626         status = U_ZERO_ERROR;
627 
628         setUCollator(kRootLocaleName, status);
629         if (status == U_ZERO_ERROR) {
630             status = U_USING_DEFAULT_WARNING;
631         }
632     }
633 
634     if (U_SUCCESS(status))
635     {
636         setRuleStringFromCollator();
637     }
638 }
639 
640 void
setUCollator(const char * locale,UErrorCode & status)641 RuleBasedCollator::setUCollator(const char *locale,
642                                 UErrorCode &status)
643 {
644     if (U_FAILURE(status)) {
645         return;
646     }
647     if (ucollator && dataIsOwned)
648         ucol_close(ucollator);
649     ucollator = ucol_open_internal(locale, &status);
650     dataIsOwned = TRUE;
651     isWriteThroughAlias = FALSE;
652 }
653 
654 
655 void
checkOwned()656 RuleBasedCollator::checkOwned() {
657     if (!(dataIsOwned || isWriteThroughAlias)) {
658         UErrorCode status = U_ZERO_ERROR;
659         ucollator = ucol_safeClone(ucollator, NULL, NULL, &status);
660         setRuleStringFromCollator();
661         dataIsOwned = TRUE;
662         isWriteThroughAlias = FALSE;
663     }
664 }
665 
666 
internalGetShortDefinitionString(const char * locale,char * buffer,int32_t capacity,UErrorCode & status) const667 int32_t RuleBasedCollator::internalGetShortDefinitionString(const char *locale,
668                                                                       char *buffer,
669                                                                       int32_t capacity,
670                                                                       UErrorCode &status) const {
671   /* simply delegate */
672   return ucol_getShortDefinitionString(ucollator, locale, buffer, capacity, &status);
673 }
674 
675 
676 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedCollator)
677 
678 U_NAMESPACE_END
679 
680 #endif /* #if !UCONFIG_NO_COLLATION */
681