Coverage Report

Created: 2024-04-24 06:23

/src/icu/source/i18n/ucol.cpp
Line
Count
Source (jump to first uncovered line)
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
42
ucol_openBinary(const uint8_t *bin, int32_t length,
43
                const UCollator *base,
44
                UErrorCode *status)
45
0
{
46
0
    if(U_FAILURE(*status)) { return NULL; }
47
0
    RuleBasedCollator *coll = new RuleBasedCollator(
48
0
            bin, length,
49
0
            RuleBasedCollator::rbcFromUCollator(base),
50
0
            *status);
51
0
    if(coll == NULL) {
52
0
        *status = U_MEMORY_ALLOCATION_ERROR;
53
0
        return NULL;
54
0
    }
55
0
    if(U_FAILURE(*status)) {
56
0
        delete coll;
57
0
        return NULL;
58
0
    }
59
0
    return coll->toUCollator();
60
0
}
61
62
U_CAPI int32_t U_EXPORT2
63
ucol_cloneBinary(const UCollator *coll,
64
                 uint8_t *buffer, int32_t capacity,
65
                 UErrorCode *status)
66
0
{
67
0
    if(U_FAILURE(*status)) {
68
0
        return 0;
69
0
    }
70
0
    const RuleBasedCollator *rbc = RuleBasedCollator::rbcFromUCollator(coll);
71
0
    if(rbc == NULL && coll != NULL) {
72
0
        *status = U_UNSUPPORTED_ERROR;
73
0
        return 0;
74
0
    }
75
0
    return rbc->cloneBinary(buffer, capacity, *status);
76
0
}
77
78
U_CAPI UCollator* U_EXPORT2
79
ucol_safeClone(const UCollator *coll, void * /*stackBuffer*/, int32_t * pBufferSize, UErrorCode *status)
80
0
{
81
0
    if (status == NULL || U_FAILURE(*status)){
82
0
        return NULL;
83
0
    }
84
0
    if (coll == NULL) {
85
0
       *status = U_ILLEGAL_ARGUMENT_ERROR;
86
0
        return NULL;
87
0
    }
88
0
    if (pBufferSize != NULL) {
89
0
        int32_t inputSize = *pBufferSize;
90
0
        *pBufferSize = 1;
91
0
        if (inputSize == 0) {
92
0
            return NULL;  // preflighting for deprecated functionality
93
0
        }
94
0
    }
95
0
    Collator *newColl = Collator::fromUCollator(coll)->clone();
96
0
    if (newColl == NULL) {
97
0
        *status = U_MEMORY_ALLOCATION_ERROR;
98
0
        return nullptr;
99
0
    } else if (pBufferSize != NULL) {
100
0
        *status = U_SAFECLONE_ALLOCATED_WARNING;
101
0
    }
102
0
    return newColl->toUCollator();
103
0
}
104
105
U_CAPI UCollator* U_EXPORT2
106
ucol_clone(const UCollator *coll, UErrorCode *status)
107
0
{
108
0
    return ucol_safeClone(coll, nullptr, nullptr, status);
109
0
}
110
111
U_CAPI void U_EXPORT2
112
ucol_close(UCollator *coll)
113
0
{
114
0
    UTRACE_ENTRY_OC(UTRACE_UCOL_CLOSE);
115
0
    UTRACE_DATA1(UTRACE_INFO, "coll = %p", coll);
116
0
    if(coll != NULL) {
117
0
        delete Collator::fromUCollator(coll);
118
0
    }
119
0
    UTRACE_EXIT();
120
0
}
121
122
U_CAPI int32_t U_EXPORT2
123
ucol_mergeSortkeys(const uint8_t *src1, int32_t src1Length,
124
                   const uint8_t *src2, int32_t src2Length,
125
0
                   uint8_t *dest, int32_t destCapacity) {
126
    /* check arguments */
127
0
    if( src1==NULL || src1Length<-1 || src1Length==0 || (src1Length>0 && src1[src1Length-1]!=0) ||
128
0
        src2==NULL || src2Length<-1 || src2Length==0 || (src2Length>0 && src2[src2Length-1]!=0) ||
129
0
        destCapacity<0 || (destCapacity>0 && dest==NULL)
130
0
    ) {
131
        /* error, attempt to write a zero byte and return 0 */
132
0
        if(dest!=NULL && destCapacity>0) {
133
0
            *dest=0;
134
0
        }
135
0
        return 0;
136
0
    }
137
138
    /* check lengths and capacity */
139
0
    if(src1Length<0) {
140
0
        src1Length=(int32_t)uprv_strlen((const char *)src1)+1;
141
0
    }
142
0
    if(src2Length<0) {
143
0
        src2Length=(int32_t)uprv_strlen((const char *)src2)+1;
144
0
    }
145
146
0
    int32_t destLength=src1Length+src2Length;
147
0
    if(destLength>destCapacity) {
148
        /* the merged sort key does not fit into the destination */
149
0
        return destLength;
150
0
    }
151
152
    /* merge the sort keys with the same number of levels */
153
0
    uint8_t *p=dest;
154
0
    for(;;) {
155
        /* copy level from src1 not including 00 or 01 */
156
0
        uint8_t b;
157
0
        while((b=*src1)>=2) {
158
0
            ++src1;
159
0
            *p++=b;
160
0
        }
161
162
        /* add a 02 merge separator */
163
0
        *p++=2;
164
165
        /* copy level from src2 not including 00 or 01 */
166
0
        while((b=*src2)>=2) {
167
0
            ++src2;
168
0
            *p++=b;
169
0
        }
170
171
        /* if both sort keys have another level, then add a 01 level separator and continue */
172
0
        if(*src1==1 && *src2==1) {
173
0
            ++src1;
174
0
            ++src2;
175
0
            *p++=1;
176
0
        } else {
177
0
            break;
178
0
        }
179
0
    }
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
0
    if(*src1!=0) {
187
        /* src1 is not finished, therefore *src2==0, and src1 is appended */
188
0
        src2=src1;
189
0
    }
190
    /* append src2, "the other, unfinished sort key" */
191
0
    while((*p++=*src2++)!=0) {}
192
193
    /* the actual length might be less than destLength if either sort key contained illegally embedded zero bytes */
194
0
    return (int32_t)(p-dest);
195
0
}
196
197
U_CAPI int32_t U_EXPORT2
198
ucol_getSortKey(const    UCollator    *coll,
199
        const    UChar        *source,
200
        int32_t        sourceLength,
201
        uint8_t        *result,
202
        int32_t        resultLength)
203
0
{
204
0
    UTRACE_ENTRY(UTRACE_UCOL_GET_SORTKEY);
205
0
    if (UTRACE_LEVEL(UTRACE_VERBOSE)) {
206
0
        UTRACE_DATA3(UTRACE_VERBOSE, "coll=%p, source string = %vh ", coll, source,
207
0
            ((sourceLength==-1 && source!=NULL) ? u_strlen(source) : sourceLength));
208
0
    }
209
210
0
    int32_t keySize = Collator::fromUCollator(coll)->
211
0
            getSortKey(source, sourceLength, result, resultLength);
212
213
0
    UTRACE_DATA2(UTRACE_VERBOSE, "Sort Key = %vb", result, keySize);
214
0
    UTRACE_EXIT_VALUE(keySize);
215
0
    return keySize;
216
0
}
217
218
U_CAPI int32_t U_EXPORT2
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
0
{
225
    /* error checking */
226
0
    if(status==NULL || U_FAILURE(*status)) {
227
0
        return 0;
228
0
    }
229
0
    UTRACE_ENTRY(UTRACE_UCOL_NEXTSORTKEYPART);
230
0
    UTRACE_DATA6(UTRACE_VERBOSE, "coll=%p, iter=%p, state=%d %d, dest=%p, count=%d",
231
0
                  coll, iter, state[0], state[1], dest, count);
232
233
0
    int32_t i = Collator::fromUCollator(coll)->
234
0
            internalNextSortKeyPart(iter, state, dest, count, *status);
235
236
    // Return number of meaningful sortkey bytes.
237
0
    UTRACE_DATA4(UTRACE_VERBOSE, "dest = %vb, state=%d %d",
238
0
                  dest,i, state[0], state[1]);
239
0
    UTRACE_EXIT_VALUE_STATUS(i, *status);
240
0
    return i;
241
0
}
242
243
/**
244
 * Produce a bound for a given sortkey and a number of levels.
245
 */
246
U_CAPI int32_t U_EXPORT2
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
0
{
255
    // consistency checks
256
0
    if(status == NULL || U_FAILURE(*status)) {
257
0
        return 0;
258
0
    }
259
0
    if(source == NULL) {
260
0
        *status = U_ILLEGAL_ARGUMENT_ERROR;
261
0
        return 0;
262
0
    }
263
264
0
    int32_t sourceIndex = 0;
265
    // Scan the string until we skip enough of the key OR reach the end of the key
266
0
    do {
267
0
        sourceIndex++;
268
0
        if(source[sourceIndex] == Collation::LEVEL_SEPARATOR_BYTE) {
269
0
            noOfLevels--;
270
0
        }
271
0
    } while (noOfLevels > 0
272
0
        && (source[sourceIndex] != 0 || sourceIndex < sourceLength));
273
274
0
    if((source[sourceIndex] == 0 || sourceIndex == sourceLength)
275
0
        && noOfLevels > 0) {
276
0
            *status = U_SORT_KEY_TOO_SHORT_WARNING;
277
0
    }
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
0
    if(result != NULL && resultLength >= sourceIndex+boundType) {
285
0
        uprv_memcpy(result, source, sourceIndex);
286
0
        switch(boundType) {
287
            // Lower bound just gets terminated. No extra bytes
288
0
        case UCOL_BOUND_LOWER: // = 0
289
0
            break;
290
            // Upper bound needs one extra byte
291
0
        case UCOL_BOUND_UPPER: // = 1
292
0
            result[sourceIndex++] = 2;
293
0
            break;
294
            // Upper long bound needs two extra bytes
295
0
        case UCOL_BOUND_UPPER_LONG: // = 2
296
0
            result[sourceIndex++] = 0xFF;
297
0
            result[sourceIndex++] = 0xFF;
298
0
            break;
299
0
        default:
300
0
            *status = U_ILLEGAL_ARGUMENT_ERROR;
301
0
            return 0;
302
0
        }
303
0
        result[sourceIndex++] = 0;
304
305
0
        return sourceIndex;
306
0
    } else {
307
0
        return sourceIndex+boundType+1;
308
0
    }
309
0
}
310
311
U_CAPI void U_EXPORT2
312
0
ucol_setMaxVariable(UCollator *coll, UColReorderCode group, UErrorCode *pErrorCode) {
313
0
    if(U_FAILURE(*pErrorCode)) { return; }
314
0
    Collator::fromUCollator(coll)->setMaxVariable(group, *pErrorCode);
315
0
}
316
317
U_CAPI UColReorderCode U_EXPORT2
318
0
ucol_getMaxVariable(const UCollator *coll) {
319
0
    return Collator::fromUCollator(coll)->getMaxVariable();
320
0
}
321
322
U_CAPI uint32_t  U_EXPORT2
323
0
ucol_setVariableTop(UCollator *coll, const UChar *varTop, int32_t len, UErrorCode *status) {
324
0
    if(U_FAILURE(*status) || coll == NULL) {
325
0
        return 0;
326
0
    }
327
0
    return Collator::fromUCollator(coll)->setVariableTop(varTop, len, *status);
328
0
}
329
330
0
U_CAPI uint32_t U_EXPORT2 ucol_getVariableTop(const UCollator *coll, UErrorCode *status) {
331
0
    if(U_FAILURE(*status) || coll == NULL) {
332
0
        return 0;
333
0
    }
334
0
    return Collator::fromUCollator(coll)->getVariableTop(*status);
335
0
}
336
337
U_CAPI void  U_EXPORT2
338
0
ucol_restoreVariableTop(UCollator *coll, const uint32_t varTop, UErrorCode *status) {
339
0
    if(U_FAILURE(*status) || coll == NULL) {
340
0
        return;
341
0
    }
342
0
    Collator::fromUCollator(coll)->setVariableTop(varTop, *status);
343
0
}
344
345
U_CAPI void  U_EXPORT2
346
0
ucol_setAttribute(UCollator *coll, UColAttribute attr, UColAttributeValue value, UErrorCode *status) {
347
0
    if(U_FAILURE(*status) || coll == NULL) {
348
0
      return;
349
0
    }
350
351
0
    Collator::fromUCollator(coll)->setAttribute(attr, value, *status);
352
0
}
353
354
U_CAPI UColAttributeValue  U_EXPORT2
355
0
ucol_getAttribute(const UCollator *coll, UColAttribute attr, UErrorCode *status) {
356
0
    if(U_FAILURE(*status) || coll == NULL) {
357
0
      return UCOL_DEFAULT;
358
0
    }
359
360
0
    return Collator::fromUCollator(coll)->getAttribute(attr, *status);
361
0
}
362
363
U_CAPI void U_EXPORT2
364
ucol_setStrength(    UCollator                *coll,
365
            UCollationStrength        strength)
366
0
{
367
0
    UErrorCode status = U_ZERO_ERROR;
368
0
    ucol_setAttribute(coll, UCOL_STRENGTH, strength, &status);
369
0
}
370
371
U_CAPI UCollationStrength U_EXPORT2
372
ucol_getStrength(const UCollator *coll)
373
0
{
374
0
    UErrorCode status = U_ZERO_ERROR;
375
0
    return ucol_getAttribute(coll, UCOL_STRENGTH, &status);
376
0
}
377
378
U_CAPI int32_t U_EXPORT2 
379
ucol_getReorderCodes(const UCollator *coll,
380
                    int32_t *dest,
381
                    int32_t destCapacity,
382
0
                    UErrorCode *status) {
383
0
    if (U_FAILURE(*status)) {
384
0
        return 0;
385
0
    }
386
387
0
    return Collator::fromUCollator(coll)->getReorderCodes(dest, destCapacity, *status);
388
0
}
389
390
U_CAPI void U_EXPORT2 
391
ucol_setReorderCodes(UCollator* coll,
392
                    const int32_t* reorderCodes,
393
                    int32_t reorderCodesLength,
394
0
                    UErrorCode *status) {
395
0
    if (U_FAILURE(*status)) {
396
0
        return;
397
0
    }
398
399
0
    Collator::fromUCollator(coll)->setReorderCodes(reorderCodes, reorderCodesLength, *status);
400
0
}
401
402
U_CAPI int32_t U_EXPORT2 
403
ucol_getEquivalentReorderCodes(int32_t reorderCode,
404
                    int32_t* dest,
405
                    int32_t destCapacity,
406
0
                    UErrorCode *pErrorCode) {
407
0
    return Collator::getEquivalentReorderCodes(reorderCode, dest, destCapacity, *pErrorCode);
408
0
}
409
410
U_CAPI void U_EXPORT2
411
ucol_getVersion(const UCollator* coll,
412
                UVersionInfo versionInfo)
413
0
{
414
0
    Collator::fromUCollator(coll)->getVersion(versionInfo);
415
0
}
416
417
U_CAPI UCollationResult U_EXPORT2
418
ucol_strcollIter( const UCollator    *coll,
419
                 UCharIterator *sIter,
420
                 UCharIterator *tIter,
421
                 UErrorCode         *status)
422
0
{
423
0
    if(!status || U_FAILURE(*status)) {
424
0
        return UCOL_EQUAL;
425
0
    }
426
427
0
    UTRACE_ENTRY(UTRACE_UCOL_STRCOLLITER);
428
0
    UTRACE_DATA3(UTRACE_VERBOSE, "coll=%p, sIter=%p, tIter=%p", coll, sIter, tIter);
429
430
0
    if(sIter == NULL || tIter == NULL || coll == NULL) {
431
0
        *status = U_ILLEGAL_ARGUMENT_ERROR;
432
0
        UTRACE_EXIT_VALUE_STATUS(UCOL_EQUAL, *status);
433
0
        return UCOL_EQUAL;
434
0
    }
435
436
0
    UCollationResult result = Collator::fromUCollator(coll)->compare(*sIter, *tIter, *status);
437
438
0
    UTRACE_EXIT_VALUE_STATUS(result, *status);
439
0
    return result;
440
0
}
441
442
443
/*                                                                      */
444
/* ucol_strcoll     Main public API string comparison function          */
445
/*                                                                      */
446
U_CAPI UCollationResult U_EXPORT2
447
ucol_strcoll( const UCollator    *coll,
448
              const UChar        *source,
449
              int32_t            sourceLength,
450
              const UChar        *target,
451
              int32_t            targetLength)
452
0
{
453
0
    UTRACE_ENTRY(UTRACE_UCOL_STRCOLL);
454
0
    if (UTRACE_LEVEL(UTRACE_VERBOSE)) {
455
0
        UTRACE_DATA3(UTRACE_VERBOSE, "coll=%p, source=%p, target=%p", coll, source, target);
456
0
        UTRACE_DATA2(UTRACE_VERBOSE, "source string = %vh ", source, sourceLength);
457
0
        UTRACE_DATA2(UTRACE_VERBOSE, "target string = %vh ", target, targetLength);
458
0
    }
459
460
0
    UErrorCode status = U_ZERO_ERROR;
461
0
    UCollationResult returnVal = Collator::fromUCollator(coll)->
462
0
            compare(source, sourceLength, target, targetLength, status);
463
0
    UTRACE_EXIT_VALUE_STATUS(returnVal, status);
464
0
    return returnVal;
465
0
}
466
467
U_CAPI UCollationResult U_EXPORT2
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
0
{
476
0
    UTRACE_ENTRY(UTRACE_UCOL_STRCOLLUTF8);
477
0
    if (UTRACE_LEVEL(UTRACE_VERBOSE)) {
478
0
        UTRACE_DATA3(UTRACE_VERBOSE, "coll=%p, source=%p, target=%p", coll, source, target);
479
0
        UTRACE_DATA2(UTRACE_VERBOSE, "source string = %vb ", source, sourceLength);
480
0
        UTRACE_DATA2(UTRACE_VERBOSE, "target string = %vb ", target, targetLength);
481
0
    }
482
483
0
    if (U_FAILURE(*status)) {
484
        /* do nothing */
485
0
        UTRACE_EXIT_VALUE_STATUS(UCOL_EQUAL, *status);
486
0
        return UCOL_EQUAL;
487
0
    }
488
489
0
    UCollationResult returnVal = Collator::fromUCollator(coll)->internalCompareUTF8(
490
0
            source, sourceLength, target, targetLength, *status);
491
0
    UTRACE_EXIT_VALUE_STATUS(returnVal, *status);
492
0
    return returnVal;
493
0
}
494
495
496
/* convenience function for comparing strings */
497
U_CAPI UBool U_EXPORT2
498
ucol_greater(    const    UCollator        *coll,
499
        const    UChar            *source,
500
        int32_t            sourceLength,
501
        const    UChar            *target,
502
        int32_t            targetLength)
503
0
{
504
0
    return (ucol_strcoll(coll, source, sourceLength, target, targetLength)
505
0
        == UCOL_GREATER);
506
0
}
507
508
/* convenience function for comparing strings */
509
U_CAPI UBool U_EXPORT2
510
ucol_greaterOrEqual(    const    UCollator    *coll,
511
            const    UChar        *source,
512
            int32_t        sourceLength,
513
            const    UChar        *target,
514
            int32_t        targetLength)
515
0
{
516
0
    return (ucol_strcoll(coll, source, sourceLength, target, targetLength)
517
0
        != UCOL_LESS);
518
0
}
519
520
/* convenience function for comparing strings */
521
U_CAPI UBool U_EXPORT2
522
ucol_equal(        const    UCollator        *coll,
523
            const    UChar            *source,
524
            int32_t            sourceLength,
525
            const    UChar            *target,
526
            int32_t            targetLength)
527
0
{
528
0
    return (ucol_strcoll(coll, source, sourceLength, target, targetLength)
529
0
        == UCOL_EQUAL);
530
0
}
531
532
U_CAPI void U_EXPORT2
533
0
ucol_getUCAVersion(const UCollator* coll, UVersionInfo info) {
534
0
    const Collator *c = Collator::fromUCollator(coll);
535
0
    if(c != NULL) {
536
0
        UVersionInfo v;
537
0
        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
0
        info[0] = v[1] >> 3;
545
0
        info[1] = v[1] & 7;
546
0
        info[2] = v[2] >> 6;
547
0
        info[3] = 0;
548
0
    }
549
0
}
550
551
U_CAPI const UChar * U_EXPORT2
552
0
ucol_getRules(const UCollator *coll, int32_t *length) {
553
0
    const RuleBasedCollator *rbc = RuleBasedCollator::rbcFromUCollator(coll);
554
    // OK to crash if coll==NULL: We do not want to check "this" pointers.
555
0
    if(rbc != NULL || coll == NULL) {
556
0
        const UnicodeString &rules = rbc->getRules();
557
0
        U_ASSERT(rules.getBuffer()[rules.length()] == 0);
558
0
        *length = rules.length();
559
0
        return rules.getBuffer();
560
0
    }
561
0
    static const UChar _NUL = 0;
562
0
    *length = 0;
563
0
    return &_NUL;
564
0
}
565
566
U_CAPI int32_t U_EXPORT2
567
0
ucol_getRulesEx(const UCollator *coll, UColRuleOption delta, UChar *buffer, int32_t bufferLen) {
568
0
    UnicodeString rules;
569
0
    const RuleBasedCollator *rbc = RuleBasedCollator::rbcFromUCollator(coll);
570
0
    if(rbc != NULL || coll == NULL) {
571
0
        rbc->getRules(delta, rules);
572
0
    }
573
0
    if(buffer != NULL && bufferLen > 0) {
574
0
        UErrorCode errorCode = U_ZERO_ERROR;
575
0
        return rules.extract(buffer, bufferLen, errorCode);
576
0
    } else {
577
0
        return rules.length();
578
0
    }
579
0
}
580
581
U_CAPI const char * U_EXPORT2
582
0
ucol_getLocale(const UCollator *coll, ULocDataLocaleType type, UErrorCode *status) {
583
0
    return ucol_getLocaleByType(coll, type, status);
584
0
}
585
586
U_CAPI const char * U_EXPORT2
587
0
ucol_getLocaleByType(const UCollator *coll, ULocDataLocaleType type, UErrorCode *status) {
588
0
    if(U_FAILURE(*status)) {
589
0
        return NULL;
590
0
    }
591
0
    UTRACE_ENTRY(UTRACE_UCOL_GETLOCALE);
592
0
    UTRACE_DATA1(UTRACE_INFO, "coll=%p", coll);
593
594
0
    const char *result;
595
0
    const RuleBasedCollator *rbc = RuleBasedCollator::rbcFromUCollator(coll);
596
0
    if(rbc == NULL && coll != NULL) {
597
0
        *status = U_UNSUPPORTED_ERROR;
598
0
        result = NULL;
599
0
    } else {
600
0
        result = rbc->internalGetLocaleID(type, *status);
601
0
    }
602
603
0
    UTRACE_DATA1(UTRACE_INFO, "result = %s", result);
604
0
    UTRACE_EXIT_STATUS(*status);
605
0
    return result;
606
0
}
607
608
U_CAPI USet * U_EXPORT2
609
0
ucol_getTailoredSet(const UCollator *coll, UErrorCode *status) {
610
0
    if(U_FAILURE(*status)) {
611
0
        return NULL;
612
0
    }
613
0
    UnicodeSet *set = Collator::fromUCollator(coll)->getTailoredSet(*status);
614
0
    if(U_FAILURE(*status)) {
615
0
        delete set;
616
0
        return NULL;
617
0
    }
618
0
    return set->toUSet();
619
0
}
620
621
U_CAPI UBool U_EXPORT2
622
0
ucol_equals(const UCollator *source, const UCollator *target) {
623
0
    return source == target ||
624
0
        (*Collator::fromUCollator(source)) == (*Collator::fromUCollator(target));
625
0
}
626
627
#endif /* #if !UCONFIG_NO_COLLATION */