/*
******************************************************************************
*
-* Copyright (C) 1999-2010, International Business Machines
+* Copyright (C) 1999-2014, International Business Machines
* Corporation and others. All Rights Reserved.
*
******************************************************************************
* created by: Markus W. Scherer
*/
-#include "unicode/utypes.h" /* U_LINUX */
+#include "unicode/utypes.h" /* U_PLATFORM etc. */
-#ifdef U_LINUX
+#ifdef __GNUC__
/* if gcc
#define ATTRIBUTE_WEAK __attribute__ ((weak))
might have to #include some other header
#include "cmemory.h"
#include "cstring.h"
#include "putilimp.h"
+#include "uassert.h"
#include "ucln_cmn.h"
#include "ucmndata.h"
#include "udatamem.h"
# include <stdio.h>
#endif
-#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
-
U_NAMESPACE_USE
/*
- * Forwards
+ * Forward declarations
*/
static UDataMemory *udata_findCachedData(const char *path);
static UBool gHaveTriedToLoadCommonData = FALSE; /* See extendICUData(). */
static UHashtable *gCommonDataCache = NULL; /* Global hash table of opened ICU data files. */
+static icu::UInitOnce gCommonDataCacheInitOnce = U_INITONCE_INITIALIZER;
static UDataFileAccess gDataFileAccess = UDATA_DEFAULT_ACCESS;
uhash_close(gCommonDataCache); /* Table owns the contents, and will delete them. */
gCommonDataCache = NULL; /* Cleanup is not thread safe. */
}
+ gCommonDataCacheInitOnce.reset();
- for (i = 0; i < LENGTHOF(gCommonICUDataArray) && gCommonICUDataArray[i] != NULL; ++i) {
+ for (i = 0; i < UPRV_LENGTHOF(gCommonICUDataArray) && gCommonICUDataArray[i] != NULL; ++i) {
udata_close(gCommonICUDataArray[i]);
gCommonICUDataArray[i] = NULL;
}
if (pData == NULL)
return FALSE;
- for (i = 0; i < LENGTHOF(gCommonICUDataArray); ++i) {
+ for (i = 0; i < UPRV_LENGTHOF(gCommonICUDataArray); ++i) {
if ((gCommonICUDataArray[i] != NULL) && (gCommonICUDataArray[i]->pHeader == pData->pHeader)) {
/* The data pointer is already in the array. */
found = TRUE;
/* their locals. */
UDatamemory_assign(newCommonData, pData);
umtx_lock(NULL);
- for (i = 0; i < LENGTHOF(gCommonICUDataArray); ++i) {
+ for (i = 0; i < UPRV_LENGTHOF(gCommonICUDataArray); ++i) {
if (gCommonICUDataArray[i] == NULL) {
gCommonICUDataArray[i] = newCommonData;
- ucln_common_registerCleanup(UCLN_COMMON_UDATA, udata_cleanup);
didUpdate = TRUE;
break;
} else if (gCommonICUDataArray[i]->pHeader == pData->pHeader) {
}
umtx_unlock(NULL);
- if (i == LENGTHOF(gCommonICUDataArray) && warn) {
+ if (i == UPRV_LENGTHOF(gCommonICUDataArray) && warn) {
*pErr = U_USING_DEFAULT_WARNING;
}
- if (!didUpdate) {
+ if (didUpdate) {
+ ucln_common_registerCleanup(UCLN_COMMON_UDATA, udata_cleanup);
+ } else {
uprv_free(newCommonData);
}
return didUpdate;
setCommonICUDataPointer(const void *pData, UBool /*warn*/, UErrorCode *pErrorCode) {
UDataMemory tData;
UDataMemory_init(&tData);
- tData.pHeader = (const DataHeader *)pData;
+ UDataMemory_setData(&tData, pData);
udata_checkCommonData(&tData, pErrorCode);
return setCommonICUData(&tData, FALSE, pErrorCode);
}
uprv_free(pDCEl); /* delete 'this' */
}
- /* 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. */
+static void udata_initHashTable() {
+ UErrorCode err = U_ZERO_ERROR;
+ U_ASSERT(gCommonDataCache == NULL);
+ gCommonDataCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &err);
+ if (U_FAILURE(err)) {
+ // TODO: handle errors better.
+ gCommonDataCache = NULL;
}
- uhash_setValueDeleter(tHT, DataCacheElement_deleter);
-
- umtx_lock(NULL);
- if (gCommonDataCache == NULL) {
- gCommonDataCache = tHT;
- tHT = NULL;
+ if (gCommonDataCache != NULL) {
+ uhash_setValueDeleter(gCommonDataCache, DataCacheElement_deleter);
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. */
- }
+ /* 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() {
+ umtx_initOnce(gCommonDataCacheInitOnce, &udata_initHashTable);
return gCommonDataCache;
}
/* ??????? TODO revisit this */
if (commonDataIndex >= 0) {
/* "mini-cache" for common ICU data */
- if(commonDataIndex >= LENGTHOF(gCommonICUDataArray)) {
+ if(commonDataIndex >= UPRV_LENGTHOF(gCommonICUDataArray)) {
return NULL;
}
if(gCommonICUDataArray[commonDataIndex] == NULL) {
* Use a specific mutex to avoid nested locks of the global mutex.
*/
#if MAP_IMPLEMENTATION==MAP_STDIO
- static UMTX extendICUDataMutex = NULL;
+ static UMutex extendICUDataMutex = U_MUTEX_INITIALIZER;
umtx_lock(&extendICUDataMutex);
#endif
if(!gHaveTriedToLoadCommonData) {
/* fields in the UDataMemory that we're assigning */
/* to CommonICUData. */
- didUpdate =
+ didUpdate = /* no longer using this result */
setCommonICUData(©PData,/* The new common data. */
FALSE, /* No warnings if write didn't happen */
pErr); /* setCommonICUData honors errors; NOP if error set */
}
}
+/*
+ * Identify the Time Zone resources that are subject to special override data loading.
+ */
+static UBool isTimeZoneFile(const char *name, const char *type) {
+ return ((uprv_strcmp(type, "res") == 0) &&
+ (uprv_strcmp(name, "zoneinfo64") == 0 ||
+ uprv_strcmp(name, "timezoneTypes") == 0 ||
+ uprv_strcmp(name, "windowsZones") == 0 ||
+ uprv_strcmp(name, "metaZones") == 0));
+}
+
/*
* A note on the ownership of Mapped Memory
*
/* End of dealing with a null basename */
dataPath = u_getDataDirectory();
+ /**** Time zone individual files override */
+ if (isTimeZoneFile(name, type) && isICUData) {
+ const char *tzFilesDir = u_getTimeZoneFilesDirectory(pErrorCode);
+ if (tzFilesDir[0] != 0) {
+#ifdef UDATA_DEBUG
+ fprintf(stderr, "Trying Time Zone Files directory = %s\n", tzFilesDir);
+#endif
+ retVal = doLoadFromIndividualFiles(/* pkgName.data() */ "", tzFilesDir, tocEntryPathSuffix,
+ /* path */ "", type, name, isAcceptable, context, &subErrorCode, pErrorCode);
+ if((retVal != NULL) || U_FAILURE(*pErrorCode)) {
+ return retVal;
+ }
+ }
+ }
+
/**** COMMON PACKAGE - only if packages are first. */
if(gDataFileAccess == UDATA_PACKAGES_FIRST) {
#ifdef UDATA_DEBUG