Index: source/i18n/collationrootelements.cpp |
diff --git a/source/i18n/collationrootelements.cpp b/source/i18n/collationrootelements.cpp |
index d59048b75b7c9c3905947e3e751b5bc0aaa618f3..c8fd0a09ffd37e2b7e2734eb3e12024b5cda3265 100644 |
--- a/source/i18n/collationrootelements.cpp |
+++ b/source/i18n/collationrootelements.cpp |
@@ -124,8 +124,8 @@ CollationRootElements::getSecondaryBefore(uint32_t p, uint32_t s) const { |
sec = elements[index] >> 16; |
} else { |
index = findPrimary(p) + 1; |
- previousSec = Collation::MERGE_SEPARATOR_WEIGHT16; |
- sec = Collation::COMMON_WEIGHT16; |
+ previousSec = Collation::BEFORE_WEIGHT16; |
+ sec = getFirstSecTerForPrimary(index) >> 16; |
} |
U_ASSERT(s >= sec); |
while(s > sec) { |
@@ -149,13 +149,13 @@ CollationRootElements::getTertiaryBefore(uint32_t p, uint32_t s, uint32_t t) con |
previousTer = 0; |
} else { |
index = (int32_t)elements[IX_FIRST_SECONDARY_INDEX]; |
- previousTer = Collation::MERGE_SEPARATOR_WEIGHT16; |
+ previousTer = Collation::BEFORE_WEIGHT16; |
} |
secTer = elements[index] & ~SEC_TER_DELTA_FLAG; |
} else { |
index = findPrimary(p) + 1; |
- previousTer = Collation::MERGE_SEPARATOR_WEIGHT16; |
- secTer = Collation::COMMON_SEC_AND_TER_CE; |
+ previousTer = Collation::BEFORE_WEIGHT16; |
+ secTer = getFirstSecTerForPrimary(index); |
} |
uint32_t st = (s << 16) | t; |
while(st > secTer) { |
@@ -191,33 +191,38 @@ CollationRootElements::getPrimaryAfter(uint32_t p, int32_t index, UBool isCompre |
uint32_t |
CollationRootElements::getSecondaryAfter(int32_t index, uint32_t s) const { |
+ uint32_t secTer; |
uint32_t secLimit; |
if(index == 0) { |
// primary = 0 |
+ U_ASSERT(s != 0); |
index = (int32_t)elements[IX_FIRST_SECONDARY_INDEX]; |
+ secTer = elements[index]; |
// Gap at the end of the secondary CE range. |
secLimit = 0x10000; |
} else { |
U_ASSERT(index >= (int32_t)elements[IX_FIRST_PRIMARY_INDEX]); |
- ++index; |
+ secTer = getFirstSecTerForPrimary(index + 1); |
+ // If this is an explicit sec/ter unit, then it will be read once more. |
// Gap for secondaries of primary CEs. |
secLimit = getSecondaryBoundary(); |
} |
for(;;) { |
- uint32_t secTer = elements[index]; |
- if((secTer & SEC_TER_DELTA_FLAG) == 0) { return secLimit; } |
uint32_t sec = secTer >> 16; |
if(sec > s) { return sec; } |
- ++index; |
+ secTer = elements[++index]; |
+ if((secTer & SEC_TER_DELTA_FLAG) == 0) { return secLimit; } |
} |
} |
uint32_t |
CollationRootElements::getTertiaryAfter(int32_t index, uint32_t s, uint32_t t) const { |
+ uint32_t secTer; |
uint32_t terLimit; |
if(index == 0) { |
// primary = 0 |
if(s == 0) { |
+ U_ASSERT(t != 0); |
index = (int32_t)elements[IX_FIRST_TERTIARY_INDEX]; |
// Gap at the end of the tertiary CE range. |
terLimit = 0x4000; |
@@ -226,22 +231,42 @@ CollationRootElements::getTertiaryAfter(int32_t index, uint32_t s, uint32_t t) c |
// Gap for tertiaries of primary/secondary CEs. |
terLimit = getTertiaryBoundary(); |
} |
+ secTer = elements[index] & ~SEC_TER_DELTA_FLAG; |
} else { |
U_ASSERT(index >= (int32_t)elements[IX_FIRST_PRIMARY_INDEX]); |
- ++index; |
+ secTer = getFirstSecTerForPrimary(index + 1); |
+ // If this is an explicit sec/ter unit, then it will be read once more. |
terLimit = getTertiaryBoundary(); |
} |
uint32_t st = (s << 16) | t; |
for(;;) { |
- uint32_t secTer = elements[index]; |
+ if(secTer > st) { |
+ U_ASSERT((secTer >> 16) == s); |
+ return secTer & 0xffff; |
+ } |
+ secTer = elements[++index]; |
// No tertiary greater than t for this primary+secondary. |
if((secTer & SEC_TER_DELTA_FLAG) == 0 || (secTer >> 16) > s) { return terLimit; } |
secTer &= ~SEC_TER_DELTA_FLAG; |
- if(secTer > st) { return secTer & 0xffff; } |
- ++index; |
} |
} |
+uint32_t |
+CollationRootElements::getFirstSecTerForPrimary(int32_t index) const { |
+ uint32_t secTer = elements[index]; |
+ if((secTer & SEC_TER_DELTA_FLAG) == 0) { |
+ // No sec/ter delta. |
+ return Collation::COMMON_SEC_AND_TER_CE; |
+ } |
+ secTer &= ~SEC_TER_DELTA_FLAG; |
+ if(secTer > Collation::COMMON_SEC_AND_TER_CE) { |
+ // Implied sec/ter. |
+ return Collation::COMMON_SEC_AND_TER_CE; |
+ } |
+ // Explicit sec/ter below common/common. |
+ return secTer; |
+} |
+ |
int32_t |
CollationRootElements::findPrimary(uint32_t p) const { |
// Requirement: p must occur as a root primary. |