X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/51004dcb01e06fef634b61be77ed73dd61cb6db9..1a147d096ae81f4c8262f7bfc56bd19fc2dee932:/icuSources/common/ucnv_io.cpp diff --git a/icuSources/common/ucnv_io.cpp b/icuSources/common/ucnv_io.cpp index 12d2b63f..7a95a3f1 100644 --- a/icuSources/common/ucnv_io.cpp +++ b/icuSources/common/ucnv_io.cpp @@ -1,7 +1,9 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /* ****************************************************************************** * -* Copyright (C) 1999-2012, International Business Machines +* Copyright (C) 1999-2015, International Business Machines * Corporation and others. All Rights Reserved. * ****************************************************************************** @@ -36,6 +38,7 @@ #include "umutex.h" #include "uarrsort.h" +#include "uassert.h" #include "udataswp.h" #include "cstring.h" #include "cmemory.h" @@ -172,6 +175,7 @@ static const char DATA_NAME[] = "cnvalias"; static const char DATA_TYPE[] = "icu"; static UDataMemory *gAliasData=NULL; +static icu::UInitOnce gAliasDataInitOnce = U_INITONCE_INITIALIZER; enum { tocLengthIndex=0, @@ -218,113 +222,97 @@ static UBool U_CALLCONV ucnv_io_cleanup(void) udata_close(gAliasData); gAliasData = NULL; } + gAliasDataInitOnce.reset(); uprv_memset(&gMainTable, 0, sizeof(gMainTable)); return TRUE; /* Everything was cleaned up */ } -static UBool -haveAliasData(UErrorCode *pErrorCode) { - int needInit; - - if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { - return FALSE; - } - - UMTX_CHECK(NULL, (gAliasData==NULL), needInit); - - /* load converter alias data from file if necessary */ - if (needInit) { - UDataMemory *data; - const uint16_t *table; - const uint32_t *sectionSizes; - uint32_t tableStart; - uint32_t currOffset; - - data = udata_openChoice(NULL, DATA_TYPE, DATA_NAME, isAcceptable, NULL, pErrorCode); - if(U_FAILURE(*pErrorCode)) { - return FALSE; - } +static void U_CALLCONV initAliasData(UErrorCode &errCode) { + UDataMemory *data; + const uint16_t *table; + const uint32_t *sectionSizes; + uint32_t tableStart; + uint32_t currOffset; - sectionSizes = (const uint32_t *)udata_getMemory(data); - table = (const uint16_t *)sectionSizes; + ucln_common_registerCleanup(UCLN_COMMON_UCNV_IO, ucnv_io_cleanup); - tableStart = sectionSizes[0]; - if (tableStart < minTocLength) { - *pErrorCode = U_INVALID_FORMAT_ERROR; - udata_close(data); - return FALSE; - } - - umtx_lock(NULL); - if(gAliasData==NULL) { - gMainTable.converterListSize = sectionSizes[1]; - gMainTable.tagListSize = sectionSizes[2]; - gMainTable.aliasListSize = sectionSizes[3]; - gMainTable.untaggedConvArraySize = sectionSizes[4]; - gMainTable.taggedAliasArraySize = sectionSizes[5]; - gMainTable.taggedAliasListsSize = sectionSizes[6]; - gMainTable.optionTableSize = sectionSizes[7]; - gMainTable.stringTableSize = sectionSizes[8]; - - if (tableStart > 8) { - gMainTable.normalizedStringTableSize = sectionSizes[9]; - } + U_ASSERT(gAliasData == NULL); + data = udata_openChoice(NULL, DATA_TYPE, DATA_NAME, isAcceptable, NULL, &errCode); + if(U_FAILURE(errCode)) { + return; + } - currOffset = tableStart * (sizeof(uint32_t)/sizeof(uint16_t)) + (sizeof(uint32_t)/sizeof(uint16_t)); - gMainTable.converterList = table + currOffset; + sectionSizes = (const uint32_t *)udata_getMemory(data); + table = (const uint16_t *)sectionSizes; - currOffset += gMainTable.converterListSize; - gMainTable.tagList = table + currOffset; + tableStart = sectionSizes[0]; + if (tableStart < minTocLength) { + errCode = U_INVALID_FORMAT_ERROR; + udata_close(data); + return; + } + gAliasData = data; + + gMainTable.converterListSize = sectionSizes[1]; + gMainTable.tagListSize = sectionSizes[2]; + gMainTable.aliasListSize = sectionSizes[3]; + gMainTable.untaggedConvArraySize = sectionSizes[4]; + gMainTable.taggedAliasArraySize = sectionSizes[5]; + gMainTable.taggedAliasListsSize = sectionSizes[6]; + gMainTable.optionTableSize = sectionSizes[7]; + gMainTable.stringTableSize = sectionSizes[8]; + + if (tableStart > 8) { + gMainTable.normalizedStringTableSize = sectionSizes[9]; + } - currOffset += gMainTable.tagListSize; - gMainTable.aliasList = table + currOffset; + currOffset = tableStart * (sizeof(uint32_t)/sizeof(uint16_t)) + (sizeof(uint32_t)/sizeof(uint16_t)); + gMainTable.converterList = table + currOffset; - currOffset += gMainTable.aliasListSize; - gMainTable.untaggedConvArray = table + currOffset; + currOffset += gMainTable.converterListSize; + gMainTable.tagList = table + currOffset; - currOffset += gMainTable.untaggedConvArraySize; - gMainTable.taggedAliasArray = table + currOffset; + currOffset += gMainTable.tagListSize; + gMainTable.aliasList = table + currOffset; - /* aliasLists is a 1's based array, but it has a padding character */ - currOffset += gMainTable.taggedAliasArraySize; - gMainTable.taggedAliasLists = table + currOffset; + currOffset += gMainTable.aliasListSize; + gMainTable.untaggedConvArray = table + currOffset; - currOffset += gMainTable.taggedAliasListsSize; - if (gMainTable.optionTableSize > 0 - && ((const UConverterAliasOptions *)(table + currOffset))->stringNormalizationType < UCNV_IO_NORM_TYPE_COUNT) - { - /* Faster table */ - gMainTable.optionTable = (const UConverterAliasOptions *)(table + currOffset); - } - else { - /* Smaller table, or I can't handle this normalization mode! - Use the original slower table lookup. */ - gMainTable.optionTable = &defaultTableOptions; - } + currOffset += gMainTable.untaggedConvArraySize; + gMainTable.taggedAliasArray = table + currOffset; - currOffset += gMainTable.optionTableSize; - gMainTable.stringTable = table + currOffset; + /* aliasLists is a 1's based array, but it has a padding character */ + currOffset += gMainTable.taggedAliasArraySize; + gMainTable.taggedAliasLists = table + currOffset; - currOffset += gMainTable.stringTableSize; - gMainTable.normalizedStringTable = ((gMainTable.optionTable->stringNormalizationType == UCNV_IO_UNNORMALIZED) - ? gMainTable.stringTable : (table + currOffset)); + currOffset += gMainTable.taggedAliasListsSize; + if (gMainTable.optionTableSize > 0 + && ((const UConverterAliasOptions *)(table + currOffset))->stringNormalizationType < UCNV_IO_NORM_TYPE_COUNT) + { + /* Faster table */ + gMainTable.optionTable = (const UConverterAliasOptions *)(table + currOffset); + } + else { + /* Smaller table, or I can't handle this normalization mode! + Use the original slower table lookup. */ + gMainTable.optionTable = &defaultTableOptions; + } - ucln_common_registerCleanup(UCLN_COMMON_UCNV_IO, ucnv_io_cleanup); + currOffset += gMainTable.optionTableSize; + gMainTable.stringTable = table + currOffset; - gAliasData = data; - data=NULL; - } - umtx_unlock(NULL); + currOffset += gMainTable.stringTableSize; + gMainTable.normalizedStringTable = ((gMainTable.optionTable->stringNormalizationType == UCNV_IO_UNNORMALIZED) + ? gMainTable.stringTable : (table + currOffset)); +} - /* if a different thread set it first, then close the extra data */ - if(data!=NULL) { - udata_close(data); /* NULL if it was set correctly */ - } - } - return TRUE; +static UBool +haveAliasData(UErrorCode *pErrorCode) { + umtx_initOnce(gAliasDataInitOnce, &initAliasData, *pErrorCode); + return U_SUCCESS(*pErrorCode); } static inline UBool @@ -351,7 +339,7 @@ static uint32_t getTagNumber(const char *tagname) { /* character types relevant for ucnv_compareNames() */ enum { - IGNORE, + UIGNORE, ZERO, NONZERO, MINLETTER /* any values from here on are lowercase letter mappings */ @@ -369,7 +357,7 @@ static const uint8_t asciiTypes[128] = { 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0, 0, 0, 0, 0 }; -#define GET_ASCII_TYPE(c) ((int8_t)(c) >= 0 ? asciiTypes[(uint8_t)c] : (uint8_t)IGNORE) +#define GET_ASCII_TYPE(c) ((int8_t)(c) >= 0 ? asciiTypes[(uint8_t)c] : (uint8_t)UIGNORE) /* character types for EBCDIC 80..FF */ static const uint8_t ebcdicTypes[128] = { @@ -383,7 +371,7 @@ static const uint8_t ebcdicTypes[128] = { ZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, NONZERO, 0, 0, 0, 0, 0, 0 }; -#define GET_EBCDIC_TYPE(c) ((int8_t)(c) < 0 ? ebcdicTypes[(c)&0x7f] : (uint8_t)IGNORE) +#define GET_EBCDIC_TYPE(c) ((int8_t)(c) < 0 ? ebcdicTypes[(c)&0x7f] : (uint8_t)UIGNORE) #if U_CHARSET_FAMILY==U_ASCII_FAMILY # define GET_CHAR_TYPE(c) GET_ASCII_TYPE(c) @@ -393,8 +381,9 @@ static const uint8_t ebcdicTypes[128] = { # error U_CHARSET_FAMILY is not valid #endif + /* @see ucnv_compareNames */ -U_CFUNC char * U_EXPORT2 +U_CAPI char * U_CALLCONV ucnv_io_stripASCIIForCompare(char *dst, const char *name) { char *dstItr = dst; uint8_t type, nextType; @@ -404,7 +393,7 @@ ucnv_io_stripASCIIForCompare(char *dst, const char *name) { while ((c1 = *name++) != 0) { type = GET_ASCII_TYPE(c1); switch (type) { - case IGNORE: + case UIGNORE: afterDigit = FALSE; continue; /* ignore all but letters and digits */ case ZERO: @@ -429,7 +418,7 @@ ucnv_io_stripASCIIForCompare(char *dst, const char *name) { return dst; } -U_CFUNC char * U_EXPORT2 +U_CAPI char * U_CALLCONV ucnv_io_stripEBCDICForCompare(char *dst, const char *name) { char *dstItr = dst; uint8_t type, nextType; @@ -439,7 +428,7 @@ ucnv_io_stripEBCDICForCompare(char *dst, const char *name) { while ((c1 = *name++) != 0) { type = GET_EBCDIC_TYPE(c1); switch (type) { - case IGNORE: + case UIGNORE: afterDigit = FALSE; continue; /* ignore all but letters and digits */ case ZERO: @@ -496,7 +485,7 @@ ucnv_compareNames(const char *name1, const char *name2) { while ((c1 = *name1++) != 0) { type = GET_CHAR_TYPE(c1); switch (type) { - case IGNORE: + case UIGNORE: afterDigit1 = FALSE; continue; /* ignore all but letters and digits */ case ZERO: @@ -520,7 +509,7 @@ ucnv_compareNames(const char *name1, const char *name2) { while ((c2 = *name2++) != 0) { type = GET_CHAR_TYPE(c2); switch (type) { - case IGNORE: + case UIGNORE: afterDigit2 = FALSE; continue; /* ignore all but letters and digits */ case ZERO: @@ -745,9 +734,7 @@ findTaggedConverterNum(const char *alias, const char *standard, UErrorCode *pErr return UINT32_MAX; } - - -U_CFUNC const char * +U_CAPI const char * ucnv_io_getConverterName(const char *alias, UBool *containsOption, UErrorCode *pErrorCode) { const char *aliasTmp = alias; int32_t i = 0; @@ -758,7 +745,7 @@ ucnv_io_getConverterName(const char *alias, UBool *containsOption, UErrorCode *p * the name begins with 'x-'. If it does, strip it off and try * again. This behaviour is similar to how ICU4J does it. */ - if (aliasTmp[0] == 'x' || aliasTmp[1] == '-') { + if (aliasTmp[0] == 'x' && aliasTmp[1] == '-') { aliasTmp = aliasTmp+2; } else { break; @@ -778,6 +765,9 @@ ucnv_io_getConverterName(const char *alias, UBool *containsOption, UErrorCode *p return NULL; } +U_CDECL_BEGIN + + static int32_t U_CALLCONV ucnv_io_countStandardAliases(UEnumeration *enumerator, UErrorCode * /*pErrorCode*/) { int32_t value = 0; @@ -790,7 +780,7 @@ ucnv_io_countStandardAliases(UEnumeration *enumerator, UErrorCode * /*pErrorCode return value; } -static const char* U_CALLCONV +static const char * U_CALLCONV ucnv_io_nextStandardAliases(UEnumeration *enumerator, int32_t* resultLength, UErrorCode * /*pErrorCode*/) @@ -828,6 +818,8 @@ ucnv_io_closeUEnumeration(UEnumeration *enumerator) { uprv_free(enumerator); } +U_CDECL_END + /* Enumerate the aliases for the specified converter and standard tag */ static const UEnumeration gEnumAliases = { NULL, @@ -1024,12 +1016,15 @@ ucnv_getCanonicalName(const char *alias, const char *standard, UErrorCode *pErro return NULL; } +U_CDECL_BEGIN + + static int32_t U_CALLCONV ucnv_io_countAllConverters(UEnumeration * /*enumerator*/, UErrorCode * /*pErrorCode*/) { return gMainTable.converterListSize; } -static const char* U_CALLCONV +static const char * U_CALLCONV ucnv_io_nextAllConverters(UEnumeration *enumerator, int32_t* resultLength, UErrorCode * /*pErrorCode*/) @@ -1054,7 +1049,7 @@ static void U_CALLCONV ucnv_io_resetAllConverters(UEnumeration *enumerator, UErrorCode * /*pErrorCode*/) { *((uint16_t *)(enumerator->context)) = 0; } - +U_CDECL_END static const UEnumeration gEnumAllConverters = { NULL, NULL, @@ -1089,7 +1084,7 @@ ucnv_openAllNames(UErrorCode *pErrorCode) { return myEnum; } -U_CFUNC uint16_t +U_CAPI uint16_t ucnv_io_countKnownConverters(UErrorCode *pErrorCode) { if (haveAliasData(pErrorCode)) { return (uint16_t)gMainTable.converterListSize; @@ -1099,7 +1094,11 @@ ucnv_io_countKnownConverters(UErrorCode *pErrorCode) { /* alias table swapping ----------------------------------------------------- */ +U_CDECL_BEGIN + typedef char * U_CALLCONV StripForCompareFn(char *dst, const char *name); +U_CDECL_END + /* * row of a temporary array @@ -1123,7 +1122,7 @@ enum { STACK_ROW_CAPACITY=500 }; -static int32_t +static int32_t U_CALLCONV io_compareRows(const void *context, const void *left, const void *right) { char strippedLeft[UCNV_MAX_CONVERTER_NAME_LENGTH], strippedRight[UCNV_MAX_CONVERTER_NAME_LENGTH]; @@ -1311,13 +1310,13 @@ ucnv_swapAliases(const UDataSwapper *ds, oldIndex=tempTable.rows[i].sortIndex; ds->swapArray16(ds, p+oldIndex, 2, r+i, pErrorCode); } - uprv_memcpy(q, r, 2*count); + uprv_memcpy(q, r, 2*(size_t)count); for(i=0; iswapArray16(ds, p2+oldIndex, 2, r+i, pErrorCode); } - uprv_memcpy(q2, r, 2*count); + uprv_memcpy(q2, r, 2*(size_t)count); } } @@ -1350,6 +1349,7 @@ ucnv_swapAliases(const UDataSwapper *ds, #endif + /* * Hey, Emacs, please set the following: *