diff options
author | neksard <neksard@yandex-team.ru> | 2022-02-10 16:45:33 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:33 +0300 |
commit | 1d9c550e7c38e051d7961f576013a482003a70d9 (patch) | |
tree | b2cc84ee7850122e7ccf51d0ea21e4fa7e7a5685 /contrib/libs/icu/i18n/collationcompare.cpp | |
parent | 8f7cf138264e0caa318144bf8a2c950e0b0a8593 (diff) | |
download | ydb-1d9c550e7c38e051d7961f576013a482003a70d9.tar.gz |
Restoring authorship annotation for <neksard@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/icu/i18n/collationcompare.cpp')
-rw-r--r-- | contrib/libs/icu/i18n/collationcompare.cpp | 710 |
1 files changed, 355 insertions, 355 deletions
diff --git a/contrib/libs/icu/i18n/collationcompare.cpp b/contrib/libs/icu/i18n/collationcompare.cpp index 26aa8da411..cbf32c9fe6 100644 --- a/contrib/libs/icu/i18n/collationcompare.cpp +++ b/contrib/libs/icu/i18n/collationcompare.cpp @@ -1,356 +1,356 @@ // © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 1996-2015, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************* -* collationcompare.cpp -* -* created on: 2012feb14 with new and old collation code -* created by: Markus W. Scherer -*/ - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_COLLATION - -#include "unicode/ucol.h" -#include "cmemory.h" -#include "collation.h" -#include "collationcompare.h" -#include "collationiterator.h" -#include "collationsettings.h" -#include "uassert.h" - -U_NAMESPACE_BEGIN - -UCollationResult -CollationCompare::compareUpToQuaternary(CollationIterator &left, CollationIterator &right, - const CollationSettings &settings, - UErrorCode &errorCode) { - if(U_FAILURE(errorCode)) { return UCOL_EQUAL; } - - int32_t options = settings.options; - uint32_t variableTop; - if((options & CollationSettings::ALTERNATE_MASK) == 0) { - variableTop = 0; - } else { - // +1 so that we can use "<" and primary ignorables test out early. - variableTop = settings.variableTop + 1; - } - UBool anyVariable = FALSE; - - // Fetch CEs, compare primaries, store secondary & tertiary weights. - for(;;) { - // We fetch CEs until we get a non-ignorable primary or reach the end. - uint32_t leftPrimary; - do { - int64_t ce = left.nextCE(errorCode); - leftPrimary = (uint32_t)(ce >> 32); - if(leftPrimary < variableTop && leftPrimary > Collation::MERGE_SEPARATOR_PRIMARY) { - // Variable CE, shift it to quaternary level. - // Ignore all following primary ignorables, and shift further variable CEs. - anyVariable = TRUE; - do { - // Store only the primary of the variable CE. - left.setCurrentCE(ce & INT64_C(0xffffffff00000000)); - for(;;) { - ce = left.nextCE(errorCode); - leftPrimary = (uint32_t)(ce >> 32); - if(leftPrimary == 0) { - left.setCurrentCE(0); - } else { - break; - } - } - } while(leftPrimary < variableTop && - leftPrimary > Collation::MERGE_SEPARATOR_PRIMARY); - } - } while(leftPrimary == 0); - - uint32_t rightPrimary; - do { - int64_t ce = right.nextCE(errorCode); - rightPrimary = (uint32_t)(ce >> 32); - if(rightPrimary < variableTop && rightPrimary > Collation::MERGE_SEPARATOR_PRIMARY) { - // Variable CE, shift it to quaternary level. - // Ignore all following primary ignorables, and shift further variable CEs. - anyVariable = TRUE; - do { - // Store only the primary of the variable CE. - right.setCurrentCE(ce & INT64_C(0xffffffff00000000)); - for(;;) { - ce = right.nextCE(errorCode); - rightPrimary = (uint32_t)(ce >> 32); - if(rightPrimary == 0) { - right.setCurrentCE(0); - } else { - break; - } - } - } while(rightPrimary < variableTop && - rightPrimary > Collation::MERGE_SEPARATOR_PRIMARY); - } - } while(rightPrimary == 0); - - if(leftPrimary != rightPrimary) { - // Return the primary difference, with script reordering. - if(settings.hasReordering()) { - leftPrimary = settings.reorder(leftPrimary); - rightPrimary = settings.reorder(rightPrimary); - } - return (leftPrimary < rightPrimary) ? UCOL_LESS : UCOL_GREATER; - } - if(leftPrimary == Collation::NO_CE_PRIMARY) { break; } - } - if(U_FAILURE(errorCode)) { return UCOL_EQUAL; } - - // Compare the buffered secondary & tertiary weights. - // We might skip the secondary level but continue with the case level - // which is turned on separately. - if(CollationSettings::getStrength(options) >= UCOL_SECONDARY) { - if((options & CollationSettings::BACKWARD_SECONDARY) == 0) { - int32_t leftIndex = 0; - int32_t rightIndex = 0; - for(;;) { - uint32_t leftSecondary; - do { - leftSecondary = ((uint32_t)left.getCE(leftIndex++)) >> 16; - } while(leftSecondary == 0); - - uint32_t rightSecondary; - do { - rightSecondary = ((uint32_t)right.getCE(rightIndex++)) >> 16; - } while(rightSecondary == 0); - - if(leftSecondary != rightSecondary) { - return (leftSecondary < rightSecondary) ? UCOL_LESS : UCOL_GREATER; - } - if(leftSecondary == Collation::NO_CE_WEIGHT16) { break; } - } - } else { - // The backwards secondary level compares secondary weights backwards - // within segments separated by the merge separator (U+FFFE, weight 02). - int32_t leftStart = 0; - int32_t rightStart = 0; - for(;;) { - // Find the merge separator or the NO_CE terminator. - uint32_t p; - int32_t leftLimit = leftStart; - while((p = (uint32_t)(left.getCE(leftLimit) >> 32)) > - Collation::MERGE_SEPARATOR_PRIMARY || - p == 0) { - ++leftLimit; - } - int32_t rightLimit = rightStart; - while((p = (uint32_t)(right.getCE(rightLimit) >> 32)) > - Collation::MERGE_SEPARATOR_PRIMARY || - p == 0) { - ++rightLimit; - } - - // Compare the segments. - int32_t leftIndex = leftLimit; - int32_t rightIndex = rightLimit; - for(;;) { - int32_t leftSecondary = 0; - while(leftSecondary == 0 && leftIndex > leftStart) { - leftSecondary = ((uint32_t)left.getCE(--leftIndex)) >> 16; - } - - int32_t rightSecondary = 0; - while(rightSecondary == 0 && rightIndex > rightStart) { - rightSecondary = ((uint32_t)right.getCE(--rightIndex)) >> 16; - } - - if(leftSecondary != rightSecondary) { - return (leftSecondary < rightSecondary) ? UCOL_LESS : UCOL_GREATER; - } - if(leftSecondary == 0) { break; } - } - - // Did we reach the end of either string? - // Both strings have the same number of merge separators, - // or else there would have been a primary-level difference. - U_ASSERT(left.getCE(leftLimit) == right.getCE(rightLimit)); - if(p == Collation::NO_CE_PRIMARY) { break; } - // Skip both merge separators and continue. - leftStart = leftLimit + 1; - rightStart = rightLimit + 1; - } - } - } - - if((options & CollationSettings::CASE_LEVEL) != 0) { - int32_t strength = CollationSettings::getStrength(options); - int32_t leftIndex = 0; - int32_t rightIndex = 0; - for(;;) { - uint32_t leftCase, leftLower32, rightCase; - if(strength == UCOL_PRIMARY) { - // Primary+caseLevel: Ignore case level weights of primary ignorables. - // Otherwise we would get a-umlaut > a - // which is not desirable for accent-insensitive sorting. - // Check for (lower 32 bits) == 0 as well because variable CEs are stored - // with only primary weights. - int64_t ce; - do { - ce = left.getCE(leftIndex++); - leftCase = (uint32_t)ce; - } while((uint32_t)(ce >> 32) == 0 || leftCase == 0); - leftLower32 = leftCase; - leftCase &= 0xc000; - - do { - ce = right.getCE(rightIndex++); - rightCase = (uint32_t)ce; - } while((uint32_t)(ce >> 32) == 0 || rightCase == 0); - rightCase &= 0xc000; - } else { - // Secondary+caseLevel: By analogy with the above, - // ignore case level weights of secondary ignorables. - // - // Note: A tertiary CE has uppercase case bits (0.0.ut) - // to keep tertiary+caseFirst well-formed. - // - // Tertiary+caseLevel: Also ignore case level weights of secondary ignorables. - // Otherwise a tertiary CE's uppercase would be no greater than - // a primary/secondary CE's uppercase. - // (See UCA well-formedness condition 2.) - // We could construct a special case weight higher than uppercase, - // but it's simpler to always ignore case weights of secondary ignorables, - // turning 0.0.ut into 0.0.0.t. - // (See LDML Collation, Case Parameters.) - do { - leftCase = (uint32_t)left.getCE(leftIndex++); - } while(leftCase <= 0xffff); - leftLower32 = leftCase; - leftCase &= 0xc000; - - do { - rightCase = (uint32_t)right.getCE(rightIndex++); - } while(rightCase <= 0xffff); - rightCase &= 0xc000; - } - - // No need to handle NO_CE and MERGE_SEPARATOR specially: - // There is one case weight for each previous-level weight, - // so level length differences were handled there. - if(leftCase != rightCase) { - if((options & CollationSettings::UPPER_FIRST) == 0) { - return (leftCase < rightCase) ? UCOL_LESS : UCOL_GREATER; - } else { - return (leftCase < rightCase) ? UCOL_GREATER : UCOL_LESS; - } - } - if((leftLower32 >> 16) == Collation::NO_CE_WEIGHT16) { break; } - } - } - if(CollationSettings::getStrength(options) <= UCOL_SECONDARY) { return UCOL_EQUAL; } - - uint32_t tertiaryMask = CollationSettings::getTertiaryMask(options); - - int32_t leftIndex = 0; - int32_t rightIndex = 0; - uint32_t anyQuaternaries = 0; - for(;;) { - uint32_t leftLower32, leftTertiary; - do { - leftLower32 = (uint32_t)left.getCE(leftIndex++); - anyQuaternaries |= leftLower32; - U_ASSERT((leftLower32 & Collation::ONLY_TERTIARY_MASK) != 0 || - (leftLower32 & 0xc0c0) == 0); - leftTertiary = leftLower32 & tertiaryMask; - } while(leftTertiary == 0); - - uint32_t rightLower32, rightTertiary; - do { - rightLower32 = (uint32_t)right.getCE(rightIndex++); - anyQuaternaries |= rightLower32; - U_ASSERT((rightLower32 & Collation::ONLY_TERTIARY_MASK) != 0 || - (rightLower32 & 0xc0c0) == 0); - rightTertiary = rightLower32 & tertiaryMask; - } while(rightTertiary == 0); - - if(leftTertiary != rightTertiary) { - if(CollationSettings::sortsTertiaryUpperCaseFirst(options)) { - // Pass through NO_CE and keep real tertiary weights larger than that. - // Do not change the artificial uppercase weight of a tertiary CE (0.0.ut), - // to keep tertiary CEs well-formed. - // Their case+tertiary weights must be greater than those of - // primary and secondary CEs. - if(leftTertiary > Collation::NO_CE_WEIGHT16) { - if(leftLower32 > 0xffff) { - leftTertiary ^= 0xc000; - } else { - leftTertiary += 0x4000; - } - } - if(rightTertiary > Collation::NO_CE_WEIGHT16) { - if(rightLower32 > 0xffff) { - rightTertiary ^= 0xc000; - } else { - rightTertiary += 0x4000; - } - } - } - return (leftTertiary < rightTertiary) ? UCOL_LESS : UCOL_GREATER; - } - if(leftTertiary == Collation::NO_CE_WEIGHT16) { break; } - } - if(CollationSettings::getStrength(options) <= UCOL_TERTIARY) { return UCOL_EQUAL; } - - if(!anyVariable && (anyQuaternaries & 0xc0) == 0) { - // If there are no "variable" CEs and no non-zero quaternary weights, - // then there are no quaternary differences. - return UCOL_EQUAL; - } - - leftIndex = 0; - rightIndex = 0; - for(;;) { - uint32_t leftQuaternary; - do { - int64_t ce = left.getCE(leftIndex++); - leftQuaternary = (uint32_t)ce & 0xffff; - if(leftQuaternary <= Collation::NO_CE_WEIGHT16) { - // Variable primary or completely ignorable or NO_CE. - leftQuaternary = (uint32_t)(ce >> 32); - } else { - // Regular CE, not tertiary ignorable. - // Preserve the quaternary weight in bits 7..6. - leftQuaternary |= 0xffffff3f; - } - } while(leftQuaternary == 0); - - uint32_t rightQuaternary; - do { - int64_t ce = right.getCE(rightIndex++); - rightQuaternary = (uint32_t)ce & 0xffff; - if(rightQuaternary <= Collation::NO_CE_WEIGHT16) { - // Variable primary or completely ignorable or NO_CE. - rightQuaternary = (uint32_t)(ce >> 32); - } else { - // Regular CE, not tertiary ignorable. - // Preserve the quaternary weight in bits 7..6. - rightQuaternary |= 0xffffff3f; - } - } while(rightQuaternary == 0); - - if(leftQuaternary != rightQuaternary) { - // Return the difference, with script reordering. - if(settings.hasReordering()) { - leftQuaternary = settings.reorder(leftQuaternary); - rightQuaternary = settings.reorder(rightQuaternary); - } - return (leftQuaternary < rightQuaternary) ? UCOL_LESS : UCOL_GREATER; - } - if(leftQuaternary == Collation::NO_CE_PRIMARY) { break; } - } - return UCOL_EQUAL; -} - -U_NAMESPACE_END - -#endif // !UCONFIG_NO_COLLATION +// License & terms of use: http://www.unicode.org/copyright.html +/* +******************************************************************************* +* Copyright (C) 1996-2015, International Business Machines +* Corporation and others. All Rights Reserved. +******************************************************************************* +* collationcompare.cpp +* +* created on: 2012feb14 with new and old collation code +* created by: Markus W. Scherer +*/ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_COLLATION + +#include "unicode/ucol.h" +#include "cmemory.h" +#include "collation.h" +#include "collationcompare.h" +#include "collationiterator.h" +#include "collationsettings.h" +#include "uassert.h" + +U_NAMESPACE_BEGIN + +UCollationResult +CollationCompare::compareUpToQuaternary(CollationIterator &left, CollationIterator &right, + const CollationSettings &settings, + UErrorCode &errorCode) { + if(U_FAILURE(errorCode)) { return UCOL_EQUAL; } + + int32_t options = settings.options; + uint32_t variableTop; + if((options & CollationSettings::ALTERNATE_MASK) == 0) { + variableTop = 0; + } else { + // +1 so that we can use "<" and primary ignorables test out early. + variableTop = settings.variableTop + 1; + } + UBool anyVariable = FALSE; + + // Fetch CEs, compare primaries, store secondary & tertiary weights. + for(;;) { + // We fetch CEs until we get a non-ignorable primary or reach the end. + uint32_t leftPrimary; + do { + int64_t ce = left.nextCE(errorCode); + leftPrimary = (uint32_t)(ce >> 32); + if(leftPrimary < variableTop && leftPrimary > Collation::MERGE_SEPARATOR_PRIMARY) { + // Variable CE, shift it to quaternary level. + // Ignore all following primary ignorables, and shift further variable CEs. + anyVariable = TRUE; + do { + // Store only the primary of the variable CE. + left.setCurrentCE(ce & INT64_C(0xffffffff00000000)); + for(;;) { + ce = left.nextCE(errorCode); + leftPrimary = (uint32_t)(ce >> 32); + if(leftPrimary == 0) { + left.setCurrentCE(0); + } else { + break; + } + } + } while(leftPrimary < variableTop && + leftPrimary > Collation::MERGE_SEPARATOR_PRIMARY); + } + } while(leftPrimary == 0); + + uint32_t rightPrimary; + do { + int64_t ce = right.nextCE(errorCode); + rightPrimary = (uint32_t)(ce >> 32); + if(rightPrimary < variableTop && rightPrimary > Collation::MERGE_SEPARATOR_PRIMARY) { + // Variable CE, shift it to quaternary level. + // Ignore all following primary ignorables, and shift further variable CEs. + anyVariable = TRUE; + do { + // Store only the primary of the variable CE. + right.setCurrentCE(ce & INT64_C(0xffffffff00000000)); + for(;;) { + ce = right.nextCE(errorCode); + rightPrimary = (uint32_t)(ce >> 32); + if(rightPrimary == 0) { + right.setCurrentCE(0); + } else { + break; + } + } + } while(rightPrimary < variableTop && + rightPrimary > Collation::MERGE_SEPARATOR_PRIMARY); + } + } while(rightPrimary == 0); + + if(leftPrimary != rightPrimary) { + // Return the primary difference, with script reordering. + if(settings.hasReordering()) { + leftPrimary = settings.reorder(leftPrimary); + rightPrimary = settings.reorder(rightPrimary); + } + return (leftPrimary < rightPrimary) ? UCOL_LESS : UCOL_GREATER; + } + if(leftPrimary == Collation::NO_CE_PRIMARY) { break; } + } + if(U_FAILURE(errorCode)) { return UCOL_EQUAL; } + + // Compare the buffered secondary & tertiary weights. + // We might skip the secondary level but continue with the case level + // which is turned on separately. + if(CollationSettings::getStrength(options) >= UCOL_SECONDARY) { + if((options & CollationSettings::BACKWARD_SECONDARY) == 0) { + int32_t leftIndex = 0; + int32_t rightIndex = 0; + for(;;) { + uint32_t leftSecondary; + do { + leftSecondary = ((uint32_t)left.getCE(leftIndex++)) >> 16; + } while(leftSecondary == 0); + + uint32_t rightSecondary; + do { + rightSecondary = ((uint32_t)right.getCE(rightIndex++)) >> 16; + } while(rightSecondary == 0); + + if(leftSecondary != rightSecondary) { + return (leftSecondary < rightSecondary) ? UCOL_LESS : UCOL_GREATER; + } + if(leftSecondary == Collation::NO_CE_WEIGHT16) { break; } + } + } else { + // The backwards secondary level compares secondary weights backwards + // within segments separated by the merge separator (U+FFFE, weight 02). + int32_t leftStart = 0; + int32_t rightStart = 0; + for(;;) { + // Find the merge separator or the NO_CE terminator. + uint32_t p; + int32_t leftLimit = leftStart; + while((p = (uint32_t)(left.getCE(leftLimit) >> 32)) > + Collation::MERGE_SEPARATOR_PRIMARY || + p == 0) { + ++leftLimit; + } + int32_t rightLimit = rightStart; + while((p = (uint32_t)(right.getCE(rightLimit) >> 32)) > + Collation::MERGE_SEPARATOR_PRIMARY || + p == 0) { + ++rightLimit; + } + + // Compare the segments. + int32_t leftIndex = leftLimit; + int32_t rightIndex = rightLimit; + for(;;) { + int32_t leftSecondary = 0; + while(leftSecondary == 0 && leftIndex > leftStart) { + leftSecondary = ((uint32_t)left.getCE(--leftIndex)) >> 16; + } + + int32_t rightSecondary = 0; + while(rightSecondary == 0 && rightIndex > rightStart) { + rightSecondary = ((uint32_t)right.getCE(--rightIndex)) >> 16; + } + + if(leftSecondary != rightSecondary) { + return (leftSecondary < rightSecondary) ? UCOL_LESS : UCOL_GREATER; + } + if(leftSecondary == 0) { break; } + } + + // Did we reach the end of either string? + // Both strings have the same number of merge separators, + // or else there would have been a primary-level difference. + U_ASSERT(left.getCE(leftLimit) == right.getCE(rightLimit)); + if(p == Collation::NO_CE_PRIMARY) { break; } + // Skip both merge separators and continue. + leftStart = leftLimit + 1; + rightStart = rightLimit + 1; + } + } + } + + if((options & CollationSettings::CASE_LEVEL) != 0) { + int32_t strength = CollationSettings::getStrength(options); + int32_t leftIndex = 0; + int32_t rightIndex = 0; + for(;;) { + uint32_t leftCase, leftLower32, rightCase; + if(strength == UCOL_PRIMARY) { + // Primary+caseLevel: Ignore case level weights of primary ignorables. + // Otherwise we would get a-umlaut > a + // which is not desirable for accent-insensitive sorting. + // Check for (lower 32 bits) == 0 as well because variable CEs are stored + // with only primary weights. + int64_t ce; + do { + ce = left.getCE(leftIndex++); + leftCase = (uint32_t)ce; + } while((uint32_t)(ce >> 32) == 0 || leftCase == 0); + leftLower32 = leftCase; + leftCase &= 0xc000; + + do { + ce = right.getCE(rightIndex++); + rightCase = (uint32_t)ce; + } while((uint32_t)(ce >> 32) == 0 || rightCase == 0); + rightCase &= 0xc000; + } else { + // Secondary+caseLevel: By analogy with the above, + // ignore case level weights of secondary ignorables. + // + // Note: A tertiary CE has uppercase case bits (0.0.ut) + // to keep tertiary+caseFirst well-formed. + // + // Tertiary+caseLevel: Also ignore case level weights of secondary ignorables. + // Otherwise a tertiary CE's uppercase would be no greater than + // a primary/secondary CE's uppercase. + // (See UCA well-formedness condition 2.) + // We could construct a special case weight higher than uppercase, + // but it's simpler to always ignore case weights of secondary ignorables, + // turning 0.0.ut into 0.0.0.t. + // (See LDML Collation, Case Parameters.) + do { + leftCase = (uint32_t)left.getCE(leftIndex++); + } while(leftCase <= 0xffff); + leftLower32 = leftCase; + leftCase &= 0xc000; + + do { + rightCase = (uint32_t)right.getCE(rightIndex++); + } while(rightCase <= 0xffff); + rightCase &= 0xc000; + } + + // No need to handle NO_CE and MERGE_SEPARATOR specially: + // There is one case weight for each previous-level weight, + // so level length differences were handled there. + if(leftCase != rightCase) { + if((options & CollationSettings::UPPER_FIRST) == 0) { + return (leftCase < rightCase) ? UCOL_LESS : UCOL_GREATER; + } else { + return (leftCase < rightCase) ? UCOL_GREATER : UCOL_LESS; + } + } + if((leftLower32 >> 16) == Collation::NO_CE_WEIGHT16) { break; } + } + } + if(CollationSettings::getStrength(options) <= UCOL_SECONDARY) { return UCOL_EQUAL; } + + uint32_t tertiaryMask = CollationSettings::getTertiaryMask(options); + + int32_t leftIndex = 0; + int32_t rightIndex = 0; + uint32_t anyQuaternaries = 0; + for(;;) { + uint32_t leftLower32, leftTertiary; + do { + leftLower32 = (uint32_t)left.getCE(leftIndex++); + anyQuaternaries |= leftLower32; + U_ASSERT((leftLower32 & Collation::ONLY_TERTIARY_MASK) != 0 || + (leftLower32 & 0xc0c0) == 0); + leftTertiary = leftLower32 & tertiaryMask; + } while(leftTertiary == 0); + + uint32_t rightLower32, rightTertiary; + do { + rightLower32 = (uint32_t)right.getCE(rightIndex++); + anyQuaternaries |= rightLower32; + U_ASSERT((rightLower32 & Collation::ONLY_TERTIARY_MASK) != 0 || + (rightLower32 & 0xc0c0) == 0); + rightTertiary = rightLower32 & tertiaryMask; + } while(rightTertiary == 0); + + if(leftTertiary != rightTertiary) { + if(CollationSettings::sortsTertiaryUpperCaseFirst(options)) { + // Pass through NO_CE and keep real tertiary weights larger than that. + // Do not change the artificial uppercase weight of a tertiary CE (0.0.ut), + // to keep tertiary CEs well-formed. + // Their case+tertiary weights must be greater than those of + // primary and secondary CEs. + if(leftTertiary > Collation::NO_CE_WEIGHT16) { + if(leftLower32 > 0xffff) { + leftTertiary ^= 0xc000; + } else { + leftTertiary += 0x4000; + } + } + if(rightTertiary > Collation::NO_CE_WEIGHT16) { + if(rightLower32 > 0xffff) { + rightTertiary ^= 0xc000; + } else { + rightTertiary += 0x4000; + } + } + } + return (leftTertiary < rightTertiary) ? UCOL_LESS : UCOL_GREATER; + } + if(leftTertiary == Collation::NO_CE_WEIGHT16) { break; } + } + if(CollationSettings::getStrength(options) <= UCOL_TERTIARY) { return UCOL_EQUAL; } + + if(!anyVariable && (anyQuaternaries & 0xc0) == 0) { + // If there are no "variable" CEs and no non-zero quaternary weights, + // then there are no quaternary differences. + return UCOL_EQUAL; + } + + leftIndex = 0; + rightIndex = 0; + for(;;) { + uint32_t leftQuaternary; + do { + int64_t ce = left.getCE(leftIndex++); + leftQuaternary = (uint32_t)ce & 0xffff; + if(leftQuaternary <= Collation::NO_CE_WEIGHT16) { + // Variable primary or completely ignorable or NO_CE. + leftQuaternary = (uint32_t)(ce >> 32); + } else { + // Regular CE, not tertiary ignorable. + // Preserve the quaternary weight in bits 7..6. + leftQuaternary |= 0xffffff3f; + } + } while(leftQuaternary == 0); + + uint32_t rightQuaternary; + do { + int64_t ce = right.getCE(rightIndex++); + rightQuaternary = (uint32_t)ce & 0xffff; + if(rightQuaternary <= Collation::NO_CE_WEIGHT16) { + // Variable primary or completely ignorable or NO_CE. + rightQuaternary = (uint32_t)(ce >> 32); + } else { + // Regular CE, not tertiary ignorable. + // Preserve the quaternary weight in bits 7..6. + rightQuaternary |= 0xffffff3f; + } + } while(rightQuaternary == 0); + + if(leftQuaternary != rightQuaternary) { + // Return the difference, with script reordering. + if(settings.hasReordering()) { + leftQuaternary = settings.reorder(leftQuaternary); + rightQuaternary = settings.reorder(rightQuaternary); + } + return (leftQuaternary < rightQuaternary) ? UCOL_LESS : UCOL_GREATER; + } + if(leftQuaternary == Collation::NO_CE_PRIMARY) { break; } + } + return UCOL_EQUAL; +} + +U_NAMESPACE_END + +#endif // !UCONFIG_NO_COLLATION |