ucol.cpp 19 KB

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