]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/collationrootelements.cpp
ICU-62141.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / collationrootelements.cpp
index d59048b75b7c9c3905947e3e751b5bc0aaa618f3..9b46d14144bb3da025112ba742720780353a91f9 100644 (file)
@@ -1,3 +1,5 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
 /*
 *******************************************************************************
 * Copyright (C) 2013-2014, International Business Machines
@@ -124,8 +126,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 +151,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 +193,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 +233,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.