12e5b6d6dSopenharmony_ci// © 2016 and later: Unicode, Inc. and others. 22e5b6d6dSopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html 32e5b6d6dSopenharmony_ci/* 42e5b6d6dSopenharmony_ci******************************************************************************* 52e5b6d6dSopenharmony_ci* Copyright (C) 2013-2014, International Business Machines 62e5b6d6dSopenharmony_ci* Corporation and others. All Rights Reserved. 72e5b6d6dSopenharmony_ci******************************************************************************* 82e5b6d6dSopenharmony_ci* collationrootelements.cpp 92e5b6d6dSopenharmony_ci* 102e5b6d6dSopenharmony_ci* created on: 2013mar05 112e5b6d6dSopenharmony_ci* created by: Markus W. Scherer 122e5b6d6dSopenharmony_ci*/ 132e5b6d6dSopenharmony_ci 142e5b6d6dSopenharmony_ci#include "unicode/utypes.h" 152e5b6d6dSopenharmony_ci 162e5b6d6dSopenharmony_ci#if !UCONFIG_NO_COLLATION 172e5b6d6dSopenharmony_ci 182e5b6d6dSopenharmony_ci#include "collation.h" 192e5b6d6dSopenharmony_ci#include "collationrootelements.h" 202e5b6d6dSopenharmony_ci#include "uassert.h" 212e5b6d6dSopenharmony_ci 222e5b6d6dSopenharmony_ciU_NAMESPACE_BEGIN 232e5b6d6dSopenharmony_ci 242e5b6d6dSopenharmony_ciint64_t 252e5b6d6dSopenharmony_ciCollationRootElements::lastCEWithPrimaryBefore(uint32_t p) const { 262e5b6d6dSopenharmony_ci if(p == 0) { return 0; } 272e5b6d6dSopenharmony_ci U_ASSERT(p > elements[elements[IX_FIRST_PRIMARY_INDEX]]); 282e5b6d6dSopenharmony_ci int32_t index = findP(p); 292e5b6d6dSopenharmony_ci uint32_t q = elements[index]; 302e5b6d6dSopenharmony_ci uint32_t secTer; 312e5b6d6dSopenharmony_ci if(p == (q & 0xffffff00)) { 322e5b6d6dSopenharmony_ci // p == elements[index] is a root primary. Find the CE before it. 332e5b6d6dSopenharmony_ci // We must not be in a primary range. 342e5b6d6dSopenharmony_ci U_ASSERT((q & PRIMARY_STEP_MASK) == 0); 352e5b6d6dSopenharmony_ci secTer = elements[index - 1]; 362e5b6d6dSopenharmony_ci if((secTer & SEC_TER_DELTA_FLAG) == 0) { 372e5b6d6dSopenharmony_ci // Primary CE just before p. 382e5b6d6dSopenharmony_ci p = secTer & 0xffffff00; 392e5b6d6dSopenharmony_ci secTer = Collation::COMMON_SEC_AND_TER_CE; 402e5b6d6dSopenharmony_ci } else { 412e5b6d6dSopenharmony_ci // secTer = last secondary & tertiary for the previous primary 422e5b6d6dSopenharmony_ci index -= 2; 432e5b6d6dSopenharmony_ci for(;;) { 442e5b6d6dSopenharmony_ci p = elements[index]; 452e5b6d6dSopenharmony_ci if((p & SEC_TER_DELTA_FLAG) == 0) { 462e5b6d6dSopenharmony_ci p &= 0xffffff00; 472e5b6d6dSopenharmony_ci break; 482e5b6d6dSopenharmony_ci } 492e5b6d6dSopenharmony_ci --index; 502e5b6d6dSopenharmony_ci } 512e5b6d6dSopenharmony_ci } 522e5b6d6dSopenharmony_ci } else { 532e5b6d6dSopenharmony_ci // p > elements[index] which is the previous primary. 542e5b6d6dSopenharmony_ci // Find the last secondary & tertiary weights for it. 552e5b6d6dSopenharmony_ci p = q & 0xffffff00; 562e5b6d6dSopenharmony_ci secTer = Collation::COMMON_SEC_AND_TER_CE; 572e5b6d6dSopenharmony_ci for(;;) { 582e5b6d6dSopenharmony_ci q = elements[++index]; 592e5b6d6dSopenharmony_ci if((q & SEC_TER_DELTA_FLAG) == 0) { 602e5b6d6dSopenharmony_ci // We must not be in a primary range. 612e5b6d6dSopenharmony_ci U_ASSERT((q & PRIMARY_STEP_MASK) == 0); 622e5b6d6dSopenharmony_ci break; 632e5b6d6dSopenharmony_ci } 642e5b6d6dSopenharmony_ci secTer = q; 652e5b6d6dSopenharmony_ci } 662e5b6d6dSopenharmony_ci } 672e5b6d6dSopenharmony_ci return ((int64_t)p << 32) | (secTer & ~SEC_TER_DELTA_FLAG); 682e5b6d6dSopenharmony_ci} 692e5b6d6dSopenharmony_ci 702e5b6d6dSopenharmony_ciint64_t 712e5b6d6dSopenharmony_ciCollationRootElements::firstCEWithPrimaryAtLeast(uint32_t p) const { 722e5b6d6dSopenharmony_ci if(p == 0) { return 0; } 732e5b6d6dSopenharmony_ci int32_t index = findP(p); 742e5b6d6dSopenharmony_ci if(p != (elements[index] & 0xffffff00)) { 752e5b6d6dSopenharmony_ci for(;;) { 762e5b6d6dSopenharmony_ci p = elements[++index]; 772e5b6d6dSopenharmony_ci if((p & SEC_TER_DELTA_FLAG) == 0) { 782e5b6d6dSopenharmony_ci // First primary after p. We must not be in a primary range. 792e5b6d6dSopenharmony_ci U_ASSERT((p & PRIMARY_STEP_MASK) == 0); 802e5b6d6dSopenharmony_ci break; 812e5b6d6dSopenharmony_ci } 822e5b6d6dSopenharmony_ci } 832e5b6d6dSopenharmony_ci } 842e5b6d6dSopenharmony_ci // The code above guarantees that p has at most 3 bytes: (p & 0xff) == 0. 852e5b6d6dSopenharmony_ci return ((int64_t)p << 32) | Collation::COMMON_SEC_AND_TER_CE; 862e5b6d6dSopenharmony_ci} 872e5b6d6dSopenharmony_ci 882e5b6d6dSopenharmony_ciuint32_t 892e5b6d6dSopenharmony_ciCollationRootElements::getPrimaryBefore(uint32_t p, UBool isCompressible) const { 902e5b6d6dSopenharmony_ci int32_t index = findPrimary(p); 912e5b6d6dSopenharmony_ci int32_t step; 922e5b6d6dSopenharmony_ci uint32_t q = elements[index]; 932e5b6d6dSopenharmony_ci if(p == (q & 0xffffff00)) { 942e5b6d6dSopenharmony_ci // Found p itself. Return the previous primary. 952e5b6d6dSopenharmony_ci // See if p is at the end of a previous range. 962e5b6d6dSopenharmony_ci step = (int32_t)q & PRIMARY_STEP_MASK; 972e5b6d6dSopenharmony_ci if(step == 0) { 982e5b6d6dSopenharmony_ci // p is not at the end of a range. Look for the previous primary. 992e5b6d6dSopenharmony_ci do { 1002e5b6d6dSopenharmony_ci p = elements[--index]; 1012e5b6d6dSopenharmony_ci } while((p & SEC_TER_DELTA_FLAG) != 0); 1022e5b6d6dSopenharmony_ci return p & 0xffffff00; 1032e5b6d6dSopenharmony_ci } 1042e5b6d6dSopenharmony_ci } else { 1052e5b6d6dSopenharmony_ci // p is in a range, and not at the start. 1062e5b6d6dSopenharmony_ci uint32_t nextElement = elements[index + 1]; 1072e5b6d6dSopenharmony_ci U_ASSERT(isEndOfPrimaryRange(nextElement)); 1082e5b6d6dSopenharmony_ci step = (int32_t)nextElement & PRIMARY_STEP_MASK; 1092e5b6d6dSopenharmony_ci } 1102e5b6d6dSopenharmony_ci // Return the previous range primary. 1112e5b6d6dSopenharmony_ci if((p & 0xffff) == 0) { 1122e5b6d6dSopenharmony_ci return Collation::decTwoBytePrimaryByOneStep(p, isCompressible, step); 1132e5b6d6dSopenharmony_ci } else { 1142e5b6d6dSopenharmony_ci return Collation::decThreeBytePrimaryByOneStep(p, isCompressible, step); 1152e5b6d6dSopenharmony_ci } 1162e5b6d6dSopenharmony_ci} 1172e5b6d6dSopenharmony_ci 1182e5b6d6dSopenharmony_ciuint32_t 1192e5b6d6dSopenharmony_ciCollationRootElements::getSecondaryBefore(uint32_t p, uint32_t s) const { 1202e5b6d6dSopenharmony_ci int32_t index; 1212e5b6d6dSopenharmony_ci uint32_t previousSec, sec; 1222e5b6d6dSopenharmony_ci if(p == 0) { 1232e5b6d6dSopenharmony_ci index = (int32_t)elements[IX_FIRST_SECONDARY_INDEX]; 1242e5b6d6dSopenharmony_ci // Gap at the beginning of the secondary CE range. 1252e5b6d6dSopenharmony_ci previousSec = 0; 1262e5b6d6dSopenharmony_ci sec = elements[index] >> 16; 1272e5b6d6dSopenharmony_ci } else { 1282e5b6d6dSopenharmony_ci index = findPrimary(p) + 1; 1292e5b6d6dSopenharmony_ci previousSec = Collation::BEFORE_WEIGHT16; 1302e5b6d6dSopenharmony_ci sec = getFirstSecTerForPrimary(index) >> 16; 1312e5b6d6dSopenharmony_ci } 1322e5b6d6dSopenharmony_ci U_ASSERT(s >= sec); 1332e5b6d6dSopenharmony_ci while(s > sec) { 1342e5b6d6dSopenharmony_ci previousSec = sec; 1352e5b6d6dSopenharmony_ci U_ASSERT((elements[index] & SEC_TER_DELTA_FLAG) != 0); 1362e5b6d6dSopenharmony_ci sec = elements[index++] >> 16; 1372e5b6d6dSopenharmony_ci } 1382e5b6d6dSopenharmony_ci U_ASSERT(sec == s); 1392e5b6d6dSopenharmony_ci return previousSec; 1402e5b6d6dSopenharmony_ci} 1412e5b6d6dSopenharmony_ci 1422e5b6d6dSopenharmony_ciuint32_t 1432e5b6d6dSopenharmony_ciCollationRootElements::getTertiaryBefore(uint32_t p, uint32_t s, uint32_t t) const { 1442e5b6d6dSopenharmony_ci U_ASSERT((t & ~Collation::ONLY_TERTIARY_MASK) == 0); 1452e5b6d6dSopenharmony_ci int32_t index; 1462e5b6d6dSopenharmony_ci uint32_t previousTer, secTer; 1472e5b6d6dSopenharmony_ci if(p == 0) { 1482e5b6d6dSopenharmony_ci if(s == 0) { 1492e5b6d6dSopenharmony_ci index = (int32_t)elements[IX_FIRST_TERTIARY_INDEX]; 1502e5b6d6dSopenharmony_ci // Gap at the beginning of the tertiary CE range. 1512e5b6d6dSopenharmony_ci previousTer = 0; 1522e5b6d6dSopenharmony_ci } else { 1532e5b6d6dSopenharmony_ci index = (int32_t)elements[IX_FIRST_SECONDARY_INDEX]; 1542e5b6d6dSopenharmony_ci previousTer = Collation::BEFORE_WEIGHT16; 1552e5b6d6dSopenharmony_ci } 1562e5b6d6dSopenharmony_ci secTer = elements[index] & ~SEC_TER_DELTA_FLAG; 1572e5b6d6dSopenharmony_ci } else { 1582e5b6d6dSopenharmony_ci index = findPrimary(p) + 1; 1592e5b6d6dSopenharmony_ci previousTer = Collation::BEFORE_WEIGHT16; 1602e5b6d6dSopenharmony_ci secTer = getFirstSecTerForPrimary(index); 1612e5b6d6dSopenharmony_ci } 1622e5b6d6dSopenharmony_ci uint32_t st = (s << 16) | t; 1632e5b6d6dSopenharmony_ci while(st > secTer) { 1642e5b6d6dSopenharmony_ci if((secTer >> 16) == s) { previousTer = secTer; } 1652e5b6d6dSopenharmony_ci U_ASSERT((elements[index] & SEC_TER_DELTA_FLAG) != 0); 1662e5b6d6dSopenharmony_ci secTer = elements[index++] & ~SEC_TER_DELTA_FLAG; 1672e5b6d6dSopenharmony_ci } 1682e5b6d6dSopenharmony_ci U_ASSERT(secTer == st); 1692e5b6d6dSopenharmony_ci return previousTer & 0xffff; 1702e5b6d6dSopenharmony_ci} 1712e5b6d6dSopenharmony_ci 1722e5b6d6dSopenharmony_ciuint32_t 1732e5b6d6dSopenharmony_ciCollationRootElements::getPrimaryAfter(uint32_t p, int32_t index, UBool isCompressible) const { 1742e5b6d6dSopenharmony_ci U_ASSERT(p == (elements[index] & 0xffffff00) || isEndOfPrimaryRange(elements[index + 1])); 1752e5b6d6dSopenharmony_ci uint32_t q = elements[++index]; 1762e5b6d6dSopenharmony_ci int32_t step; 1772e5b6d6dSopenharmony_ci if((q & SEC_TER_DELTA_FLAG) == 0 && (step = (int32_t)q & PRIMARY_STEP_MASK) != 0) { 1782e5b6d6dSopenharmony_ci // Return the next primary in this range. 1792e5b6d6dSopenharmony_ci if((p & 0xffff) == 0) { 1802e5b6d6dSopenharmony_ci return Collation::incTwoBytePrimaryByOffset(p, isCompressible, step); 1812e5b6d6dSopenharmony_ci } else { 1822e5b6d6dSopenharmony_ci return Collation::incThreeBytePrimaryByOffset(p, isCompressible, step); 1832e5b6d6dSopenharmony_ci } 1842e5b6d6dSopenharmony_ci } else { 1852e5b6d6dSopenharmony_ci // Return the next primary in the list. 1862e5b6d6dSopenharmony_ci while((q & SEC_TER_DELTA_FLAG) != 0) { 1872e5b6d6dSopenharmony_ci q = elements[++index]; 1882e5b6d6dSopenharmony_ci } 1892e5b6d6dSopenharmony_ci U_ASSERT((q & PRIMARY_STEP_MASK) == 0); 1902e5b6d6dSopenharmony_ci return q; 1912e5b6d6dSopenharmony_ci } 1922e5b6d6dSopenharmony_ci} 1932e5b6d6dSopenharmony_ci 1942e5b6d6dSopenharmony_ciuint32_t 1952e5b6d6dSopenharmony_ciCollationRootElements::getSecondaryAfter(int32_t index, uint32_t s) const { 1962e5b6d6dSopenharmony_ci uint32_t secTer; 1972e5b6d6dSopenharmony_ci uint32_t secLimit; 1982e5b6d6dSopenharmony_ci if(index == 0) { 1992e5b6d6dSopenharmony_ci // primary = 0 2002e5b6d6dSopenharmony_ci U_ASSERT(s != 0); 2012e5b6d6dSopenharmony_ci index = (int32_t)elements[IX_FIRST_SECONDARY_INDEX]; 2022e5b6d6dSopenharmony_ci secTer = elements[index]; 2032e5b6d6dSopenharmony_ci // Gap at the end of the secondary CE range. 2042e5b6d6dSopenharmony_ci secLimit = 0x10000; 2052e5b6d6dSopenharmony_ci } else { 2062e5b6d6dSopenharmony_ci U_ASSERT(index >= (int32_t)elements[IX_FIRST_PRIMARY_INDEX]); 2072e5b6d6dSopenharmony_ci secTer = getFirstSecTerForPrimary(index + 1); 2082e5b6d6dSopenharmony_ci // If this is an explicit sec/ter unit, then it will be read once more. 2092e5b6d6dSopenharmony_ci // Gap for secondaries of primary CEs. 2102e5b6d6dSopenharmony_ci secLimit = getSecondaryBoundary(); 2112e5b6d6dSopenharmony_ci } 2122e5b6d6dSopenharmony_ci for(;;) { 2132e5b6d6dSopenharmony_ci uint32_t sec = secTer >> 16; 2142e5b6d6dSopenharmony_ci if(sec > s) { return sec; } 2152e5b6d6dSopenharmony_ci secTer = elements[++index]; 2162e5b6d6dSopenharmony_ci if((secTer & SEC_TER_DELTA_FLAG) == 0) { return secLimit; } 2172e5b6d6dSopenharmony_ci } 2182e5b6d6dSopenharmony_ci} 2192e5b6d6dSopenharmony_ci 2202e5b6d6dSopenharmony_ciuint32_t 2212e5b6d6dSopenharmony_ciCollationRootElements::getTertiaryAfter(int32_t index, uint32_t s, uint32_t t) const { 2222e5b6d6dSopenharmony_ci uint32_t secTer; 2232e5b6d6dSopenharmony_ci uint32_t terLimit; 2242e5b6d6dSopenharmony_ci if(index == 0) { 2252e5b6d6dSopenharmony_ci // primary = 0 2262e5b6d6dSopenharmony_ci if(s == 0) { 2272e5b6d6dSopenharmony_ci U_ASSERT(t != 0); 2282e5b6d6dSopenharmony_ci index = (int32_t)elements[IX_FIRST_TERTIARY_INDEX]; 2292e5b6d6dSopenharmony_ci // Gap at the end of the tertiary CE range. 2302e5b6d6dSopenharmony_ci terLimit = 0x4000; 2312e5b6d6dSopenharmony_ci } else { 2322e5b6d6dSopenharmony_ci index = (int32_t)elements[IX_FIRST_SECONDARY_INDEX]; 2332e5b6d6dSopenharmony_ci // Gap for tertiaries of primary/secondary CEs. 2342e5b6d6dSopenharmony_ci terLimit = getTertiaryBoundary(); 2352e5b6d6dSopenharmony_ci } 2362e5b6d6dSopenharmony_ci secTer = elements[index] & ~SEC_TER_DELTA_FLAG; 2372e5b6d6dSopenharmony_ci } else { 2382e5b6d6dSopenharmony_ci U_ASSERT(index >= (int32_t)elements[IX_FIRST_PRIMARY_INDEX]); 2392e5b6d6dSopenharmony_ci secTer = getFirstSecTerForPrimary(index + 1); 2402e5b6d6dSopenharmony_ci // If this is an explicit sec/ter unit, then it will be read once more. 2412e5b6d6dSopenharmony_ci terLimit = getTertiaryBoundary(); 2422e5b6d6dSopenharmony_ci } 2432e5b6d6dSopenharmony_ci uint32_t st = (s << 16) | t; 2442e5b6d6dSopenharmony_ci for(;;) { 2452e5b6d6dSopenharmony_ci if(secTer > st) { 2462e5b6d6dSopenharmony_ci U_ASSERT((secTer >> 16) == s); 2472e5b6d6dSopenharmony_ci return secTer & 0xffff; 2482e5b6d6dSopenharmony_ci } 2492e5b6d6dSopenharmony_ci secTer = elements[++index]; 2502e5b6d6dSopenharmony_ci // No tertiary greater than t for this primary+secondary. 2512e5b6d6dSopenharmony_ci if((secTer & SEC_TER_DELTA_FLAG) == 0 || (secTer >> 16) > s) { return terLimit; } 2522e5b6d6dSopenharmony_ci secTer &= ~SEC_TER_DELTA_FLAG; 2532e5b6d6dSopenharmony_ci } 2542e5b6d6dSopenharmony_ci} 2552e5b6d6dSopenharmony_ci 2562e5b6d6dSopenharmony_ciuint32_t 2572e5b6d6dSopenharmony_ciCollationRootElements::getFirstSecTerForPrimary(int32_t index) const { 2582e5b6d6dSopenharmony_ci uint32_t secTer = elements[index]; 2592e5b6d6dSopenharmony_ci if((secTer & SEC_TER_DELTA_FLAG) == 0) { 2602e5b6d6dSopenharmony_ci // No sec/ter delta. 2612e5b6d6dSopenharmony_ci return Collation::COMMON_SEC_AND_TER_CE; 2622e5b6d6dSopenharmony_ci } 2632e5b6d6dSopenharmony_ci secTer &= ~SEC_TER_DELTA_FLAG; 2642e5b6d6dSopenharmony_ci if(secTer > Collation::COMMON_SEC_AND_TER_CE) { 2652e5b6d6dSopenharmony_ci // Implied sec/ter. 2662e5b6d6dSopenharmony_ci return Collation::COMMON_SEC_AND_TER_CE; 2672e5b6d6dSopenharmony_ci } 2682e5b6d6dSopenharmony_ci // Explicit sec/ter below common/common. 2692e5b6d6dSopenharmony_ci return secTer; 2702e5b6d6dSopenharmony_ci} 2712e5b6d6dSopenharmony_ci 2722e5b6d6dSopenharmony_ciint32_t 2732e5b6d6dSopenharmony_ciCollationRootElements::findPrimary(uint32_t p) const { 2742e5b6d6dSopenharmony_ci // Requirement: p must occur as a root primary. 2752e5b6d6dSopenharmony_ci U_ASSERT((p & 0xff) == 0); // at most a 3-byte primary 2762e5b6d6dSopenharmony_ci int32_t index = findP(p); 2772e5b6d6dSopenharmony_ci // If p is in a range, then we just assume that p is an actual primary in this range. 2782e5b6d6dSopenharmony_ci // (Too cumbersome/expensive to check.) 2792e5b6d6dSopenharmony_ci // Otherwise, it must be an exact match. 2802e5b6d6dSopenharmony_ci U_ASSERT(isEndOfPrimaryRange(elements[index + 1]) || p == (elements[index] & 0xffffff00)); 2812e5b6d6dSopenharmony_ci return index; 2822e5b6d6dSopenharmony_ci} 2832e5b6d6dSopenharmony_ci 2842e5b6d6dSopenharmony_ciint32_t 2852e5b6d6dSopenharmony_ciCollationRootElements::findP(uint32_t p) const { 2862e5b6d6dSopenharmony_ci // p need not occur as a root primary. 2872e5b6d6dSopenharmony_ci // For example, it might be a reordering group boundary. 2882e5b6d6dSopenharmony_ci U_ASSERT((p >> 24) != Collation::UNASSIGNED_IMPLICIT_BYTE); 2892e5b6d6dSopenharmony_ci // modified binary search 2902e5b6d6dSopenharmony_ci int32_t start = (int32_t)elements[IX_FIRST_PRIMARY_INDEX]; 2912e5b6d6dSopenharmony_ci U_ASSERT(p >= elements[start]); 2922e5b6d6dSopenharmony_ci int32_t limit = length - 1; 2932e5b6d6dSopenharmony_ci U_ASSERT(elements[limit] >= PRIMARY_SENTINEL); 2942e5b6d6dSopenharmony_ci U_ASSERT(p < elements[limit]); 2952e5b6d6dSopenharmony_ci while((start + 1) < limit) { 2962e5b6d6dSopenharmony_ci // Invariant: elements[start] and elements[limit] are primaries, 2972e5b6d6dSopenharmony_ci // and elements[start]<=p<=elements[limit]. 2982e5b6d6dSopenharmony_ci int32_t i = (start + limit) / 2; 2992e5b6d6dSopenharmony_ci uint32_t q = elements[i]; 3002e5b6d6dSopenharmony_ci if((q & SEC_TER_DELTA_FLAG) != 0) { 3012e5b6d6dSopenharmony_ci // Find the next primary. 3022e5b6d6dSopenharmony_ci int32_t j = i + 1; 3032e5b6d6dSopenharmony_ci for(;;) { 3042e5b6d6dSopenharmony_ci if(j == limit) { break; } 3052e5b6d6dSopenharmony_ci q = elements[j]; 3062e5b6d6dSopenharmony_ci if((q & SEC_TER_DELTA_FLAG) == 0) { 3072e5b6d6dSopenharmony_ci i = j; 3082e5b6d6dSopenharmony_ci break; 3092e5b6d6dSopenharmony_ci } 3102e5b6d6dSopenharmony_ci ++j; 3112e5b6d6dSopenharmony_ci } 3122e5b6d6dSopenharmony_ci if((q & SEC_TER_DELTA_FLAG) != 0) { 3132e5b6d6dSopenharmony_ci // Find the preceding primary. 3142e5b6d6dSopenharmony_ci j = i - 1; 3152e5b6d6dSopenharmony_ci for(;;) { 3162e5b6d6dSopenharmony_ci if(j == start) { break; } 3172e5b6d6dSopenharmony_ci q = elements[j]; 3182e5b6d6dSopenharmony_ci if((q & SEC_TER_DELTA_FLAG) == 0) { 3192e5b6d6dSopenharmony_ci i = j; 3202e5b6d6dSopenharmony_ci break; 3212e5b6d6dSopenharmony_ci } 3222e5b6d6dSopenharmony_ci --j; 3232e5b6d6dSopenharmony_ci } 3242e5b6d6dSopenharmony_ci if((q & SEC_TER_DELTA_FLAG) != 0) { 3252e5b6d6dSopenharmony_ci // No primary between start and limit. 3262e5b6d6dSopenharmony_ci break; 3272e5b6d6dSopenharmony_ci } 3282e5b6d6dSopenharmony_ci } 3292e5b6d6dSopenharmony_ci } 3302e5b6d6dSopenharmony_ci if(p < (q & 0xffffff00)) { // Reset the "step" bits of a range end primary. 3312e5b6d6dSopenharmony_ci limit = i; 3322e5b6d6dSopenharmony_ci } else { 3332e5b6d6dSopenharmony_ci start = i; 3342e5b6d6dSopenharmony_ci } 3352e5b6d6dSopenharmony_ci } 3362e5b6d6dSopenharmony_ci return start; 3372e5b6d6dSopenharmony_ci} 3382e5b6d6dSopenharmony_ci 3392e5b6d6dSopenharmony_ciU_NAMESPACE_END 3402e5b6d6dSopenharmony_ci 3412e5b6d6dSopenharmony_ci#endif // !UCONFIG_NO_COLLATION 342