Index: source/i18n/collationsettings.cpp |
diff --git a/source/i18n/collationsettings.cpp b/source/i18n/collationsettings.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b63d6bf3a604f320d669f53ec7bcb63ba2d1ae49 |
--- /dev/null |
+++ b/source/i18n/collationsettings.cpp |
@@ -0,0 +1,238 @@ |
+/* |
+******************************************************************************* |
+* Copyright (C) 2013-2014, International Business Machines |
+* Corporation and others. All Rights Reserved. |
+******************************************************************************* |
+* collationsettings.cpp |
+* |
+* created on: 2013feb07 |
+* created by: Markus W. Scherer |
+*/ |
+ |
+#include "unicode/utypes.h" |
+ |
+#if !UCONFIG_NO_COLLATION |
+ |
+#include "unicode/ucol.h" |
+#include "cmemory.h" |
+#include "collation.h" |
+#include "collationsettings.h" |
+#include "sharedobject.h" |
+#include "uassert.h" |
+#include "umutex.h" |
+ |
+U_NAMESPACE_BEGIN |
+ |
+CollationSettings::CollationSettings(const CollationSettings &other) |
+ : SharedObject(other), |
+ options(other.options), variableTop(other.variableTop), |
+ reorderTable(NULL), |
+ reorderCodes(NULL), reorderCodesLength(0), reorderCodesCapacity(0), |
+ fastLatinOptions(other.fastLatinOptions) { |
+ int32_t length = other.reorderCodesLength; |
+ if(length == 0) { |
+ U_ASSERT(other.reorderTable == NULL); |
+ } else { |
+ U_ASSERT(other.reorderTable != NULL); |
+ if(other.reorderCodesCapacity == 0) { |
+ aliasReordering(other.reorderCodes, length, other.reorderTable); |
+ } else { |
+ setReordering(other.reorderCodes, length, other.reorderTable); |
+ } |
+ } |
+ if(fastLatinOptions >= 0) { |
+ uprv_memcpy(fastLatinPrimaries, other.fastLatinPrimaries, sizeof(fastLatinPrimaries)); |
+ } |
+} |
+ |
+CollationSettings::~CollationSettings() { |
+ if(reorderCodesCapacity != 0) { |
+ uprv_free(const_cast<int32_t *>(reorderCodes)); |
+ } |
+} |
+ |
+UBool |
+CollationSettings::operator==(const CollationSettings &other) const { |
+ if(options != other.options) { return FALSE; } |
+ if((options & ALTERNATE_MASK) != 0 && variableTop != other.variableTop) { return FALSE; } |
+ if(reorderCodesLength != other.reorderCodesLength) { return FALSE; } |
+ for(int32_t i = 0; i < reorderCodesLength; ++i) { |
+ if(reorderCodes[i] != other.reorderCodes[i]) { return FALSE; } |
+ } |
+ return TRUE; |
+} |
+ |
+int32_t |
+CollationSettings::hashCode() const { |
+ int32_t h = options << 8; |
+ if((options & ALTERNATE_MASK) != 0) { h ^= variableTop; } |
+ h ^= reorderCodesLength; |
+ for(int32_t i = 0; i < reorderCodesLength; ++i) { |
+ h ^= (reorderCodes[i] << i); |
+ } |
+ return h; |
+} |
+ |
+void |
+CollationSettings::resetReordering() { |
+ // When we turn off reordering, we want to set a NULL permutation |
+ // rather than a no-op permutation. |
+ // Keep the memory via reorderCodes and its capacity. |
+ reorderTable = NULL; |
+ reorderCodesLength = 0; |
+} |
+ |
+void |
+CollationSettings::aliasReordering(const int32_t *codes, int32_t length, const uint8_t *table) { |
+ if(length == 0) { |
+ resetReordering(); |
+ } else { |
+ // We need to release the memory before setting the alias pointer. |
+ if(reorderCodesCapacity != 0) { |
+ uprv_free(const_cast<int32_t *>(reorderCodes)); |
+ reorderCodesCapacity = 0; |
+ } |
+ reorderTable = table; |
+ reorderCodes = codes; |
+ reorderCodesLength = length; |
+ } |
+} |
+ |
+UBool |
+CollationSettings::setReordering(const int32_t *codes, int32_t length, const uint8_t table[256]) { |
+ if(length == 0) { |
+ resetReordering(); |
+ } else { |
+ uint8_t *ownedTable; |
+ int32_t *ownedCodes; |
+ if(length <= reorderCodesCapacity) { |
+ ownedTable = const_cast<uint8_t *>(reorderTable); |
+ ownedCodes = const_cast<int32_t *>(reorderCodes); |
+ } else { |
+ // Allocate one memory block for the codes and the 16-aligned table. |
+ int32_t capacity = (length + 3) & ~3; // round up to a multiple of 4 ints |
+ uint8_t *bytes = (uint8_t *)uprv_malloc(256 + capacity * 4); |
+ if(bytes == NULL) { return FALSE; } |
+ if(reorderCodesCapacity != 0) { |
+ uprv_free(const_cast<int32_t *>(reorderCodes)); |
+ } |
+ reorderTable = ownedTable = bytes + capacity * 4; |
+ reorderCodes = ownedCodes = (int32_t *)bytes; |
+ reorderCodesCapacity = capacity; |
+ } |
+ uprv_memcpy(ownedTable, table, 256); |
+ uprv_memcpy(ownedCodes, codes, length * 4); |
+ reorderCodesLength = length; |
+ } |
+ return TRUE; |
+} |
+ |
+void |
+CollationSettings::setStrength(int32_t value, int32_t defaultOptions, UErrorCode &errorCode) { |
+ if(U_FAILURE(errorCode)) { return; } |
+ int32_t noStrength = options & ~STRENGTH_MASK; |
+ switch(value) { |
+ case UCOL_PRIMARY: |
+ case UCOL_SECONDARY: |
+ case UCOL_TERTIARY: |
+ case UCOL_QUATERNARY: |
+ case UCOL_IDENTICAL: |
+ options = noStrength | (value << STRENGTH_SHIFT); |
+ break; |
+ case UCOL_DEFAULT: |
+ options = noStrength | (defaultOptions & STRENGTH_MASK); |
+ break; |
+ default: |
+ errorCode = U_ILLEGAL_ARGUMENT_ERROR; |
+ break; |
+ } |
+} |
+ |
+void |
+CollationSettings::setFlag(int32_t bit, UColAttributeValue value, |
+ int32_t defaultOptions, UErrorCode &errorCode) { |
+ if(U_FAILURE(errorCode)) { return; } |
+ switch(value) { |
+ case UCOL_ON: |
+ options |= bit; |
+ break; |
+ case UCOL_OFF: |
+ options &= ~bit; |
+ break; |
+ case UCOL_DEFAULT: |
+ options = (options & ~bit) | (defaultOptions & bit); |
+ break; |
+ default: |
+ errorCode = U_ILLEGAL_ARGUMENT_ERROR; |
+ break; |
+ } |
+} |
+ |
+void |
+CollationSettings::setCaseFirst(UColAttributeValue value, |
+ int32_t defaultOptions, UErrorCode &errorCode) { |
+ if(U_FAILURE(errorCode)) { return; } |
+ int32_t noCaseFirst = options & ~CASE_FIRST_AND_UPPER_MASK; |
+ switch(value) { |
+ case UCOL_OFF: |
+ options = noCaseFirst; |
+ break; |
+ case UCOL_LOWER_FIRST: |
+ options = noCaseFirst | CASE_FIRST; |
+ break; |
+ case UCOL_UPPER_FIRST: |
+ options = noCaseFirst | CASE_FIRST_AND_UPPER_MASK; |
+ break; |
+ case UCOL_DEFAULT: |
+ options = noCaseFirst | (defaultOptions & CASE_FIRST_AND_UPPER_MASK); |
+ break; |
+ default: |
+ errorCode = U_ILLEGAL_ARGUMENT_ERROR; |
+ break; |
+ } |
+} |
+ |
+void |
+CollationSettings::setAlternateHandling(UColAttributeValue value, |
+ int32_t defaultOptions, UErrorCode &errorCode) { |
+ if(U_FAILURE(errorCode)) { return; } |
+ int32_t noAlternate = options & ~ALTERNATE_MASK; |
+ switch(value) { |
+ case UCOL_NON_IGNORABLE: |
+ options = noAlternate; |
+ break; |
+ case UCOL_SHIFTED: |
+ options = noAlternate | SHIFTED; |
+ break; |
+ case UCOL_DEFAULT: |
+ options = noAlternate | (defaultOptions & ALTERNATE_MASK); |
+ break; |
+ default: |
+ errorCode = U_ILLEGAL_ARGUMENT_ERROR; |
+ break; |
+ } |
+} |
+ |
+void |
+CollationSettings::setMaxVariable(int32_t value, int32_t defaultOptions, UErrorCode &errorCode) { |
+ if(U_FAILURE(errorCode)) { return; } |
+ int32_t noMax = options & ~MAX_VARIABLE_MASK; |
+ switch(value) { |
+ case MAX_VAR_SPACE: |
+ case MAX_VAR_PUNCT: |
+ case MAX_VAR_SYMBOL: |
+ case MAX_VAR_CURRENCY: |
+ options = noMax | (value << MAX_VARIABLE_SHIFT); |
+ break; |
+ case UCOL_DEFAULT: |
+ options = noMax | (defaultOptions & MAX_VARIABLE_MASK); |
+ break; |
+ default: |
+ errorCode = U_ILLEGAL_ARGUMENT_ERROR; |
+ break; |
+ } |
+} |
+ |
+U_NAMESPACE_END |
+ |
+#endif // !UCONFIG_NO_COLLATION |