• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *******************************************************************************
5 *   Copyright (C) 1996-2015, International Business Machines
6 *   Corporation and others.  All Rights Reserved.
7 *******************************************************************************
8 *   file name:  ucol.cpp
9 *   encoding:   UTF-8
10 *   tab size:   8 (not used)
11 *   indentation:4
12 *
13 * Modification history
14 * Date        Name      Comments
15 * 1996-1999   various members of ICU team maintained C API for collation framework
16 * 02/16/2001  synwee    Added internal method getPrevSpecialCE
17 * 03/01/2001  synwee    Added maxexpansion functionality.
18 * 03/16/2001  weiv      Collation framework is rewritten in C and made UCA compliant
19 * 2012-2014   markus    Rewritten in C++ again.
20 */
21 
22 #include "unicode/utypes.h"
23 
24 #if !UCONFIG_NO_COLLATION
25 
26 #include "unicode/coll.h"
27 #include "unicode/tblcoll.h"
28 #include "unicode/bytestream.h"
29 #include "unicode/coleitr.h"
30 #include "unicode/ucoleitr.h"
31 #include "unicode/ustring.h"
32 #include "cmemory.h"
33 #include "collation.h"
34 #include "cstring.h"
35 #include "putilimp.h"
36 #include "uassert.h"
37 #include "utracimp.h"
38 
39 U_NAMESPACE_USE
40 
41 U_CAPI UCollator* U_EXPORT2
ucol_openBinary(const uint8_t * bin,int32_t length,const UCollator * base,UErrorCode * status)42 ucol_openBinary(const uint8_t *bin, int32_t length,
43                 const UCollator *base,
44                 UErrorCode *status)
45 {
46     if(U_FAILURE(*status)) { return NULL; }
47     RuleBasedCollator *coll = new RuleBasedCollator(
48             bin, length,
49             RuleBasedCollator::rbcFromUCollator(base),
50             *status);
51     if(coll == NULL) {
52         *status = U_MEMORY_ALLOCATION_ERROR;
53         return NULL;
54     }
55     if(U_FAILURE(*status)) {
56         delete coll;
57         return NULL;
58     }
59     return coll->toUCollator();
60 }
61 
62 U_CAPI int32_t U_EXPORT2
ucol_cloneBinary(const UCollator * coll,uint8_t * buffer,int32_t capacity,UErrorCode * status)63 ucol_cloneBinary(const UCollator *coll,
64                  uint8_t *buffer, int32_t capacity,
65                  UErrorCode *status)
66 {
67     if(U_FAILURE(*status)) {
68         return 0;
69     }
70     const RuleBasedCollator *rbc = RuleBasedCollator::rbcFromUCollator(coll);
71     if(rbc == NULL && coll != NULL) {
72         *status = U_UNSUPPORTED_ERROR;
73         return 0;
74     }
75     return rbc->cloneBinary(buffer, capacity, *status);
76 }
77 
78 U_CAPI UCollator* U_EXPORT2
ucol_safeClone(const UCollator * coll,void *,int32_t * pBufferSize,UErrorCode * status)79 ucol_safeClone(const UCollator *coll, void * /*stackBuffer*/, int32_t * pBufferSize, UErrorCode *status)
80 {
81     if (status == NULL || U_FAILURE(*status)){
82         return NULL;
83     }
84     if (coll == NULL) {
85        *status = U_ILLEGAL_ARGUMENT_ERROR;
86         return NULL;
87     }
88     if (pBufferSize != NULL) {
89         int32_t inputSize = *pBufferSize;
90         *pBufferSize = 1;
91         if (inputSize == 0) {
92             return NULL;  // preflighting for deprecated functionality
93         }
94     }
95     Collator *newColl = Collator::fromUCollator(coll)->clone();
96     if (newColl == NULL) {
97         *status = U_MEMORY_ALLOCATION_ERROR;
98         return nullptr;
99     } else if (pBufferSize != NULL) {
100         *status = U_SAFECLONE_ALLOCATED_WARNING;
101     }
102     return newColl->toUCollator();
103 }
104 
105 U_CAPI UCollator* U_EXPORT2
ucol_clone(const UCollator * coll,UErrorCode * status)106 ucol_clone(const UCollator *coll, UErrorCode *status)
107 {
108     return ucol_safeClone(coll, nullptr, nullptr, status);
109 }
110 
111 U_CAPI void U_EXPORT2
ucol_close(UCollator * coll)112 ucol_close(UCollator *coll)
113 {
114     UTRACE_ENTRY_OC(UTRACE_UCOL_CLOSE);
115     UTRACE_DATA1(UTRACE_INFO, "coll = %p", coll);
116     if(coll != NULL) {
117         delete Collator::fromUCollator(coll);
118     }
119     UTRACE_EXIT();
120 }
121 
122 U_CAPI int32_t U_EXPORT2
ucol_mergeSortkeys(const uint8_t * src1,int32_t src1Length,const uint8_t * src2,int32_t src2Length,uint8_t * dest,int32_t destCapacity)123 ucol_mergeSortkeys(const uint8_t *src1, int32_t src1Length,
124                    const uint8_t *src2, int32_t src2Length,
125                    uint8_t *dest, int32_t destCapacity) {
126     /* check arguments */
127     if( src1==NULL || src1Length<-1 || src1Length==0 || (src1Length>0 && src1[src1Length-1]!=0) ||
128         src2==NULL || src2Length<-1 || src2Length==0 || (src2Length>0 && src2[src2Length-1]!=0) ||
129         destCapacity<0 || (destCapacity>0 && dest==NULL)
130     ) {
131         /* error, attempt to write a zero byte and return 0 */
132         if(dest!=NULL && destCapacity>0) {
133             *dest=0;
134         }
135         return 0;
136     }
137 
138     /* check lengths and capacity */
139     if(src1Length<0) {
140         src1Length=(int32_t)uprv_strlen((const char *)src1)+1;
141     }
142     if(src2Length<0) {
143         src2Length=(int32_t)uprv_strlen((const char *)src2)+1;
144     }
145 
146     int32_t destLength=src1Length+src2Length;
147     if(destLength>destCapacity) {
148         /* the merged sort key does not fit into the destination */
149         return destLength;
150     }
151 
152     /* merge the sort keys with the same number of levels */
153     uint8_t *p=dest;
154     for(;;) {
155         /* copy level from src1 not including 00 or 01 */
156         uint8_t b;
157         while((b=*src1)>=2) {
158             ++src1;
159             *p++=b;
160         }
161 
162         /* add a 02 merge separator */
163         *p++=2;
164 
165         /* copy level from src2 not including 00 or 01 */
166         while((b=*src2)>=2) {
167             ++src2;
168             *p++=b;
169         }
170 
171         /* if both sort keys have another level, then add a 01 level separator and continue */
172         if(*src1==1 && *src2==1) {
173             ++src1;
174             ++src2;
175             *p++=1;
176         } else {
177             break;
178         }
179     }
180 
181     /*
182      * here, at least one sort key is finished now, but the other one
183      * might have some contents left from containing more levels;
184      * that contents is just appended to the result
185      */
186     if(*src1!=0) {
187         /* src1 is not finished, therefore *src2==0, and src1 is appended */
188         src2=src1;
189     }
190     /* append src2, "the other, unfinished sort key" */
191     while((*p++=*src2++)!=0) {}
192 
193     /* the actual length might be less than destLength if either sort key contained illegally embedded zero bytes */
194     return (int32_t)(p-dest);
195 }
196 
197 U_CAPI int32_t U_EXPORT2
ucol_getSortKey(const UCollator * coll,const UChar * source,int32_t sourceLength,uint8_t * result,int32_t resultLength)198 ucol_getSortKey(const    UCollator    *coll,
199         const    UChar        *source,
200         int32_t        sourceLength,
201         uint8_t        *result,
202         int32_t        resultLength)
203 {
204     UTRACE_ENTRY(UTRACE_UCOL_GET_SORTKEY);
205     if (UTRACE_LEVEL(UTRACE_VERBOSE)) {
206         UTRACE_DATA3(UTRACE_VERBOSE, "coll=%p, source string = %vh ", coll, source,
207             ((sourceLength==-1 && source!=NULL) ? u_strlen(source) : sourceLength));
208     }
209 
210     int32_t keySize = Collator::fromUCollator(coll)->
211             getSortKey(source, sourceLength, result, resultLength);
212 
213     UTRACE_DATA2(UTRACE_VERBOSE, "Sort Key = %vb", result, keySize);
214     UTRACE_EXIT_VALUE(keySize);
215     return keySize;
216 }
217 
218 U_CAPI int32_t U_EXPORT2
ucol_nextSortKeyPart(const UCollator * coll,UCharIterator * iter,uint32_t state[2],uint8_t * dest,int32_t count,UErrorCode * status)219 ucol_nextSortKeyPart(const UCollator *coll,
220                      UCharIterator *iter,
221                      uint32_t state[2],
222                      uint8_t *dest, int32_t count,
223                      UErrorCode *status)
224 {
225     /* error checking */
226     if(status==NULL || U_FAILURE(*status)) {
227         return 0;
228     }
229     UTRACE_ENTRY(UTRACE_UCOL_NEXTSORTKEYPART);
230     UTRACE_DATA6(UTRACE_VERBOSE, "coll=%p, iter=%p, state=%d %d, dest=%p, count=%d",
231                   coll, iter, state[0], state[1], dest, count);
232 
233     int32_t i = Collator::fromUCollator(coll)->
234             internalNextSortKeyPart(iter, state, dest, count, *status);
235 
236     // Return number of meaningful sortkey bytes.
237     UTRACE_DATA4(UTRACE_VERBOSE, "dest = %vb, state=%d %d",
238                   dest,i, state[0], state[1]);
239     UTRACE_EXIT_VALUE_STATUS(i, *status);
240     return i;
241 }
242 
243 /**
244  * Produce a bound for a given sortkey and a number of levels.
245  */
246 U_CAPI int32_t U_EXPORT2
ucol_getBound(const uint8_t * source,int32_t sourceLength,UColBoundMode boundType,uint32_t noOfLevels,uint8_t * result,int32_t resultLength,UErrorCode * status)247 ucol_getBound(const uint8_t       *source,
248         int32_t             sourceLength,
249         UColBoundMode       boundType,
250         uint32_t            noOfLevels,
251         uint8_t             *result,
252         int32_t             resultLength,
253         UErrorCode          *status)
254 {
255     // consistency checks
256     if(status == NULL || U_FAILURE(*status)) {
257         return 0;
258     }
259     if(source == NULL) {
260         *status = U_ILLEGAL_ARGUMENT_ERROR;
261         return 0;
262     }
263 
264     int32_t sourceIndex = 0;
265     // Scan the string until we skip enough of the key OR reach the end of the key
266     do {
267         sourceIndex++;
268         if(source[sourceIndex] == Collation::LEVEL_SEPARATOR_BYTE) {
269             noOfLevels--;
270         }
271     } while (noOfLevels > 0
272         && (source[sourceIndex] != 0 || sourceIndex < sourceLength));
273 
274     if((source[sourceIndex] == 0 || sourceIndex == sourceLength)
275         && noOfLevels > 0) {
276             *status = U_SORT_KEY_TOO_SHORT_WARNING;
277     }
278 
279 
280     // READ ME: this code assumes that the values for boundType
281     // enum will not changes. They are set so that the enum value
282     // corresponds to the number of extra bytes each bound type
283     // needs.
284     if(result != NULL && resultLength >= sourceIndex+boundType) {
285         uprv_memcpy(result, source, sourceIndex);
286         switch(boundType) {
287             // Lower bound just gets terminated. No extra bytes
288         case UCOL_BOUND_LOWER: // = 0
289             break;
290             // Upper bound needs one extra byte
291         case UCOL_BOUND_UPPER: // = 1
292             result[sourceIndex++] = 2;
293             break;
294             // Upper long bound needs two extra bytes
295         case UCOL_BOUND_UPPER_LONG: // = 2
296             result[sourceIndex++] = 0xFF;
297             result[sourceIndex++] = 0xFF;
298             break;
299         default:
300             *status = U_ILLEGAL_ARGUMENT_ERROR;
301             return 0;
302         }
303         result[sourceIndex++] = 0;
304 
305         return sourceIndex;
306     } else {
307         return sourceIndex+boundType+1;
308     }
309 }
310 
311 U_CAPI void U_EXPORT2
ucol_setMaxVariable(UCollator * coll,UColReorderCode group,UErrorCode * pErrorCode)312 ucol_setMaxVariable(UCollator *coll, UColReorderCode group, UErrorCode *pErrorCode) {
313     if(U_FAILURE(*pErrorCode)) { return; }
314     Collator::fromUCollator(coll)->setMaxVariable(group, *pErrorCode);
315 }
316 
317 U_CAPI UColReorderCode U_EXPORT2
ucol_getMaxVariable(const UCollator * coll)318 ucol_getMaxVariable(const UCollator *coll) {
319     return Collator::fromUCollator(coll)->getMaxVariable();
320 }
321 
322 U_CAPI uint32_t  U_EXPORT2
ucol_setVariableTop(UCollator * coll,const UChar * varTop,int32_t len,UErrorCode * status)323 ucol_setVariableTop(UCollator *coll, const UChar *varTop, int32_t len, UErrorCode *status) {
324     if(U_FAILURE(*status) || coll == NULL) {
325         return 0;
326     }
327     return Collator::fromUCollator(coll)->setVariableTop(varTop, len, *status);
328 }
329 
ucol_getVariableTop(const UCollator * coll,UErrorCode * status)330 U_CAPI uint32_t U_EXPORT2 ucol_getVariableTop(const UCollator *coll, UErrorCode *status) {
331     if(U_FAILURE(*status) || coll == NULL) {
332         return 0;
333     }
334     return Collator::fromUCollator(coll)->getVariableTop(*status);
335 }
336 
337 U_CAPI void  U_EXPORT2
ucol_restoreVariableTop(UCollator * coll,const uint32_t varTop,UErrorCode * status)338 ucol_restoreVariableTop(UCollator *coll, const uint32_t varTop, UErrorCode *status) {
339     if(U_FAILURE(*status) || coll == NULL) {
340         return;
341     }
342     Collator::fromUCollator(coll)->setVariableTop(varTop, *status);
343 }
344 
345 U_CAPI void  U_EXPORT2
ucol_setAttribute(UCollator * coll,UColAttribute attr,UColAttributeValue value,UErrorCode * status)346 ucol_setAttribute(UCollator *coll, UColAttribute attr, UColAttributeValue value, UErrorCode *status) {
347     if(U_FAILURE(*status) || coll == NULL) {
348       return;
349     }
350 
351     Collator::fromUCollator(coll)->setAttribute(attr, value, *status);
352 }
353 
354 U_CAPI UColAttributeValue  U_EXPORT2
ucol_getAttribute(const UCollator * coll,UColAttribute attr,UErrorCode * status)355 ucol_getAttribute(const UCollator *coll, UColAttribute attr, UErrorCode *status) {
356     if(U_FAILURE(*status) || coll == NULL) {
357       return UCOL_DEFAULT;
358     }
359 
360     return Collator::fromUCollator(coll)->getAttribute(attr, *status);
361 }
362 
363 U_CAPI void U_EXPORT2
ucol_setStrength(UCollator * coll,UCollationStrength strength)364 ucol_setStrength(    UCollator                *coll,
365             UCollationStrength        strength)
366 {
367     UErrorCode status = U_ZERO_ERROR;
368     ucol_setAttribute(coll, UCOL_STRENGTH, strength, &status);
369 }
370 
371 U_CAPI UCollationStrength U_EXPORT2
ucol_getStrength(const UCollator * coll)372 ucol_getStrength(const UCollator *coll)
373 {
374     UErrorCode status = U_ZERO_ERROR;
375     return ucol_getAttribute(coll, UCOL_STRENGTH, &status);
376 }
377 
378 U_CAPI int32_t U_EXPORT2
ucol_getReorderCodes(const UCollator * coll,int32_t * dest,int32_t destCapacity,UErrorCode * status)379 ucol_getReorderCodes(const UCollator *coll,
380                     int32_t *dest,
381                     int32_t destCapacity,
382                     UErrorCode *status) {
383     if (U_FAILURE(*status)) {
384         return 0;
385     }
386 
387     return Collator::fromUCollator(coll)->getReorderCodes(dest, destCapacity, *status);
388 }
389 
390 U_CAPI void U_EXPORT2
ucol_setReorderCodes(UCollator * coll,const int32_t * reorderCodes,int32_t reorderCodesLength,UErrorCode * status)391 ucol_setReorderCodes(UCollator* coll,
392                     const int32_t* reorderCodes,
393                     int32_t reorderCodesLength,
394                     UErrorCode *status) {
395     if (U_FAILURE(*status)) {
396         return;
397     }
398 
399     Collator::fromUCollator(coll)->setReorderCodes(reorderCodes, reorderCodesLength, *status);
400 }
401 
402 U_CAPI int32_t U_EXPORT2
ucol_getEquivalentReorderCodes(int32_t reorderCode,int32_t * dest,int32_t destCapacity,UErrorCode * pErrorCode)403 ucol_getEquivalentReorderCodes(int32_t reorderCode,
404                     int32_t* dest,
405                     int32_t destCapacity,
406                     UErrorCode *pErrorCode) {
407     return Collator::getEquivalentReorderCodes(reorderCode, dest, destCapacity, *pErrorCode);
408 }
409 
410 U_CAPI void U_EXPORT2
ucol_getVersion(const UCollator * coll,UVersionInfo versionInfo)411 ucol_getVersion(const UCollator* coll,
412                 UVersionInfo versionInfo)
413 {
414     Collator::fromUCollator(coll)->getVersion(versionInfo);
415 }
416 
417 U_CAPI UCollationResult U_EXPORT2
ucol_strcollIter(const UCollator * coll,UCharIterator * sIter,UCharIterator * tIter,UErrorCode * status)418 ucol_strcollIter( const UCollator    *coll,
419                  UCharIterator *sIter,
420                  UCharIterator *tIter,
421                  UErrorCode         *status)
422 {
423     if(!status || U_FAILURE(*status)) {
424         return UCOL_EQUAL;
425     }
426 
427     UTRACE_ENTRY(UTRACE_UCOL_STRCOLLITER);
428     UTRACE_DATA3(UTRACE_VERBOSE, "coll=%p, sIter=%p, tIter=%p", coll, sIter, tIter);
429 
430     if(sIter == NULL || tIter == NULL || coll == NULL) {
431         *status = U_ILLEGAL_ARGUMENT_ERROR;
432         UTRACE_EXIT_VALUE_STATUS(UCOL_EQUAL, *status);
433         return UCOL_EQUAL;
434     }
435 
436     UCollationResult result = Collator::fromUCollator(coll)->compare(*sIter, *tIter, *status);
437 
438     UTRACE_EXIT_VALUE_STATUS(result, *status);
439     return result;
440 }
441 
442 
443 /*                                                                      */
444 /* ucol_strcoll     Main public API string comparison function          */
445 /*                                                                      */
446 U_CAPI UCollationResult U_EXPORT2
ucol_strcoll(const UCollator * coll,const UChar * source,int32_t sourceLength,const UChar * target,int32_t targetLength)447 ucol_strcoll( const UCollator    *coll,
448               const UChar        *source,
449               int32_t            sourceLength,
450               const UChar        *target,
451               int32_t            targetLength)
452 {
453     UTRACE_ENTRY(UTRACE_UCOL_STRCOLL);
454     if (UTRACE_LEVEL(UTRACE_VERBOSE)) {
455         UTRACE_DATA3(UTRACE_VERBOSE, "coll=%p, source=%p, target=%p", coll, source, target);
456         UTRACE_DATA2(UTRACE_VERBOSE, "source string = %vh ", source, sourceLength);
457         UTRACE_DATA2(UTRACE_VERBOSE, "target string = %vh ", target, targetLength);
458     }
459 
460     UErrorCode status = U_ZERO_ERROR;
461     UCollationResult returnVal = Collator::fromUCollator(coll)->
462             compare(source, sourceLength, target, targetLength, status);
463     UTRACE_EXIT_VALUE_STATUS(returnVal, status);
464     return returnVal;
465 }
466 
467 U_CAPI UCollationResult U_EXPORT2
ucol_strcollUTF8(const UCollator * coll,const char * source,int32_t sourceLength,const char * target,int32_t targetLength,UErrorCode * status)468 ucol_strcollUTF8(
469         const UCollator *coll,
470         const char      *source,
471         int32_t         sourceLength,
472         const char      *target,
473         int32_t         targetLength,
474         UErrorCode      *status)
475 {
476     UTRACE_ENTRY(UTRACE_UCOL_STRCOLLUTF8);
477     if (UTRACE_LEVEL(UTRACE_VERBOSE)) {
478         UTRACE_DATA3(UTRACE_VERBOSE, "coll=%p, source=%p, target=%p", coll, source, target);
479         UTRACE_DATA2(UTRACE_VERBOSE, "source string = %vb ", source, sourceLength);
480         UTRACE_DATA2(UTRACE_VERBOSE, "target string = %vb ", target, targetLength);
481     }
482 
483     if (U_FAILURE(*status)) {
484         /* do nothing */
485         UTRACE_EXIT_VALUE_STATUS(UCOL_EQUAL, *status);
486         return UCOL_EQUAL;
487     }
488 
489     UCollationResult returnVal = Collator::fromUCollator(coll)->internalCompareUTF8(
490             source, sourceLength, target, targetLength, *status);
491     UTRACE_EXIT_VALUE_STATUS(returnVal, *status);
492     return returnVal;
493 }
494 
495 
496 /* convenience function for comparing strings */
497 U_CAPI UBool U_EXPORT2
ucol_greater(const UCollator * coll,const UChar * source,int32_t sourceLength,const UChar * target,int32_t targetLength)498 ucol_greater(    const    UCollator        *coll,
499         const    UChar            *source,
500         int32_t            sourceLength,
501         const    UChar            *target,
502         int32_t            targetLength)
503 {
504     return (ucol_strcoll(coll, source, sourceLength, target, targetLength)
505         == UCOL_GREATER);
506 }
507 
508 /* convenience function for comparing strings */
509 U_CAPI UBool U_EXPORT2
ucol_greaterOrEqual(const UCollator * coll,const UChar * source,int32_t sourceLength,const UChar * target,int32_t targetLength)510 ucol_greaterOrEqual(    const    UCollator    *coll,
511             const    UChar        *source,
512             int32_t        sourceLength,
513             const    UChar        *target,
514             int32_t        targetLength)
515 {
516     return (ucol_strcoll(coll, source, sourceLength, target, targetLength)
517         != UCOL_LESS);
518 }
519 
520 /* convenience function for comparing strings */
521 U_CAPI UBool U_EXPORT2
ucol_equal(const UCollator * coll,const UChar * source,int32_t sourceLength,const UChar * target,int32_t targetLength)522 ucol_equal(        const    UCollator        *coll,
523             const    UChar            *source,
524             int32_t            sourceLength,
525             const    UChar            *target,
526             int32_t            targetLength)
527 {
528     return (ucol_strcoll(coll, source, sourceLength, target, targetLength)
529         == UCOL_EQUAL);
530 }
531 
532 U_CAPI void U_EXPORT2
ucol_getUCAVersion(const UCollator * coll,UVersionInfo info)533 ucol_getUCAVersion(const UCollator* coll, UVersionInfo info) {
534     const Collator *c = Collator::fromUCollator(coll);
535     if(c != NULL) {
536         UVersionInfo v;
537         c->getVersion(v);
538         // Note: This is tied to how the current implementation encodes the UCA version
539         // in the overall getVersion().
540         // Alternatively, we could load the root collator and get at lower-level data from there.
541         // Either way, it will reflect the input collator's UCA version only
542         // if it is a known implementation.
543         // It would be cleaner to make this a virtual Collator method.
544         info[0] = v[1] >> 3;
545         info[1] = v[1] & 7;
546         info[2] = v[2] >> 6;
547         info[3] = 0;
548     }
549 }
550 
551 U_CAPI const UChar * U_EXPORT2
ucol_getRules(const UCollator * coll,int32_t * length)552 ucol_getRules(const UCollator *coll, int32_t *length) {
553     const RuleBasedCollator *rbc = RuleBasedCollator::rbcFromUCollator(coll);
554     // OK to crash if coll==NULL: We do not want to check "this" pointers.
555     if(rbc != NULL || coll == NULL) {
556         const UnicodeString &rules = rbc->getRules();
557         U_ASSERT(rules.getBuffer()[rules.length()] == 0);
558         *length = rules.length();
559         return rules.getBuffer();
560     }
561     static const UChar _NUL = 0;
562     *length = 0;
563     return &_NUL;
564 }
565 
566 U_CAPI int32_t U_EXPORT2
ucol_getRulesEx(const UCollator * coll,UColRuleOption delta,UChar * buffer,int32_t bufferLen)567 ucol_getRulesEx(const UCollator *coll, UColRuleOption delta, UChar *buffer, int32_t bufferLen) {
568     UnicodeString rules;
569     const RuleBasedCollator *rbc = RuleBasedCollator::rbcFromUCollator(coll);
570     if(rbc != NULL || coll == NULL) {
571         rbc->getRules(delta, rules);
572     }
573     if(buffer != NULL && bufferLen > 0) {
574         UErrorCode errorCode = U_ZERO_ERROR;
575         return rules.extract(buffer, bufferLen, errorCode);
576     } else {
577         return rules.length();
578     }
579 }
580 
581 U_CAPI const char * U_EXPORT2
ucol_getLocale(const UCollator * coll,ULocDataLocaleType type,UErrorCode * status)582 ucol_getLocale(const UCollator *coll, ULocDataLocaleType type, UErrorCode *status) {
583     return ucol_getLocaleByType(coll, type, status);
584 }
585 
586 U_CAPI const char * U_EXPORT2
ucol_getLocaleByType(const UCollator * coll,ULocDataLocaleType type,UErrorCode * status)587 ucol_getLocaleByType(const UCollator *coll, ULocDataLocaleType type, UErrorCode *status) {
588     if(U_FAILURE(*status)) {
589         return NULL;
590     }
591     UTRACE_ENTRY(UTRACE_UCOL_GETLOCALE);
592     UTRACE_DATA1(UTRACE_INFO, "coll=%p", coll);
593 
594     const char *result;
595     const RuleBasedCollator *rbc = RuleBasedCollator::rbcFromUCollator(coll);
596     if(rbc == NULL && coll != NULL) {
597         *status = U_UNSUPPORTED_ERROR;
598         result = NULL;
599     } else {
600         result = rbc->internalGetLocaleID(type, *status);
601     }
602 
603     UTRACE_DATA1(UTRACE_INFO, "result = %s", result);
604     UTRACE_EXIT_STATUS(*status);
605     return result;
606 }
607 
608 U_CAPI USet * U_EXPORT2
ucol_getTailoredSet(const UCollator * coll,UErrorCode * status)609 ucol_getTailoredSet(const UCollator *coll, UErrorCode *status) {
610     if(U_FAILURE(*status)) {
611         return NULL;
612     }
613     UnicodeSet *set = Collator::fromUCollator(coll)->getTailoredSet(*status);
614     if(U_FAILURE(*status)) {
615         delete set;
616         return NULL;
617     }
618     return set->toUSet();
619 }
620 
621 U_CAPI UBool U_EXPORT2
ucol_equals(const UCollator * source,const UCollator * target)622 ucol_equals(const UCollator *source, const UCollator *target) {
623     return source == target ||
624         (*Collator::fromUCollator(source)) == (*Collator::fromUCollator(target));
625 }
626 
627 #endif /* #if !UCONFIG_NO_COLLATION */
628