/* * The collator returned by this function is owned by the callee and must be * closed when this method returns with a U_SUCCESS UErrorCode. * * On error, the return value is undefined. */ UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t options, UErrorCode* pErr) { UColAttributeValue strength = ucol_getStrength(pCollator); bool isIgnoreCase = (options & CompareOptionsIgnoreCase) == CompareOptionsIgnoreCase; bool isIgnoreNonSpace = (options & CompareOptionsIgnoreNonSpace) == CompareOptionsIgnoreNonSpace; bool isIgnoreSymbols = (options & CompareOptionsIgnoreSymbols) == CompareOptionsIgnoreSymbols; if (isIgnoreCase) { strength = UCOL_SECONDARY; } if (isIgnoreNonSpace) { strength = UCOL_PRIMARY; } UCollator* pClonedCollator; std::vector<UChar> customRules = GetCustomRules(options, strength, isIgnoreSymbols); if (customRules.empty()) { pClonedCollator = ucol_safeClone(pCollator, nullptr, nullptr, pErr); } else { int32_t customRuleLength = customRules.size(); int32_t localeRulesLength; const UChar* localeRules = ucol_getRules(pCollator, &localeRulesLength); std::vector<UChar> completeRules(localeRulesLength + customRuleLength + 1, '\0'); for (int i = 0; i < localeRulesLength; i++) { completeRules[i] = localeRules[i]; } for (int i = 0; i < customRuleLength; i++) { completeRules[localeRulesLength + i] = customRules[i]; } pClonedCollator = ucol_openRules(completeRules.data(), completeRules.size(), UCOL_DEFAULT, strength, NULL, pErr); } if (isIgnoreSymbols) { ucol_setAttribute(pClonedCollator, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, pErr); } ucol_setAttribute(pClonedCollator, UCOL_STRENGTH, strength, pErr); // casing differs at the tertiary level. // if strength is less than tertiary, but we are not ignoring case, then we need to flip CASE_LEVEL On if (strength < UCOL_TERTIARY && !isIgnoreCase) { ucol_setAttribute(pClonedCollator, UCOL_CASE_LEVEL, UCOL_ON, pErr); } return pClonedCollator; }
/* * The collator returned by this function is owned by the callee and must be * closed when this method returns with a U_SUCCESS UErrorCode. * * On error, the return value is undefined. */ UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t options, UErrorCode* pErr) { UColAttributeValue strength = ucol_getStrength(pCollator); bool isIgnoreCase = (options & CompareOptionsIgnoreCase) == CompareOptionsIgnoreCase; bool isIgnoreNonSpace = (options & CompareOptionsIgnoreNonSpace) == CompareOptionsIgnoreNonSpace; bool isIgnoreSymbols = (options & CompareOptionsIgnoreSymbols) == CompareOptionsIgnoreSymbols; if (isIgnoreCase) { strength = UCOL_SECONDARY; } if (isIgnoreNonSpace) { strength = UCOL_PRIMARY; } UCollator* pClonedCollator; std::vector<UChar> customRules = GetCustomRules(options, strength, isIgnoreSymbols); if (customRules.empty()) { pClonedCollator = ucol_safeClone(pCollator, nullptr, nullptr, pErr); } else { int32_t customRuleLength = customRules.size(); int32_t localeRulesLength; const UChar* localeRules = ucol_getRules(pCollator, &localeRulesLength); std::vector<UChar> completeRules(localeRulesLength + customRuleLength + 1, '\0'); for (int i = 0; i < localeRulesLength; i++) { completeRules[i] = localeRules[i]; } for (int i = 0; i < customRuleLength; i++) { completeRules[localeRulesLength + i] = customRules[i]; } pClonedCollator = ucol_openRules(completeRules.data(), completeRules.size(), UCOL_DEFAULT, strength, NULL, pErr); } if (isIgnoreSymbols) { ucol_setAttribute(pClonedCollator, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, pErr); // by default, ICU alternate shifted handling only ignores punctuation, but // IgnoreSymbols needs symbols and currency as well, so change the "variable top" // to include all symbols and currency #if HAVE_SET_MAX_VARIABLE ucol_setMaxVariable(pClonedCollator, UCOL_REORDER_CODE_CURRENCY, pErr); #else // 0xfdfc is the last currency character before the first digit character // in http://source.icu-project.org/repos/icu/icu/tags/release-52-1/source/data/unidata/FractionalUCA.txt const UChar ignoreSymbolsVariableTop[] = { 0xfdfc }; ucol_setVariableTop(pClonedCollator, ignoreSymbolsVariableTop, 1, pErr); #endif } ucol_setAttribute(pClonedCollator, UCOL_STRENGTH, strength, pErr); // casing differs at the tertiary level. // if strength is less than tertiary, but we are not ignoring case, then we need to flip CASE_LEVEL On if (strength < UCOL_TERTIARY && !isIgnoreCase) { ucol_setAttribute(pClonedCollator, UCOL_CASE_LEVEL, UCOL_ON, pErr); } return pClonedCollator; }