ucol.cpp 20 KB

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