U_CDECL_END /** * Load the property names data. Caller should check that data is * not loaded BEFORE calling this function. Returns TRUE if the load * succeeds. */ static UBool _load() { UErrorCode ec = U_ZERO_ERROR; UDataMemory* data = udata_openChoice(0, PNAME_DATA_TYPE, PNAME_DATA_NAME, isPNameAcceptable, 0, &ec); if (U_SUCCESS(ec)) { umtx_lock(NULL); if (UDATA == NULL) { UDATA = data; PNAME = (const PropertyAliases*) udata_getMemory(UDATA); ucln_common_registerCleanup(UCLN_COMMON_PNAME, pname_cleanup); data = NULL; } umtx_unlock(NULL); } if (data) { udata_close(data); } return PNAME!=NULL; }
U_CDECL_END /** Initializes the cache for resources */ static void initCache(UErrorCode * status) { UBool makeCache; UMTX_CHECK(&usprepMutex, (SHARED_DATA_HASHTABLE == NULL), makeCache); if (makeCache) { UHashtable * newCache = uhash_open(hashEntry, compareEntries, NULL, status); if (U_SUCCESS(*status)) { umtx_lock(&usprepMutex); if (SHARED_DATA_HASHTABLE == NULL) { SHARED_DATA_HASHTABLE = newCache; ucln_common_registerCleanup(UCLN_COMMON_USPREP, usprep_cleanup); newCache = NULL; } umtx_unlock(&usprepMutex); } if (newCache != NULL) { uhash_close(newCache); } } }
static void U_CALLCONV locale_init(UErrorCode &status) { U_NAMESPACE_USE U_ASSERT(gLocaleCache == NULL); gLocaleCache = new Locale[(int)eMAX_LOCALES]; if (gLocaleCache == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return; } ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup); gLocaleCache[eROOT] = Locale(""); gLocaleCache[eENGLISH] = Locale("en"); gLocaleCache[eFRENCH] = Locale("fr"); gLocaleCache[eGERMAN] = Locale("de"); gLocaleCache[eITALIAN] = Locale("it"); gLocaleCache[eJAPANESE] = Locale("ja"); gLocaleCache[eKOREAN] = Locale("ko"); gLocaleCache[eCHINESE] = Locale("zh"); gLocaleCache[eFRANCE] = Locale("fr", "FR"); gLocaleCache[eGERMANY] = Locale("de", "DE"); gLocaleCache[eITALY] = Locale("it", "IT"); gLocaleCache[eJAPAN] = Locale("ja", "JP"); gLocaleCache[eKOREA] = Locale("ko", "KR"); gLocaleCache[eCHINA] = Locale("zh", "CN"); gLocaleCache[eTAIWAN] = Locale("zh", "TW"); gLocaleCache[eUK] = Locale("en", "GB"); gLocaleCache[eUS] = Locale("en", "US"); gLocaleCache[eCANADA] = Locale("en", "CA"); gLocaleCache[eCANADA_FRENCH] = Locale("fr", "CA"); }
static void setCommonICUData(UDataMemory *pData, /* The new common data. Belongs to caller, we copy it. */ UDataMemory *oldData, /* Old ICUData ptr. Overwrite of this value is ok, */ /* of any others is not. */ UBool warn, /* If true, set USING_DEFAULT warning if ICUData was */ /* changed by another thread before we got to it. */ UErrorCode *pErr) { UDataMemory *newCommonData = UDataMemory_createNewInstance(pErr); if (U_FAILURE(*pErr)) { return; } /* For the assignment, other threads must cleanly see either the old */ /* or the new, not some partially initialized new. The old can not be */ /* deleted - someone may still have a pointer to it lying around in */ /* their locals. */ UDatamemory_assign(newCommonData, pData); umtx_lock(NULL); if (gCommonICUData==oldData) { gStubICUData = gCommonICUData; /* remember the old Common Data, so it can be cleaned up. */ gCommonICUData = newCommonData; ucln_common_registerCleanup(UCLN_COMMON_UDATA, udata_cleanup); } else { if (warn==TRUE) { *pErr = U_USING_DEFAULT_WARNING; } uprv_free(newCommonData); } umtx_unlock(NULL); }
static void U_CALLCONV initData(UErrorCode &status) { #if UCONFIG_ENABLE_PLUGINS /* initialize plugins */ uplug_init(&status); #endif #if !UCONFIG_NO_CONVERSION /* * 2005-may-02 * * ICU4C 3.4 (jitterbug 4497) hardcodes the data for Unicode character * properties for APIs that want to be fast. * Therefore, we need not load them here nor check for errors. * Instead, we load the converter alias table to see if any ICU data * is available. * Users should really open the service objects they need and check * for errors there, to make sure that the actual items they need are * available. */ ucnv_io_countKnownConverters(&status); #endif ucln_common_registerCleanup(UCLN_COMMON_UINIT, uinit_cleanup); }
/* udata_getCacheHashTable() * Get the hash table used to store the data cache entries. * Lazy create it if it doesn't yet exist. */ static UHashtable *udata_getHashTable() { UErrorCode err = U_ZERO_ERROR; UBool cacheIsInitialized; UHashtable *tHT = NULL; UMTX_CHECK(NULL, (gCommonDataCache != NULL), cacheIsInitialized); if (cacheIsInitialized) { return gCommonDataCache; } tHT = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &err); /* Check for null pointer. */ if (tHT == NULL) { return NULL; /* TODO: Handle this error better. */ } uhash_setValueDeleter(tHT, DataCacheElement_deleter); umtx_lock(NULL); if (gCommonDataCache == NULL) { gCommonDataCache = tHT; tHT = NULL; ucln_common_registerCleanup(UCLN_COMMON_UDATA, udata_cleanup); } umtx_unlock(NULL); if (tHT != NULL) { uhash_close(tHT); } if (U_FAILURE(err)) { return NULL; /* TODO: handle this error better. */ } return gCommonDataCache; }
/* * Set the data directory. * Make a copy of the passed string, and set the global data dir to point to it. * TODO: see bug #2849, regarding thread safety. */ U_CAPI void U_EXPORT2 u_setDataDirectory(const char *directory) { char *newDataDir; int32_t length; if(directory==NULL || *directory==0) { /* A small optimization to prevent the malloc and copy when the shared library is used, and this is a way to make sure that NULL is never returned. */ newDataDir = (char *)""; } else { length=(int32_t)uprv_strlen(directory); newDataDir = (char *)uprv_malloc(length + 2); uprv_strcpy(newDataDir, directory); #if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR) { char *p; while(p = uprv_strchr(newDataDir, U_FILE_ALT_SEP_CHAR)) { *p = U_FILE_SEP_CHAR; } } #endif } umtx_lock(NULL); if (gDataDirectory && *gDataDirectory) { uprv_free(gDataDirectory); } gDataDirectory = newDataDir; ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup); umtx_unlock(NULL); }
/* get the UBiDiProps singleton, or else its dummy, once and for all */ static const UBiDiProps * getBiDiProps() { /* * This lazy intialization with double-checked locking (without mutex protection for * the initial check) is transiently unsafe under certain circumstances. * Check the readme and use u_init() if necessary. */ /* the initial check is performed by the GET_BIDI_PROPS() macro */ const UBiDiProps *bdp; UErrorCode errorCode=U_ZERO_ERROR; bdp=ubidi_getSingleton(&errorCode); #if !UBIDI_HARDCODE_DATA if(U_FAILURE(errorCode)) { errorCode=U_ZERO_ERROR; bdp=ubidi_getDummy(&errorCode); if(U_FAILURE(errorCode)) { return NULL; } } #endif umtx_lock(NULL); if(gBdp==NULL) { gBdp=bdp; ucln_common_registerCleanup(UCLN_COMMON_UPROPS, uprops_cleanup); } umtx_unlock(NULL); return gBdp; }
U_CDECL_END U_NAMESPACE_BEGIN Locale *locale_set_default_internal(const char *id, UErrorCode& status) { // Synchronize this entire function. Mutex lock(&gDefaultLocaleMutex); UBool canonicalize = FALSE; // If given a NULL string for the locale id, grab the default // name from the system. // (Different from most other locale APIs, where a null name means use // the current ICU default locale.) if (id == NULL) { id = uprv_getDefaultLocaleID(); // This function not thread safe? TODO: verify. canonicalize = TRUE; // always canonicalize host ID } char localeNameBuf[512]; if (canonicalize) { uloc_canonicalize(id, localeNameBuf, sizeof(localeNameBuf)-1, &status); } else { uloc_getName(id, localeNameBuf, sizeof(localeNameBuf)-1, &status); } localeNameBuf[sizeof(localeNameBuf)-1] = 0; // Force null termination in event of // a long name filling the buffer. // (long names are truncated.) // if (U_FAILURE(status)) { return gDefaultLocale; } if (gDefaultLocalesHashT == NULL) { gDefaultLocalesHashT = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status); if (U_FAILURE(status)) { return gDefaultLocale; } uhash_setValueDeleter(gDefaultLocalesHashT, deleteLocale); ucln_common_registerCleanup(UCLN_COMMON_LOCALE, locale_cleanup); } Locale *newDefault = (Locale *)uhash_get(gDefaultLocalesHashT, localeNameBuf); if (newDefault == NULL) { newDefault = new Locale(Locale::eBOGUS); if (newDefault == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return gDefaultLocale; } newDefault->init(localeNameBuf, FALSE); uhash_put(gDefaultLocalesHashT, (char*) newDefault->getName(), newDefault, &status); if (U_FAILURE(status)) { return gDefaultLocale; } } gDefaultLocale = newDefault; return gDefaultLocale; }
U_CDECL_END U_NAMESPACE_BEGIN static void U_CALLCONV initService(void) { gService = new ICUBreakIteratorService(); ucln_common_registerCleanup(UCLN_COMMON_BREAKITERATOR, breakiterator_cleanup); }
// Cache some sets for other services -------------------------------------- *** void U_CALLCONV createUni32Set(UErrorCode &errorCode) { U_ASSERT(uni32Singleton == NULL); uni32Singleton = new UnicodeSet(UNICODE_STRING_SIMPLE("[:age=3.2:]"), errorCode); if(uni32Singleton==NULL) { errorCode=U_MEMORY_ALLOCATION_ERROR; } else { uni32Singleton->freeze(); } ucln_common_registerCleanup(UCLN_COMMON_USET, uset_cleanup); }
// UInitOnce singleton initialization function static void U_CALLCONV initSingletons(const char *what, UErrorCode &errorCode) { if (uprv_strcmp(what, "nfkc") == 0) { nfkcSingleton = Norm2AllModes::createInstance(NULL, "nfkc", errorCode); } else if (uprv_strcmp(what, "nfkc_cf") == 0) { nfkc_cfSingleton = Norm2AllModes::createInstance(NULL, "nfkc_cf", errorCode); } else { U_ASSERT(FALSE); // Unknown singleton } ucln_common_registerCleanup(UCLN_COMMON_LOADED_NORMALIZER2, uprv_loaded_normalizer2_cleanup); }
static void *createInstance(const void *context, UErrorCode &errorCode) { UnicodeString pattern((const char *)context, -1, US_INV); UnicodeSet *set=new UnicodeSet(pattern, errorCode); if(set==NULL) { errorCode=U_MEMORY_ALLOCATION_ERROR; } set->freeze(); ucln_common_registerCleanup(UCLN_COMMON_USET, uset_cleanup); return set; }
static int8_t uprv_loadPropsData(UErrorCode *pErrorCode) { /* load Unicode character properties data from file if necessary */ /* * This lazy intialization with double-checked locking (without mutex protection for * haveNormData==0) is transiently unsafe under certain circumstances. * Check the readme and use u_init() if necessary. */ if(havePropsData==0) { UCharProps ucp={ NULL }; if(U_FAILURE(*pErrorCode)) { return havePropsData; } /* open the data outside the mutex block */ _openProps(&ucp, pErrorCode); if(U_SUCCESS(*pErrorCode)) { /* in the mutex block, set the data for this process */ umtx_lock(NULL); if(propsData==NULL) { propsData=ucp.propsData; ucp.propsData=NULL; pData32=ucp.pData32; ucp.pData32=NULL; uprv_memcpy(&propsTrie, &ucp.propsTrie, sizeof(propsTrie)); uprv_memcpy(&propsVectorsTrie, &ucp.propsVectorsTrie, sizeof(propsVectorsTrie)); } /* initialize some variables */ uprv_memcpy(indexes, pData32, sizeof(indexes)); /* additional properties */ if(indexes[UPROPS_ADDITIONAL_VECTORS_INDEX]!=0) { propsVectors=pData32+indexes[UPROPS_ADDITIONAL_VECTORS_INDEX]; countPropsVectors=indexes[UPROPS_RESERVED_INDEX]-indexes[UPROPS_ADDITIONAL_VECTORS_INDEX]; propsVectorsColumns=indexes[UPROPS_ADDITIONAL_VECTORS_COLUMNS_INDEX]; } havePropsData=1; umtx_unlock(NULL); } else { dataErrorCode=*pErrorCode; havePropsData=-1; } ucln_common_registerCleanup(UCLN_COMMON_UCHAR, uchar_cleanup); /* if a different thread set it first, then close the extra data */ udata_close(ucp.propsData); /* NULL if it was set correctly */ } return havePropsData; }
U_CDECL_END /** Initializes the cache for resources */ static void U_CALLCONV createCache(UErrorCode &status) { SHARED_DATA_HASHTABLE = uhash_open(hashEntry, compareEntries, NULL, &status); if (U_FAILURE(status)) { SHARED_DATA_HASHTABLE = NULL; } ucln_common_registerCleanup(UCLN_COMMON_USPREP, usprep_cleanup); }
U_CAPI const UBiDiProps * U_EXPORT2 ubidi_getDummy(UErrorCode *pErrorCode) { UBiDiProps *bdp; if(U_FAILURE(*pErrorCode)) { return NULL; } UMTX_CHECK(NULL, gBdpDummy, bdp); if(bdp!=NULL) { /* the dummy object was already created */ return bdp; } else /* bdp==NULL */ { /* create the dummy object */ int32_t *indexes; bdp=(UBiDiProps *)uprv_malloc(sizeof(UBiDiProps)+UBIDI_IX_TOP*4+UTRIE_DUMMY_SIZE); if(bdp==NULL) { *pErrorCode=U_MEMORY_ALLOCATION_ERROR; return NULL; } uprv_memset(bdp, 0, sizeof(UBiDiProps)+UBIDI_IX_TOP*4); bdp->indexes=indexes=(int32_t *)(bdp+1); indexes[UBIDI_IX_INDEX_TOP]=UBIDI_IX_TOP; indexes[UBIDI_IX_TRIE_SIZE]= utrie_unserializeDummy(&bdp->trie, indexes+UBIDI_IX_TOP, UTRIE_DUMMY_SIZE, 0, 0, TRUE, pErrorCode); if(U_FAILURE(*pErrorCode)) { uprv_free(bdp); return NULL; } bdp->formatVersion[0]=1; bdp->formatVersion[2]=UTRIE_SHIFT; bdp->formatVersion[3]=UTRIE_INDEX_SHIFT; /* set the static variables */ umtx_lock(NULL); if(gBdpDummy==NULL) { gBdpDummy=bdp; bdp=NULL; ucln_common_registerCleanup(UCLN_COMMON_UBIDI, ubidi_cleanup); } umtx_unlock(NULL); uprv_free(bdp); return gBdpDummy; } }
U_CAPI const UCaseProps * U_EXPORT2 ucase_getDummy(UErrorCode *pErrorCode) { UCaseProps *csp; if(U_FAILURE(*pErrorCode)) { return NULL; } UMTX_CHECK(NULL, gCspDummy, csp); if(csp!=NULL) { /* the dummy object was already created */ return csp; } else /* csp==NULL */ { /* create the dummy object */ int32_t *indexes; csp=(UCaseProps *)uprv_malloc(sizeof(UCaseProps)+UCASE_IX_TOP*4+UTRIE_DUMMY_SIZE); if(csp==NULL) { *pErrorCode=U_MEMORY_ALLOCATION_ERROR; return NULL; } uprv_memset(csp, 0, sizeof(UCaseProps)+UCASE_IX_TOP*4); csp->indexes=indexes=(int32_t *)(csp+1); indexes[UCASE_IX_INDEX_TOP]=UCASE_IX_TOP; indexes[UCASE_IX_TRIE_SIZE]= utrie_unserializeDummy(&csp->trie, indexes+UCASE_IX_TOP, UTRIE_DUMMY_SIZE, 0, 0, TRUE, pErrorCode); if(U_FAILURE(*pErrorCode)) { uprv_free(csp); return NULL; } csp->formatVersion[0]=1; csp->formatVersion[2]=UTRIE_SHIFT; csp->formatVersion[3]=UTRIE_INDEX_SHIFT; /* set the static variables */ umtx_lock(NULL); if(gCspDummy==NULL) { gCspDummy=csp; csp=NULL; ucln_common_registerCleanup(UCLN_COMMON_UCASE, ucase_cleanup); } umtx_unlock(NULL); uprv_free(csp); return gCspDummy; } }
static void U_CALLCONV cacheInit(UErrorCode &status) { U_ASSERT(gCache == NULL); ucln_common_registerCleanup( UCLN_COMMON_UNIFIED_CACHE, unifiedcache_cleanup); gCache = new UnifiedCache(status); if (gCache == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } if (U_FAILURE(status)) { delete gCache; gCache = NULL; return; } }
void ListFormatter::initializeHash(UErrorCode& errorCode) { if (U_FAILURE(errorCode)) { return; } listPatternHash = new Hashtable(); if (listPatternHash == NULL) { errorCode = U_MEMORY_ALLOCATION_ERROR; return; } listPatternHash->setValueDeleter(uprv_deleteListFormatInternal); ucln_common_registerCleanup(UCLN_COMMON_LIST_FORMATTER, uprv_listformatter_cleanup); }
U_CAPI const UCaseProps * U_EXPORT2 ucase_getSingleton(UErrorCode *pErrorCode) { #if UCASE_HARDCODE_DATA if(U_FAILURE(*pErrorCode)) { return NULL; } return &ucase_props_singleton; #else int8_t haveData; if(U_FAILURE(*pErrorCode)) { return NULL; } UMTX_CHECK(NULL, gHaveData, haveData); if(haveData>0) { /* data was loaded */ return gCsp; } else if(haveData<0) { /* data loading failed */ *pErrorCode=gErrorCode; return NULL; } else /* haveData==0 */ { /* load the data */ UCaseProps *csp=ucase_open(pErrorCode); if(U_FAILURE(*pErrorCode)) { gHaveData=-1; gErrorCode=*pErrorCode; return NULL; } /* set the static variables */ umtx_lock(NULL); if(gCsp==NULL) { gCsp=csp; csp=NULL; gHaveData=1; ucln_common_registerCleanup(UCLN_COMMON_UCASE, ucase_cleanup); } umtx_unlock(NULL); ucase_close(csp); return gCsp; } #endif }
U_CAPI const UBiDiProps * U_EXPORT2 ubidi_getSingleton(UErrorCode *pErrorCode) { #if UBIDI_HARDCODE_DATA if(U_FAILURE(*pErrorCode)) { return NULL; } return &ubidi_props_singleton; #else int8_t haveData; if(U_FAILURE(*pErrorCode)) { return NULL; } UMTX_CHECK(NULL, gHaveData, haveData); if(haveData>0) { /* data was loaded */ return gBdp; } else if(haveData<0) { /* data loading failed */ *pErrorCode=gErrorCode; return NULL; } else /* haveData==0 */ { /* load the data */ UBiDiProps *bdp=ubidi_openProps(pErrorCode); if(U_FAILURE(*pErrorCode)) { gHaveData=-1; gErrorCode=*pErrorCode; return NULL; } /* set the static variables */ umtx_lock(NULL); if(gBdp==NULL) { gBdp=bdp; bdp=NULL; gHaveData=1; ucln_common_registerCleanup(UCLN_COMMON_UBIDI, ubidi_cleanup); } umtx_unlock(NULL); ubidi_closeProps(bdp); return gBdp; } #endif }
U_CDECL_END U_NAMESPACE_BEGIN static ICULocaleService* getService(void) { UBool needsInit; UMTX_CHECK(NULL, (UBool)(gService == NULL), needsInit); if (needsInit) { ICULocaleService *tService = new ICUBreakIteratorService(); umtx_lock(NULL); if (gService == NULL) { gService = tService; tService = NULL; ucln_common_registerCleanup(UCLN_COMMON_BREAKITERATOR, breakiterator_cleanup); } umtx_unlock(NULL); delete tService; } return gService; }
static void U_CALLCONV cacheInit(UErrorCode &status) { U_ASSERT(gCache == NULL); ucln_common_registerCleanup( UCLN_COMMON_UNIFIED_CACHE, unifiedcache_cleanup); // gNoValue must be created first to avoid assertion error in // cache constructor. gNoValue = new SharedObject(); gCache = new UnifiedCache(status); if (gCache == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } if (U_FAILURE(status)) { delete gCache; delete gNoValue; gCache = NULL; gNoValue = NULL; return; } // We add a softref because we want hash elements with gNoValue to be // elligible for purging but we don't ever want gNoValue to be deleted. gNoValue->addSoftRef(); }
/** Initializes the cache for resources */ static void initCache(UErrorCode *status) { UBool makeCache = FALSE; umtx_lock(&usprepMutex); makeCache = (SHARED_DATA_HASHTABLE == NULL); umtx_unlock(&usprepMutex); if(makeCache) { UHashtable *newCache = uhash_open(hashEntry, compareEntries, status); if (U_FAILURE(*status)) { return; } umtx_lock(&usprepMutex); if(SHARED_DATA_HASHTABLE == NULL) { SHARED_DATA_HASHTABLE = newCache; ucln_common_registerCleanup(UCLN_COMMON_USPREP, usprep_cleanup); newCache = NULL; } umtx_unlock(&usprepMutex); if(newCache != NULL) { uhash_close(newCache); } } }
static void U_CALLCONV initAliasData(UErrorCode &errCode) { UDataMemory *data; const uint16_t *table; const uint32_t *sectionSizes; uint32_t tableStart; uint32_t currOffset; ucln_common_registerCleanup(UCLN_COMMON_UCNV_IO, ucnv_io_cleanup); U_ASSERT(gAliasData == NULL); data = udata_openChoice(NULL, DATA_TYPE, DATA_NAME, isAcceptable, NULL, &errCode); if(U_FAILURE(errCode)) { return; } sectionSizes = (const uint32_t *)udata_getMemory(data); table = (const uint16_t *)sectionSizes; 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 = tableStart * (sizeof(uint32_t)/sizeof(uint16_t)) + (sizeof(uint32_t)/sizeof(uint16_t)); gMainTable.converterList = table + currOffset; currOffset += gMainTable.converterListSize; gMainTable.tagList = table + currOffset; currOffset += gMainTable.tagListSize; gMainTable.aliasList = table + currOffset; currOffset += gMainTable.aliasListSize; gMainTable.untaggedConvArray = table + currOffset; currOffset += gMainTable.untaggedConvArraySize; gMainTable.taggedAliasArray = table + currOffset; /* aliasLists is a 1's based array, but it has a padding character */ currOffset += gMainTable.taggedAliasArraySize; gMainTable.taggedAliasLists = 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.optionTableSize; gMainTable.stringTable = table + currOffset; currOffset += gMainTable.stringTableSize; gMainTable.normalizedStringTable = ((gMainTable.optionTable->stringNormalizationType == UCNV_IO_UNNORMALIZED) ? gMainTable.stringTable : (table + currOffset)); }
U_CDECL_END U_NAMESPACE_BEGIN /* Reduce excessive reallocation, and make it easier to detect initialization problems. Usually you don't see smaller sets than this for Unicode 5.0. */ #define DEFAULT_INCLUSION_CAPACITY 3072 const UnicodeSet* UnicodeSet::getInclusions(int32_t src, UErrorCode &status) { UBool needInit; UMTX_CHECK(NULL, (INCLUSIONS[src] == NULL), needInit); if (needInit) { UnicodeSet* incl = new UnicodeSet(); USetAdder sa = { (USet *)incl, _set_add, _set_addRange, _set_addString, NULL, // don't need remove() NULL // don't need removeRange() }; incl->ensureCapacity(DEFAULT_INCLUSION_CAPACITY, status); if (incl != NULL) { switch(src) { case UPROPS_SRC_CHAR: uchar_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_PROPSVEC: upropsvec_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_CHAR_AND_PROPSVEC: uchar_addPropertyStarts(&sa, &status); upropsvec_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_HST: uhst_addPropertyStarts(&sa, &status); break; #if !UCONFIG_NO_NORMALIZATION case UPROPS_SRC_NORM: unorm_addPropertyStarts(&sa, &status); break; #endif case UPROPS_SRC_CASE: ucase_addPropertyStarts(ucase_getSingleton(&status), &sa, &status); break; case UPROPS_SRC_BIDI: ubidi_addPropertyStarts(ubidi_getSingleton(&status), &sa, &status); break; default: status = U_INTERNAL_PROGRAM_ERROR; break; } if (U_SUCCESS(status)) { // Compact for caching incl->compact(); umtx_lock(NULL); if (INCLUSIONS[src] == NULL) { INCLUSIONS[src] = incl; incl = NULL; ucln_common_registerCleanup(UCLN_COMMON_USET, uset_cleanup); } umtx_unlock(NULL); } delete incl; } else { status = U_MEMORY_ALLOCATION_ERROR; } } return INCLUSIONS[src]; }
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; } sectionSizes = (const uint32_t *)udata_getMemory(data); table = (const uint16_t *)sectionSizes; 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]; } currOffset = tableStart * (sizeof(uint32_t)/sizeof(uint16_t)) + (sizeof(uint32_t)/sizeof(uint16_t)); gMainTable.converterList = table + currOffset; currOffset += gMainTable.converterListSize; gMainTable.tagList = table + currOffset; currOffset += gMainTable.tagListSize; gMainTable.aliasList = table + currOffset; currOffset += gMainTable.aliasListSize; gMainTable.untaggedConvArray = table + currOffset; currOffset += gMainTable.untaggedConvArraySize; gMainTable.taggedAliasArray = table + currOffset; /* aliasLists is a 1's based array, but it has a padding character */ currOffset += gMainTable.taggedAliasArraySize; gMainTable.taggedAliasLists = 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.optionTableSize; gMainTable.stringTable = table + currOffset; currOffset += gMainTable.stringTableSize; gMainTable.normalizedStringTable = ((gMainTable.optionTable->stringNormalizationType == UCNV_IO_UNNORMALIZED) ? gMainTable.stringTable : (table + currOffset)); ucln_common_registerCleanup(UCLN_COMMON_UCNV_IO, ucnv_io_cleanup); gAliasData = data; data=NULL; } umtx_unlock(NULL); /* 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; }
const Normalizer2 * Normalizer2::getInstance(const char *packageName, const char *name, UNormalization2Mode mode, UErrorCode &errorCode) { if(U_FAILURE(errorCode)) { return NULL; } if(name==NULL || *name==0) { errorCode=U_ILLEGAL_ARGUMENT_ERROR; return NULL; } const Norm2AllModes *allModes=NULL; if(packageName==NULL) { if(0==uprv_strcmp(name, "nfc")) { allModes=Norm2AllModes::getNFCInstance(errorCode); } else if(0==uprv_strcmp(name, "nfkc")) { allModes=Norm2AllModes::getNFKCInstance(errorCode); } else if(0==uprv_strcmp(name, "nfkc_cf")) { allModes=Norm2AllModes::getNFKC_CFInstance(errorCode); } } if(allModes==NULL && U_SUCCESS(errorCode)) { { Mutex lock; if(cache!=NULL) { allModes=(Norm2AllModes *)uhash_get(cache, name); } } if(allModes==NULL) { ucln_common_registerCleanup(UCLN_COMMON_LOADED_NORMALIZER2, uprv_loaded_normalizer2_cleanup); LocalPointer<Norm2AllModes> localAllModes( Norm2AllModes::createInstance(packageName, name, errorCode)); if(U_SUCCESS(errorCode)) { Mutex lock; if(cache==NULL) { cache=uhash_open(uhash_hashChars, uhash_compareChars, NULL, &errorCode); if(U_FAILURE(errorCode)) { return NULL; } uhash_setKeyDeleter(cache, uprv_free); uhash_setValueDeleter(cache, deleteNorm2AllModes); } void *temp=uhash_get(cache, name); if(temp==NULL) { int32_t keyLength= static_cast<int32_t>(uprv_strlen(name)+1); char *nameCopy=(char *)uprv_malloc(keyLength); if(nameCopy==NULL) { errorCode=U_MEMORY_ALLOCATION_ERROR; return NULL; } uprv_memcpy(nameCopy, name, keyLength); allModes=localAllModes.getAlias(); uhash_put(cache, nameCopy, localAllModes.orphan(), &errorCode); } else { // race condition allModes=(Norm2AllModes *)temp; } } } } if(allModes!=NULL && U_SUCCESS(errorCode)) { switch(mode) { case UNORM2_COMPOSE: return &allModes->comp; case UNORM2_DECOMPOSE: return &allModes->decomp; case UNORM2_FCD: return &allModes->fcd; case UNORM2_COMPOSE_CONTIGUOUS: return &allModes->fcc; default: break; // do nothing } } return NULL; }
U_CDECL_END static void U_CALLCONV initFromResourceBundle(UErrorCode& sts) { U_NAMESPACE_USE ucln_common_registerCleanup(UCLN_COMMON_LOCALE_KEY_TYPE, uloc_key_type_cleanup); gLocExtKeyMap = uhash_open(uhash_hashIChars, uhash_compareIChars, NULL, &sts); LocalUResourceBundlePointer keyTypeDataRes(ures_openDirect(NULL, "keyTypeData", &sts)); LocalUResourceBundlePointer keyMapRes(ures_getByKey(keyTypeDataRes.getAlias(), "keyMap", NULL, &sts)); LocalUResourceBundlePointer typeMapRes(ures_getByKey(keyTypeDataRes.getAlias(), "typeMap", NULL, &sts)); if (U_FAILURE(sts)) { return; } UErrorCode tmpSts = U_ZERO_ERROR; LocalUResourceBundlePointer typeAliasRes(ures_getByKey(keyTypeDataRes.getAlias(), "typeAlias", NULL, &tmpSts)); tmpSts = U_ZERO_ERROR; LocalUResourceBundlePointer bcpTypeAliasRes(ures_getByKey(keyTypeDataRes.getAlias(), "bcpTypeAlias", NULL, &tmpSts)); // initialize vectors storing dynamically allocated objects gKeyTypeStringPool = new UVector(uloc_deleteKeyTypeStringPoolEntry, NULL, sts); if (gKeyTypeStringPool == NULL) { if (U_SUCCESS(sts)) { sts = U_MEMORY_ALLOCATION_ERROR; } } if (U_FAILURE(sts)) { return; } gLocExtKeyDataEntries = new UVector(uloc_deleteKeyDataEntry, NULL, sts); if (gLocExtKeyDataEntries == NULL) { if (U_SUCCESS(sts)) { sts = U_MEMORY_ALLOCATION_ERROR; } } if (U_FAILURE(sts)) { return; } gLocExtTypeEntries = new UVector(uloc_deleteTypeEntry, NULL, sts); if (gLocExtTypeEntries == NULL) { if (U_SUCCESS(sts)) { sts = U_MEMORY_ALLOCATION_ERROR; } } if (U_FAILURE(sts)) { return; } // iterate through keyMap resource LocalUResourceBundlePointer keyMapEntry; while (ures_hasNext(keyMapRes.getAlias())) { keyMapEntry.adoptInstead(ures_getNextResource(keyMapRes.getAlias(), keyMapEntry.orphan(), &sts)); if (U_FAILURE(sts)) { break; } const char* legacyKeyId = ures_getKey(keyMapEntry.getAlias()); int32_t bcpKeyIdLen = 0; const UChar* uBcpKeyId = ures_getString(keyMapEntry.getAlias(), &bcpKeyIdLen, &sts); if (U_FAILURE(sts)) { break; } // empty value indicates that BCP key is same with the legacy key. const char* bcpKeyId = legacyKeyId; if (bcpKeyIdLen > 0) { char* bcpKeyIdBuf = (char*)uprv_malloc(bcpKeyIdLen + 1); if (bcpKeyIdBuf == NULL) { sts = U_MEMORY_ALLOCATION_ERROR; break; } u_UCharsToChars(uBcpKeyId, bcpKeyIdBuf, bcpKeyIdLen); bcpKeyIdBuf[bcpKeyIdLen] = 0; gKeyTypeStringPool->addElement(bcpKeyIdBuf, sts); if (U_FAILURE(sts)) { break; } bcpKeyId = bcpKeyIdBuf; } UBool isTZ = uprv_strcmp(legacyKeyId, "timezone") == 0; UHashtable* typeDataMap = uhash_open(uhash_hashIChars, uhash_compareIChars, NULL, &sts); if (U_FAILURE(sts)) { break; } uint32_t specialTypes = SPECIALTYPE_NONE; LocalUResourceBundlePointer typeAliasResByKey; LocalUResourceBundlePointer bcpTypeAliasResByKey; if (typeAliasRes.isValid()) { tmpSts = U_ZERO_ERROR; typeAliasResByKey.adoptInstead(ures_getByKey(typeAliasRes.getAlias(), legacyKeyId, NULL, &tmpSts)); if (U_FAILURE(tmpSts)) { typeAliasResByKey.orphan(); } } if (bcpTypeAliasRes.isValid()) { tmpSts = U_ZERO_ERROR; bcpTypeAliasResByKey.adoptInstead(ures_getByKey(bcpTypeAliasRes.getAlias(), bcpKeyId, NULL, &tmpSts)); if (U_FAILURE(tmpSts)) { bcpTypeAliasResByKey.orphan(); } } // look up type map for the key, and walk through the mapping data tmpSts = U_ZERO_ERROR; LocalUResourceBundlePointer typeMapResByKey(ures_getByKey(typeMapRes.getAlias(), legacyKeyId, NULL, &tmpSts)); if (U_FAILURE(tmpSts)) { // type map for each key must exist U_ASSERT(FALSE); } else { LocalUResourceBundlePointer typeMapEntry; while (ures_hasNext(typeMapResByKey.getAlias())) { typeMapEntry.adoptInstead(ures_getNextResource(typeMapResByKey.getAlias(), typeMapEntry.orphan(), &sts)); if (U_FAILURE(sts)) { break; } const char* legacyTypeId = ures_getKey(typeMapEntry.getAlias()); // special types if (uprv_strcmp(legacyTypeId, "CODEPOINTS") == 0) { specialTypes |= SPECIALTYPE_CODEPOINTS; continue; } if (uprv_strcmp(legacyTypeId, "REORDER_CODE") == 0) { specialTypes |= SPECIALTYPE_REORDER_CODE; continue; } if (uprv_strcmp(legacyTypeId, "RG_KEY_VALUE") == 0) { specialTypes |= SPECIALTYPE_RG_KEY_VALUE; continue; } if (isTZ) { // a timezone key uses a colon instead of a slash in the resource. // e.g. America:Los_Angeles if (uprv_strchr(legacyTypeId, ':') != NULL) { int32_t legacyTypeIdLen = uprv_strlen(legacyTypeId); char* legacyTypeIdBuf = (char*)uprv_malloc(legacyTypeIdLen + 1); if (legacyTypeIdBuf == NULL) { sts = U_MEMORY_ALLOCATION_ERROR; break; } const char* p = legacyTypeId; char* q = legacyTypeIdBuf; while (*p) { if (*p == ':') { *q++ = '/'; } else { *q++ = *p; } p++; } *q = 0; gKeyTypeStringPool->addElement(legacyTypeIdBuf, sts); if (U_FAILURE(sts)) { break; } legacyTypeId = legacyTypeIdBuf; } } int32_t bcpTypeIdLen = 0; const UChar* uBcpTypeId = ures_getString(typeMapEntry.getAlias(), &bcpTypeIdLen, &sts); if (U_FAILURE(sts)) { break; } // empty value indicates that BCP type is same with the legacy type. const char* bcpTypeId = legacyTypeId; if (bcpTypeIdLen > 0) { char* bcpTypeIdBuf = (char*)uprv_malloc(bcpTypeIdLen + 1); if (bcpTypeIdBuf == NULL) { sts = U_MEMORY_ALLOCATION_ERROR; break; } u_UCharsToChars(uBcpTypeId, bcpTypeIdBuf, bcpTypeIdLen); bcpTypeIdBuf[bcpTypeIdLen] = 0; gKeyTypeStringPool->addElement(bcpTypeIdBuf, sts); if (U_FAILURE(sts)) { break; } bcpTypeId = bcpTypeIdBuf; } // Note: legacy type value should never be // equivalent to bcp type value of a different // type under the same key. So we use a single // map for lookup. LocExtType* t = (LocExtType*)uprv_malloc(sizeof(LocExtType)); if (t == NULL) { sts = U_MEMORY_ALLOCATION_ERROR; break; } t->bcpId = bcpTypeId; t->legacyId = legacyTypeId; gLocExtTypeEntries->addElement((void*)t, sts); if (U_FAILURE(sts)) { break; } uhash_put(typeDataMap, (void*)legacyTypeId, t, &sts); if (bcpTypeId != legacyTypeId) { // different type value uhash_put(typeDataMap, (void*)bcpTypeId, t, &sts); } if (U_FAILURE(sts)) { break; } // also put aliases in the map if (typeAliasResByKey.isValid()) { LocalUResourceBundlePointer typeAliasDataEntry; ures_resetIterator(typeAliasResByKey.getAlias()); while (ures_hasNext(typeAliasResByKey.getAlias()) && U_SUCCESS(sts)) { int32_t toLen; typeAliasDataEntry.adoptInstead(ures_getNextResource(typeAliasResByKey.getAlias(), typeAliasDataEntry.orphan(), &sts)); const UChar* to = ures_getString(typeAliasDataEntry.getAlias(), &toLen, &sts); if (U_FAILURE(sts)) { break; } // check if this is an alias of canoncal legacy type if (uprv_compareInvWithUChar(NULL, legacyTypeId, -1, to, toLen) == 0) { const char* from = ures_getKey(typeAliasDataEntry.getAlias()); if (isTZ) { // replace colon with slash if necessary if (uprv_strchr(from, ':') != NULL) { int32_t fromLen = uprv_strlen(from); char* fromBuf = (char*)uprv_malloc(fromLen + 1); if (fromBuf == NULL) { sts = U_MEMORY_ALLOCATION_ERROR; break; } const char* p = from; char* q = fromBuf; while (*p) { if (*p == ':') { *q++ = '/'; } else { *q++ = *p; } p++; } *q = 0; gKeyTypeStringPool->addElement(fromBuf, sts); if (U_FAILURE(sts)) { break; } from = fromBuf; } } uhash_put(typeDataMap, (void*)from, t, &sts); } } if (U_FAILURE(sts)) { break; } } if (bcpTypeAliasResByKey.isValid()) { LocalUResourceBundlePointer bcpTypeAliasDataEntry; ures_resetIterator(bcpTypeAliasResByKey.getAlias()); while (ures_hasNext(bcpTypeAliasResByKey.getAlias()) && U_SUCCESS(sts)) { int32_t toLen; bcpTypeAliasDataEntry.adoptInstead(ures_getNextResource(bcpTypeAliasResByKey.getAlias(), bcpTypeAliasDataEntry.orphan(), &sts)); const UChar* to = ures_getString(bcpTypeAliasDataEntry.getAlias(), &toLen, &sts); if (U_FAILURE(sts)) { break; } // check if this is an alias of bcp type if (uprv_compareInvWithUChar(NULL, bcpTypeId, -1, to, toLen) == 0) { const char* from = ures_getKey(bcpTypeAliasDataEntry.getAlias()); uhash_put(typeDataMap, (void*)from, t, &sts); } } if (U_FAILURE(sts)) { break; } } } } if (U_FAILURE(sts)) { break; } LocExtKeyData* keyData = (LocExtKeyData*)uprv_malloc(sizeof(LocExtKeyData)); if (keyData == NULL) { sts = U_MEMORY_ALLOCATION_ERROR; break; } keyData->bcpId = bcpKeyId; keyData->legacyId = legacyKeyId; keyData->specialTypes = specialTypes; keyData->typeMap = typeDataMap; gLocExtKeyDataEntries->addElement((void*)keyData, sts); if (U_FAILURE(sts)) { break; } uhash_put(gLocExtKeyMap, (void*)legacyKeyId, keyData, &sts); if (legacyKeyId != bcpKeyId) { // different key value uhash_put(gLocExtKeyMap, (void*)bcpKeyId, keyData, &sts); } if (U_FAILURE(sts)) { break; } } }
U_CDECL_END U_NAMESPACE_BEGIN /* Reduce excessive reallocation, and make it easier to detect initialization problems. Usually you don't see smaller sets than this for Unicode 5.0. */ #define DEFAULT_INCLUSION_CAPACITY 3072 void U_CALLCONV UnicodeSet_initInclusion(int32_t src, UErrorCode &status) { // This function is invoked only via umtx_initOnce(). // This function is a friend of class UnicodeSet. U_ASSERT(src >=0 && src<UPROPS_SRC_COUNT); UnicodeSet * &incl = gInclusions[src].fSet; U_ASSERT(incl == NULL); incl = new UnicodeSet(); if (incl == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return; } USetAdder sa = { (USet *)incl, _set_add, _set_addRange, _set_addString, NULL, // don't need remove() NULL // don't need removeRange() }; incl->ensureCapacity(DEFAULT_INCLUSION_CAPACITY, status); switch(src) { case UPROPS_SRC_CHAR: uchar_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_PROPSVEC: upropsvec_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_CHAR_AND_PROPSVEC: uchar_addPropertyStarts(&sa, &status); upropsvec_addPropertyStarts(&sa, &status); break; #if !UCONFIG_NO_NORMALIZATION case UPROPS_SRC_CASE_AND_NORM: { const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(status); if(U_SUCCESS(status)) { impl->addPropertyStarts(&sa, status); } ucase_addPropertyStarts(&sa, &status); break; } case UPROPS_SRC_NFC: { const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(status); if(U_SUCCESS(status)) { impl->addPropertyStarts(&sa, status); } break; } case UPROPS_SRC_NFKC: { const Normalizer2Impl *impl=Normalizer2Factory::getNFKCImpl(status); if(U_SUCCESS(status)) { impl->addPropertyStarts(&sa, status); } break; } case UPROPS_SRC_NFKC_CF: { const Normalizer2Impl *impl=Normalizer2Factory::getNFKC_CFImpl(status); if(U_SUCCESS(status)) { impl->addPropertyStarts(&sa, status); } break; } case UPROPS_SRC_NFC_CANON_ITER: { const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(status); if(U_SUCCESS(status)) { impl->addCanonIterPropertyStarts(&sa, status); } break; } #endif case UPROPS_SRC_CASE: ucase_addPropertyStarts(&sa, &status); break; case UPROPS_SRC_BIDI: ubidi_addPropertyStarts(ubidi_getSingleton(), &sa, &status); break; default: status = U_INTERNAL_PROGRAM_ERROR; break; } if (U_FAILURE(status)) { delete incl; incl = NULL; return; } // Compact for caching incl->compact(); ucln_common_registerCleanup(UCLN_COMMON_USET, uset_cleanup); }