/*
*******************************************************************************
-* Copyright (C) 1996-2011, International Business Machines
+* Copyright (C) 1996-2012, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
* file name: ucol_res.cpp
pInfo->dataFormat[1]==UCA_DATA_FORMAT_1 &&
pInfo->dataFormat[2]==UCA_DATA_FORMAT_2 &&
pInfo->dataFormat[3]==UCA_DATA_FORMAT_3 &&
- pInfo->formatVersion[0]==UCA_FORMAT_VERSION_0 &&
- pInfo->formatVersion[1]>=UCA_FORMAT_VERSION_1// &&
+ pInfo->formatVersion[0]==UCA_FORMAT_VERSION_0
+#if UCA_FORMAT_VERSION_1!=0
+ && pInfo->formatVersion[1]>=UCA_FORMAT_VERSION_1
+#endif
//pInfo->formatVersion[1]==UCA_FORMAT_VERSION_1 &&
//pInfo->formatVersion[2]==UCA_FORMAT_VERSION_2 && // Too harsh
//pInfo->formatVersion[3]==UCA_FORMAT_VERSION_3 && // Too harsh
if (U_SUCCESS(intStatus)) {
int32_t reorderCodesLen = 0;
const int32_t* reorderCodes = ures_getIntVector(reorderRes, &reorderCodesLen, status);
- ucol_setReorderCodes(result, reorderCodes, reorderCodesLen, status);
+ if (reorderCodesLen > 0) {
+ ucol_setReorderCodes(result, reorderCodes, reorderCodesLen, status);
+ // copy the reorder codes into the default reorder codes
+ result->defaultReorderCodesLength = result->reorderCodesLength;
+ result->defaultReorderCodes = (int32_t*) uprv_malloc(result->defaultReorderCodesLength * sizeof(int32_t));
+ uprv_memcpy(result->defaultReorderCodes, result->reorderCodes, result->defaultReorderCodesLength * sizeof(int32_t));
+ result->freeDefaultReorderCodesOnClose = TRUE;
+ }
if (U_FAILURE(*status)) {
goto clean;
}
goto cleanup;
}
- if(src.resultLen > 0 || src.removeSet != NULL) { /* we have a set of rules, let's make something of it */
+ /* if we have a set of rules, let's make something of it */
+ if(src.resultLen > 0 || src.removeSet != NULL) {
/* also, if we wanted to remove some contractions, we should make a tailoring */
table = ucol_assembleTailoringTable(&src, status);
if(U_SUCCESS(*status)) {
}
result->hasRealData = TRUE;
result->freeImageOnClose = TRUE;
+ } else {
+ goto cleanup;
}
} else { /* no rules, but no error either */
// must be only options
}
uprv_memcpy(opts, src.opts, sizeof(UColOptionSet));
ucol_setOptionsFromHeader(result, opts, status);
- ucol_setReorderCodesFromParser(result, &src, status);
result->freeOptionsOnClose = TRUE;
result->hasRealData = FALSE;
result->freeImageOnClose = FALSE;
}
+ ucol_setReorderCodesFromParser(result, &src, status);
+
if(U_SUCCESS(*status)) {
UChar *newRules;
result->dataVersion[0] = UCOL_BUILDER_VERSION;
if (U_FAILURE(*status)) {
return NULL;
}
- StringEnumeration *s = Collator::getAvailableLocales();
+ StringEnumeration *s = icu::Collator::getAvailableLocales();
if (s == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
UTRACE_ENTRY(UTRACE_UCOL_GETLOCALE);
UTRACE_DATA1(UTRACE_INFO, "coll=%p", coll);
+ if(coll->delegate!=NULL) {
+ return ((const Collator*)coll->delegate)->getLocale(type, *status).getName();
+ }
switch(type) {
case ULOC_ACTUAL_LOCALE:
result = coll->actualLocale;
* Collation Reordering
*/
-static void ucol_setReorderCodesFromParser(UCollator *coll, UColTokenParser *parser, UErrorCode *status) {
+void ucol_setReorderCodesFromParser(UCollator *coll, UColTokenParser *parser, UErrorCode *status) {
if (U_FAILURE(*status)) {
return;
}
+ if (parser->reorderCodesLength == 0 || parser->reorderCodes == NULL) {
+ return;
+ }
+
coll->reorderCodesLength = 0;
- if (coll->reorderCodes != NULL) {
+ if (coll->reorderCodes != NULL && coll->freeReorderCodesOnClose == TRUE) {
uprv_free(coll->reorderCodes);
}
- if (parser->reorderCodesLength == 0 || parser->reorderCodes == NULL) {
+ if (coll->defaultReorderCodes != NULL && coll->freeDefaultReorderCodesOnClose == TRUE) {
+ uprv_free(coll->defaultReorderCodes);
+ }
+ coll->defaultReorderCodesLength = parser->reorderCodesLength;
+ coll->defaultReorderCodes = (int32_t*) uprv_malloc(coll->defaultReorderCodesLength * sizeof(int32_t));
+ if (coll->defaultReorderCodes == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
return;
}
+ uprv_memcpy(coll->defaultReorderCodes, parser->reorderCodes, coll->defaultReorderCodesLength * sizeof(int32_t));
+ coll->freeDefaultReorderCodesOnClose = TRUE;
coll->reorderCodesLength = parser->reorderCodesLength;
coll->reorderCodes = (int32_t*) uprv_malloc(coll->reorderCodesLength * sizeof(int32_t));
+ if (coll->reorderCodes == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
uprv_memcpy(coll->reorderCodes, parser->reorderCodes, coll->reorderCodesLength * sizeof(int32_t));
+ coll->freeReorderCodesOnClose = TRUE;
}
-static int ucol_getLeadBytesForReorderCode(UCollator *coll, int reorderCode, uint16_t* returnLeadBytes, int returnCapacity) {
- uint16_t reorderCodeIndexLength = *((uint16_t*) ((uint8_t *)coll->UCA->image + coll->UCA->image->scriptToLeadByte));
- uint16_t* reorderCodeIndex = (uint16_t*) ((uint8_t *)coll->UCA->image + coll->UCA->image->scriptToLeadByte + 2 *sizeof(uint16_t));
+/*
+ * Data is stored in the reorder code to lead byte table as:
+ * index count - unsigned short (2 bytes) - number of index entries
+ * data size - unsigned short (2 bytes) - number of unsigned short data elements
+ * index[index count] - array of 2 unsigned shorts (4 bytes each entry)
+ * - reorder code, offset
+ * - index is sorted by reorder code
+ * - if an offset has the high bit set then it is not an offset but a single data entry
+ * once the high bit is stripped off
+ * data[data size] - array of unsigned short (2 bytes each entry)
+ * - the data is an usigned short count followed by count number
+ * of lead bytes stored in an unsigned short
+ */
+U_CFUNC int U_EXPORT2
+ucol_getLeadBytesForReorderCode(const UCollator *uca, int reorderCode, uint16_t* returnLeadBytes, int returnCapacity) {
+ uint16_t reorderCodeIndexLength = *((uint16_t*) ((uint8_t *)uca->image + uca->image->scriptToLeadByte));
+ uint16_t* reorderCodeIndex = (uint16_t*) ((uint8_t *)uca->image + uca->image->scriptToLeadByte + 2 *sizeof(uint16_t));
- // TODO - replace with a binary search
// reorder code index is 2 uint16_t's - reorder code + offset
for (int i = 0; i < reorderCodeIndexLength; i++) {
if (reorderCode == reorderCodeIndex[i*2]) {
return 0;
}
-static int ucol_getReorderCodesForLeadByte(UCollator *coll, int leadByte, int16_t* returnReorderCodes, int returnCapacity) {
- int leadByteIndexLength = *((uint16_t*) ((uint8_t *)coll->UCA->image + coll->UCA->image->leadByteToScript));
- uint16_t* leadByteIndex = (uint16_t*) ((uint8_t *)coll->UCA->image + coll->UCA->image->leadByteToScript + 2 *sizeof(uint16_t));
+/*
+ * Data is stored in the lead byte to reorder code table as:
+ * index count - unsigned short (2 bytes) - number of index entries
+ * data size - unsigned short (2 bytes) - number of unsigned short data elements
+ * index[index count] - array of unsigned short (2 bytes each entry)
+ * - index is sorted by lead byte
+ * - if an index has the high bit set then it is not an index but a single data entry
+ * once the high bit is stripped off
+ * data[data size] - array of unsigned short (2 bytes each entry)
+ * - the data is an usigned short count followed by count number of reorder codes
+ */
+U_CFUNC int U_EXPORT2
+ucol_getReorderCodesForLeadByte(const UCollator *uca, int leadByte, int16_t* returnReorderCodes, int returnCapacity) {
+ uint16_t* leadByteTable = ((uint16_t*) ((uint8_t *)uca->image + uca->image->leadByteToScript));
+ uint16_t leadByteIndexLength = *leadByteTable;
if (leadByte >= leadByteIndexLength) {
return 0;
}
-
- if ((leadByteIndex[leadByte] & 0x8000) == 0x8000) {
+ uint16_t leadByteIndex = *(leadByteTable + (2 + leadByte));
+
+ if ((leadByteIndex & 0x8000) == 0x8000) {
// offset isn't offset but instead is a single data element
if (returnCapacity >= 1) {
- returnReorderCodes[0] = leadByteIndex[leadByte] & ~0x8000;
+ returnReorderCodes[0] = leadByteIndex & ~0x8000;
return 1;
}
return 0;
}
- uint16_t* dataOffsetBase = (uint16_t*) ((uint8_t *)leadByteIndex + leadByteIndexLength * (2 * sizeof(uint16_t)));
- uint16_t reorderCodeCount = *(dataOffsetBase + leadByteIndex[leadByte]);
- reorderCodeCount = reorderCodeCount > returnCapacity ? returnCapacity : reorderCodeCount;
- uprv_memcpy(returnReorderCodes, dataOffsetBase + leadByteIndex[leadByte] + 1, reorderCodeCount * sizeof(uint16_t));
+ //uint16_t* dataOffsetBase = leadByteTable + (2 + leadByteIndexLength);
+ uint16_t* reorderCodeData = leadByteTable + (2 + leadByteIndexLength) + leadByteIndex;
+ uint16_t reorderCodeCount = *reorderCodeData > returnCapacity ? returnCapacity : *reorderCodeData;
+ uprv_memcpy(returnReorderCodes, reorderCodeData + 1, reorderCodeCount * sizeof(uint16_t));
return reorderCodeCount;
}
// used to mark ignorable reorder code slots
static const int32_t UCOL_REORDER_CODE_IGNORE = UCOL_REORDER_CODE_LIMIT + 1;
-void ucol_buildPermutationTable(UCollator *coll, UErrorCode *status) {
+U_CFUNC void U_EXPORT2
+ucol_buildPermutationTable(UCollator *coll, UErrorCode *status) {
uint16_t leadBytesSize = 256;
uint16_t leadBytes[256];
int32_t internalReorderCodesLength = coll->reorderCodesLength + (UCOL_REORDER_CODE_LIMIT - UCOL_REORDER_CODE_FIRST);
bool permutationSlotFilled[256];
// nothing to do
- if(U_FAILURE(*status) || coll == NULL || coll->reorderCodesLength == 0) {
- if (coll != NULL) {
- if (coll->leadBytePermutationTable != NULL) {
+ if(U_FAILURE(*status) || coll == NULL) {
+ return;
+ }
+
+ // clear the reordering
+ if (coll->reorderCodes == NULL || coll->reorderCodesLength == 0
+ || (coll->reorderCodesLength == 1 && coll->reorderCodes[0] == UCOL_REORDER_CODE_NONE)) {
+ if (coll->leadBytePermutationTable != NULL) {
+ if (coll->freeLeadBytePermutationTableOnClose) {
uprv_free(coll->leadBytePermutationTable);
- coll->leadBytePermutationTable = NULL;
}
+ coll->leadBytePermutationTable = NULL;
coll->reorderCodesLength = 0;
}
return;
}
+ // set reordering to the default reordering
+ if (coll->reorderCodes[0] == UCOL_REORDER_CODE_DEFAULT) {
+ if (coll->reorderCodesLength != 1) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ if (coll->freeReorderCodesOnClose == TRUE) {
+ uprv_free(coll->reorderCodes);
+ }
+ coll->reorderCodes = NULL;
+
+ if (coll->leadBytePermutationTable != NULL && coll->freeLeadBytePermutationTableOnClose == TRUE) {
+ uprv_free(coll->leadBytePermutationTable);
+ }
+ coll->leadBytePermutationTable = NULL;
+
+ if (coll->defaultReorderCodesLength == 0) {
+ return;
+ }
+
+ coll->reorderCodes = (int32_t*)uprv_malloc(coll->defaultReorderCodesLength * sizeof(int32_t));
+ coll->freeReorderCodesOnClose = TRUE;
+ if (coll->reorderCodes == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ coll->reorderCodesLength = coll->defaultReorderCodesLength;
+ uprv_memcpy(coll->defaultReorderCodes, coll->reorderCodes, coll->reorderCodesLength * sizeof(int32_t));
+ }
+
if (coll->leadBytePermutationTable == NULL) {
coll->leadBytePermutationTable = (uint8_t*)uprv_malloc(256*sizeof(uint8_t));
+ coll->freeLeadBytePermutationTableOnClose = TRUE;
if (coll->leadBytePermutationTable == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
return;
internalReorderCodes = (int32_t*)uprv_malloc(internalReorderCodesLength * sizeof(int32_t));
if (internalReorderCodes == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
- if (coll->leadBytePermutationTable != NULL) {
+ if (coll->leadBytePermutationTable != NULL && coll->freeLeadBytePermutationTableOnClose == TRUE) {
uprv_free(coll->leadBytePermutationTable);
- coll->leadBytePermutationTable = NULL;
}
+ coll->leadBytePermutationTable = NULL;
return;
}
if (fromTheBottom == false) {
// double turnaround
*status = U_ILLEGAL_ARGUMENT_ERROR;
- if (coll->leadBytePermutationTable != NULL) {
+ if (coll->leadBytePermutationTable != NULL && coll->freeLeadBytePermutationTableOnClose == TRUE) {
uprv_free(coll->leadBytePermutationTable);
- coll->leadBytePermutationTable = NULL;
}
+ coll->leadBytePermutationTable = NULL;
coll->reorderCodesLength = 0;
if (internalReorderCodes != NULL) {
uprv_free(internalReorderCodes);
continue;
}
- uint16_t leadByteCount = ucol_getLeadBytesForReorderCode(coll, next, leadBytes, leadBytesSize);
+ uint16_t leadByteCount = ucol_getLeadBytesForReorderCode(coll->UCA, next, leadBytes, leadBytesSize);
if (fromTheBottom) {
for (int leadByteIndex = 0; leadByteIndex < leadByteCount; leadByteIndex++) {
// don't place a lead byte twice in the permutation table
if (permutationSlotFilled[leadBytes[leadByteIndex]]) {
// lead byte already used
*status = U_ILLEGAL_ARGUMENT_ERROR;
- if (coll->leadBytePermutationTable != NULL) {
+ if (coll->leadBytePermutationTable != NULL && coll->freeLeadBytePermutationTableOnClose == TRUE) {
uprv_free(coll->leadBytePermutationTable);
- coll->leadBytePermutationTable = NULL;
}
+ coll->leadBytePermutationTable = NULL;
coll->reorderCodesLength = 0;
if (internalReorderCodes != NULL) {
uprv_free(internalReorderCodes);
if (permutationSlotFilled[leadBytes[leadByteIndex]]) {
// lead byte already used
*status = U_ILLEGAL_ARGUMENT_ERROR;
- if (coll->leadBytePermutationTable != NULL) {
+ if (coll->leadBytePermutationTable != NULL && coll->freeLeadBytePermutationTableOnClose == TRUE) {
uprv_free(coll->leadBytePermutationTable);
- coll->leadBytePermutationTable = NULL;
}
+ coll->leadBytePermutationTable = NULL;
coll->reorderCodesLength = 0;
if (internalReorderCodes != NULL) {
uprv_free(internalReorderCodes);