1fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius/* 2fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius******************************************************************************* 31b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert* Copyright (C) 2013-2015, International Business Machines 4fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Corporation and others. All Rights Reserved. 5fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius******************************************************************************* 6fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* collationsettings.cpp 7fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* 8fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* created on: 2013feb07 9fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* created by: Markus W. Scherer 10fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius*/ 11fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 12fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/utypes.h" 13fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 14fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if !UCONFIG_NO_COLLATION 15fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 16fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/ucol.h" 17fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "cmemory.h" 18fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collation.h" 191b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert#include "collationdata.h" 20fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "collationsettings.h" 21fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "sharedobject.h" 22fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "uassert.h" 23fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "umutex.h" 241b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert#include "uvectr32.h" 25fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 26fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_BEGIN 27fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 28fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationSettings::CollationSettings(const CollationSettings &other) 29fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius : SharedObject(other), 30fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options(other.options), variableTop(other.variableTop), 31fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius reorderTable(NULL), 321b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert minHighNoReorder(other.minHighNoReorder), 331b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderRanges(NULL), reorderRangesLength(0), 34fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius reorderCodes(NULL), reorderCodesLength(0), reorderCodesCapacity(0), 35fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius fastLatinOptions(other.fastLatinOptions) { 361b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UErrorCode errorCode = U_ZERO_ERROR; 371b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert copyReorderingFrom(other, errorCode); 38fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(fastLatinOptions >= 0) { 39fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_memcpy(fastLatinPrimaries, other.fastLatinPrimaries, sizeof(fastLatinPrimaries)); 40fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 41fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 42fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 43fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationSettings::~CollationSettings() { 44fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(reorderCodesCapacity != 0) { 45fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_free(const_cast<int32_t *>(reorderCodes)); 46fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 47fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 48fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 49fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUBool 50fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationSettings::operator==(const CollationSettings &other) const { 51fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(options != other.options) { return FALSE; } 52fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if((options & ALTERNATE_MASK) != 0 && variableTop != other.variableTop) { return FALSE; } 53fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(reorderCodesLength != other.reorderCodesLength) { return FALSE; } 54fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for(int32_t i = 0; i < reorderCodesLength; ++i) { 55fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(reorderCodes[i] != other.reorderCodes[i]) { return FALSE; } 56fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 57fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return TRUE; 58fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 59fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 60fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusint32_t 61fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationSettings::hashCode() const { 62fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t h = options << 8; 63fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if((options & ALTERNATE_MASK) != 0) { h ^= variableTop; } 64fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius h ^= reorderCodesLength; 65fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for(int32_t i = 0; i < reorderCodesLength; ++i) { 66fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius h ^= (reorderCodes[i] << i); 67fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 68fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return h; 69fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 70fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 71fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid 72fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationSettings::resetReordering() { 73fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // When we turn off reordering, we want to set a NULL permutation 74fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // rather than a no-op permutation. 75fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Keep the memory via reorderCodes and its capacity. 76fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius reorderTable = NULL; 771b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert minHighNoReorder = 0; 781b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderRangesLength = 0; 79fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius reorderCodesLength = 0; 80fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 81fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 82fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid 831b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertCollationSettings::aliasReordering(const CollationData &data, const int32_t *codes, int32_t length, 841b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert const uint32_t *ranges, int32_t rangesLength, 851b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert const uint8_t *table, UErrorCode &errorCode) { 861b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(U_FAILURE(errorCode)) { return; } 871b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(table != NULL && 881b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert (rangesLength == 0 ? 891b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert !reorderTableHasSplitBytes(table) : 901b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert rangesLength >= 2 && 911b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // The first offset must be 0. The last offset must not be 0. 921b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert (ranges[0] & 0xffff) == 0 && (ranges[rangesLength - 1] & 0xffff) != 0)) { 93fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // We need to release the memory before setting the alias pointer. 94fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(reorderCodesCapacity != 0) { 95fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_free(const_cast<int32_t *>(reorderCodes)); 96fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius reorderCodesCapacity = 0; 97fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 98fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius reorderTable = table; 99fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius reorderCodes = codes; 100fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius reorderCodesLength = length; 1011b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // Drop ranges before the first split byte. They are reordered by the table. 1021b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // This then speeds up reordering of the remaining ranges. 1031b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert int32_t firstSplitByteRangeIndex = 0; 1041b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert while(firstSplitByteRangeIndex < rangesLength && 1051b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert (ranges[firstSplitByteRangeIndex] & 0xff0000) == 0) { 1061b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // The second byte of the primary limit is 0. 1071b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert ++firstSplitByteRangeIndex; 1081b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 1091b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(firstSplitByteRangeIndex == rangesLength) { 1101b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert U_ASSERT(!reorderTableHasSplitBytes(table)); 1111b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert minHighNoReorder = 0; 1121b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderRanges = NULL; 1131b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderRangesLength = 0; 1141b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } else { 1151b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert U_ASSERT(table[ranges[firstSplitByteRangeIndex] >> 24] == 0); 1161b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert minHighNoReorder = ranges[rangesLength - 1] & 0xffff0000; 1171b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderRanges = ranges + firstSplitByteRangeIndex; 1181b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderRangesLength = rangesLength - firstSplitByteRangeIndex; 1191b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 1201b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return; 121fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 1221b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // Regenerate missing data. 1231b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert setReordering(data, codes, length, errorCode); 124fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 125fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 1261b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertvoid 1271b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertCollationSettings::setReordering(const CollationData &data, 1281b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert const int32_t *codes, int32_t codesLength, 1291b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UErrorCode &errorCode) { 1301b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(U_FAILURE(errorCode)) { return; } 1311b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(codesLength == 0 || (codesLength == 1 && codes[0] == UCOL_REORDER_CODE_NONE)) { 132fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius resetReordering(); 1331b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return; 1341b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 1351b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert UVector32 rangesList(errorCode); 1361b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert data.makeReorderRanges(codes, codesLength, rangesList, errorCode); 1371b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(U_FAILURE(errorCode)) { return; } 1381b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert int32_t rangesLength = rangesList.size(); 1391b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(rangesLength == 0) { 1401b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert resetReordering(); 1411b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return; 1421b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 1431b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert const uint32_t *ranges = reinterpret_cast<uint32_t *>(rangesList.getBuffer()); 1441b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // ranges[] contains at least two (limit, offset) pairs. 1451b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // The first offset must be 0. The last offset must not be 0. 1461b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // Separators (at the low end) and trailing weights (at the high end) 1471b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // are never reordered. 1481b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert U_ASSERT(rangesLength >= 2); 1491b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert U_ASSERT((ranges[0] & 0xffff) == 0 && (ranges[rangesLength - 1] & 0xffff) != 0); 1501b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert minHighNoReorder = ranges[rangesLength - 1] & 0xffff0000; 1511b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert 1521b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // Write the lead byte permutation table. 1531b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // Set a 0 for each lead byte that has a range boundary in the middle. 1541b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert uint8_t table[256]; 1551b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert int32_t b = 0; 1561b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert int32_t firstSplitByteRangeIndex = -1; 1571b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert for(int32_t i = 0; i < rangesLength; ++i) { 1581b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert uint32_t pair = ranges[i]; 1591b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert int32_t limit1 = (int32_t)(pair >> 24); 1601b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert while(b < limit1) { 1611b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert table[b] = (uint8_t)(b + pair); 1621b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert ++b; 1631b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 1641b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // Check the second byte of the limit. 1651b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if((pair & 0xff0000) != 0) { 1661b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert table[limit1] = 0; 1671b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert b = limit1 + 1; 1681b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(firstSplitByteRangeIndex < 0) { 1691b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert firstSplitByteRangeIndex = i; 170fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 171fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 172fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 1731b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert while(b <= 0xff) { 1741b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert table[b] = (uint8_t)b; 1751b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert ++b; 1761b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 1771b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(firstSplitByteRangeIndex < 0) { 1781b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // The lead byte permutation table alone suffices for reordering. 1791b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert rangesLength = 0; 1801b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } else { 1811b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // Remove the ranges below the first split byte. 1821b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert ranges += firstSplitByteRangeIndex; 1831b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert rangesLength -= firstSplitByteRangeIndex; 1841b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 1851b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert setReorderArrays(codes, codesLength, ranges, rangesLength, table, errorCode); 1861b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert} 1871b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert 1881b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertvoid 1891b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertCollationSettings::setReorderArrays(const int32_t *codes, int32_t codesLength, 1901b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert const uint32_t *ranges, int32_t rangesLength, 1911b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert const uint8_t *table, UErrorCode &errorCode) { 1921b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(U_FAILURE(errorCode)) { return; } 1931b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert int32_t *ownedCodes; 1941b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert int32_t totalLength = codesLength + rangesLength; 1951b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert U_ASSERT(totalLength > 0); 1961b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(totalLength <= reorderCodesCapacity) { 1971b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert ownedCodes = const_cast<int32_t *>(reorderCodes); 1981b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } else { 1991b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // Allocate one memory block for the codes, the ranges, and the 16-aligned table. 2001b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert int32_t capacity = (totalLength + 3) & ~3; // round up to a multiple of 4 ints 2011b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert ownedCodes = (int32_t *)uprv_malloc(capacity * 4 + 256); 2021b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(ownedCodes == NULL) { 2031b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert resetReordering(); 2041b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert errorCode = U_MEMORY_ALLOCATION_ERROR; 2051b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return; 2061b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 2071b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(reorderCodesCapacity != 0) { 2081b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert uprv_free(const_cast<int32_t *>(reorderCodes)); 2091b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 2101b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderCodes = ownedCodes; 2111b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderCodesCapacity = capacity; 2121b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 2131b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert uprv_memcpy(ownedCodes + reorderCodesCapacity, table, 256); 2141b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert uprv_memcpy(ownedCodes, codes, codesLength * 4); 2151b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert uprv_memcpy(ownedCodes + codesLength, ranges, rangesLength * 4); 2161b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderTable = reinterpret_cast<const uint8_t *>(reorderCodes + reorderCodesCapacity); 2171b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderCodesLength = codesLength; 2181b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderRanges = reinterpret_cast<uint32_t *>(ownedCodes) + codesLength; 2191b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderRangesLength = rangesLength; 2201b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert} 2211b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert 2221b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertvoid 2231b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertCollationSettings::copyReorderingFrom(const CollationSettings &other, UErrorCode &errorCode) { 2241b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(U_FAILURE(errorCode)) { return; } 2251b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(!other.hasReordering()) { 2261b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert resetReordering(); 2271b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return; 2281b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 2291b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert minHighNoReorder = other.minHighNoReorder; 2301b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(other.reorderCodesCapacity == 0) { 2311b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // The reorder arrays are aliased to memory-mapped data. 2321b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderTable = other.reorderTable; 2331b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderRanges = other.reorderRanges; 2341b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderRangesLength = other.reorderRangesLength; 2351b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderCodes = other.reorderCodes; 2361b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert reorderCodesLength = other.reorderCodesLength; 2371b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } else { 2381b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert setReorderArrays(other.reorderCodes, other.reorderCodesLength, 2391b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert other.reorderRanges, other.reorderRangesLength, 2401b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert other.reorderTable, errorCode); 2411b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 2421b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert} 2431b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert 2441b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertUBool 2451b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertCollationSettings::reorderTableHasSplitBytes(const uint8_t table[256]) { 2461b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert U_ASSERT(table[0] == 0); 2471b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert for(int32_t i = 1; i < 256; ++i) { 2481b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(table[i] == 0) { 2491b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return TRUE; 2501b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 2511b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert } 2521b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return FALSE; 2531b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert} 2541b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert 2551b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertuint32_t 2561b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertCollationSettings::reorderEx(uint32_t p) const { 2571b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert if(p >= minHighNoReorder) { return p; } 2581b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // Round up p so that its lower 16 bits are >= any offset bits. 2591b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert // Then compare q directly with (limit, offset) pairs. 2601b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert uint32_t q = p | 0xffff; 2611b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert uint32_t r; 2621b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert const uint32_t *ranges = reorderRanges; 2631b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert while(q >= (r = *ranges)) { ++ranges; } 2641b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert return p + (r << 24); 265fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 266fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 267fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid 268fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationSettings::setStrength(int32_t value, int32_t defaultOptions, UErrorCode &errorCode) { 269fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return; } 270fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t noStrength = options & ~STRENGTH_MASK; 271fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius switch(value) { 272fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_PRIMARY: 273fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_SECONDARY: 274fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_TERTIARY: 275fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_QUATERNARY: 276fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_IDENTICAL: 277fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options = noStrength | (value << STRENGTH_SHIFT); 278fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 279fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_DEFAULT: 280fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options = noStrength | (defaultOptions & STRENGTH_MASK); 281fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 282fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius default: 283fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_ILLEGAL_ARGUMENT_ERROR; 284fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 285fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 286fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 287fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 288fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid 289fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationSettings::setFlag(int32_t bit, UColAttributeValue value, 290fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t defaultOptions, UErrorCode &errorCode) { 291fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return; } 292fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius switch(value) { 293fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_ON: 294fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options |= bit; 295fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 296fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_OFF: 297fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options &= ~bit; 298fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 299fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_DEFAULT: 300fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options = (options & ~bit) | (defaultOptions & bit); 301fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 302fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius default: 303fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_ILLEGAL_ARGUMENT_ERROR; 304fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 305fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 306fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 307fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 308fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid 309fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationSettings::setCaseFirst(UColAttributeValue value, 310fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t defaultOptions, UErrorCode &errorCode) { 311fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return; } 312fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t noCaseFirst = options & ~CASE_FIRST_AND_UPPER_MASK; 313fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius switch(value) { 314fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_OFF: 315fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options = noCaseFirst; 316fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 317fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_LOWER_FIRST: 318fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options = noCaseFirst | CASE_FIRST; 319fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 320fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_UPPER_FIRST: 321fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options = noCaseFirst | CASE_FIRST_AND_UPPER_MASK; 322fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 323fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_DEFAULT: 324fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options = noCaseFirst | (defaultOptions & CASE_FIRST_AND_UPPER_MASK); 325fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 326fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius default: 327fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_ILLEGAL_ARGUMENT_ERROR; 328fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 329fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 330fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 331fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 332fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid 333fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationSettings::setAlternateHandling(UColAttributeValue value, 334fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t defaultOptions, UErrorCode &errorCode) { 335fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return; } 336fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t noAlternate = options & ~ALTERNATE_MASK; 337fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius switch(value) { 338fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_NON_IGNORABLE: 339fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options = noAlternate; 340fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 341fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_SHIFTED: 342fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options = noAlternate | SHIFTED; 343fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 344fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_DEFAULT: 345fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options = noAlternate | (defaultOptions & ALTERNATE_MASK); 346fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 347fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius default: 348fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_ILLEGAL_ARGUMENT_ERROR; 349fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 350fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 351fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 352fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 353fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid 354fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusCollationSettings::setMaxVariable(int32_t value, int32_t defaultOptions, UErrorCode &errorCode) { 355fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(U_FAILURE(errorCode)) { return; } 356fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t noMax = options & ~MAX_VARIABLE_MASK; 357fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius switch(value) { 358fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case MAX_VAR_SPACE: 359fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case MAX_VAR_PUNCT: 360fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case MAX_VAR_SYMBOL: 361fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case MAX_VAR_CURRENCY: 362fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options = noMax | (value << MAX_VARIABLE_SHIFT); 363fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 364fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case UCOL_DEFAULT: 365fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius options = noMax | (defaultOptions & MAX_VARIABLE_MASK); 366fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 367fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius default: 368fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius errorCode = U_ILLEGAL_ARGUMENT_ERROR; 369fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 370fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 371fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 372fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 373fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_END 374fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 375fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif // !UCONFIG_NO_COLLATION 376