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