mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
ICU-10051 Mutexes: introduce UInitOnce; remove UMTX_CHECK; replace all uses of UMTX_CHECK.
X-SVN-Rev: 33787
This commit is contained in:
parent
8ec350d593
commit
978f71fe78
51 changed files with 1274 additions and 2180 deletions
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2003-2012, International Business Machines Corporation and *
|
||||
* Copyright (C) 2003-2013, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -124,12 +124,14 @@ void BuddhistCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& stat
|
|||
}
|
||||
#endif
|
||||
|
||||
// default century
|
||||
const UDate BuddhistCalendar::fgSystemDefaultCentury = DBL_MIN;
|
||||
const int32_t BuddhistCalendar::fgSystemDefaultCenturyYear = -1;
|
||||
|
||||
UDate BuddhistCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
|
||||
int32_t BuddhistCalendar::fgSystemDefaultCenturyStartYear = -1;
|
||||
/**
|
||||
* The system maintains a static default century start date. This is initialized
|
||||
* the first time it is used. Once the system default century date and year
|
||||
* are set, they do not change.
|
||||
*/
|
||||
static UDate gSystemDefaultCenturyStart = DBL_MIN;
|
||||
static int32_t gSystemDefaultCenturyStartYear = -1;
|
||||
static UInitOnce gBCInitOnce;
|
||||
|
||||
|
||||
UBool BuddhistCalendar::haveDefaultCentury() const
|
||||
|
@ -137,75 +139,40 @@ UBool BuddhistCalendar::haveDefaultCentury() const
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
UDate BuddhistCalendar::defaultCenturyStart() const
|
||||
{
|
||||
return internalGetDefaultCenturyStart();
|
||||
}
|
||||
|
||||
int32_t BuddhistCalendar::defaultCenturyStartYear() const
|
||||
{
|
||||
return internalGetDefaultCenturyStartYear();
|
||||
}
|
||||
|
||||
UDate
|
||||
BuddhistCalendar::internalGetDefaultCenturyStart() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (needsUpdate) {
|
||||
initializeSystemDefaultCentury();
|
||||
}
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStart
|
||||
|
||||
return fgSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t
|
||||
BuddhistCalendar::internalGetDefaultCenturyStartYear() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStartYear
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (needsUpdate) {
|
||||
initializeSystemDefaultCentury();
|
||||
}
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStartYear
|
||||
|
||||
return fgSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
void
|
||||
BuddhistCalendar::initializeSystemDefaultCentury()
|
||||
static void U_CALLCONV
|
||||
initializeSystemDefaultCentury()
|
||||
{
|
||||
// initialize systemDefaultCentury and systemDefaultCenturyYear based
|
||||
// on the current time. They'll be set to 80 years before
|
||||
// the current time.
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
BuddhistCalendar calendar(Locale("@calendar=buddhist"),status);
|
||||
if (U_SUCCESS(status))
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
calendar.setTime(Calendar::getNow(), status);
|
||||
calendar.add(UCAL_YEAR, -80, status);
|
||||
UDate newStart = calendar.getTime(status);
|
||||
int32_t newYear = calendar.get(UCAL_YEAR, status);
|
||||
umtx_lock(NULL);
|
||||
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury) {
|
||||
fgSystemDefaultCenturyStartYear = newYear;
|
||||
fgSystemDefaultCenturyStart = newStart;
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
gSystemDefaultCenturyStartYear = newYear;
|
||||
gSystemDefaultCenturyStart = newStart;
|
||||
}
|
||||
// We have no recourse upon failure unless we want to propagate the failure
|
||||
// out.
|
||||
}
|
||||
|
||||
UDate BuddhistCalendar::defaultCenturyStart() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStart and systemDefaultCenturyStartYear
|
||||
umtx_initOnce(gBCInitOnce, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t BuddhistCalendar::defaultCenturyStartYear() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStartYear and systemDefaultCenturyStart
|
||||
umtx_initOnce(gBCInitOnce, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
********************************************************************************
|
||||
* Copyright (C) 2003-2007, International Business Machines Corporation
|
||||
* Copyright (C) 2003-2013, International Business Machines Corporation
|
||||
* and others. All Rights Reserved.
|
||||
********************************************************************************
|
||||
*
|
||||
|
@ -189,49 +189,6 @@ private:
|
|||
* @internal
|
||||
*/
|
||||
virtual int32_t defaultCenturyStartYear() const;
|
||||
|
||||
private: // default century stuff.
|
||||
/**
|
||||
* The system maintains a static default century start date. This is initialized
|
||||
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
|
||||
* indicate an uninitialized state. Once the system default century date and year
|
||||
* are set, they do not change.
|
||||
*/
|
||||
static UDate fgSystemDefaultCenturyStart;
|
||||
|
||||
/**
|
||||
* See documentation for systemDefaultCenturyStart.
|
||||
*/
|
||||
static int32_t fgSystemDefaultCenturyStartYear;
|
||||
|
||||
/**
|
||||
* Default value that indicates the defaultCenturyStartYear is unitialized
|
||||
*/
|
||||
static const int32_t fgSystemDefaultCenturyYear;
|
||||
|
||||
/**
|
||||
* start of default century, as a date
|
||||
*/
|
||||
static const UDate fgSystemDefaultCentury;
|
||||
|
||||
/**
|
||||
* Returns the beginning date of the 100-year window that dates
|
||||
* with 2-digit years are considered to fall within.
|
||||
*/
|
||||
UDate internalGetDefaultCenturyStart(void) const;
|
||||
|
||||
/**
|
||||
* Returns the first year of the 100-year window that dates with
|
||||
* 2-digit years are considered to fall within.
|
||||
*/
|
||||
int32_t internalGetDefaultCenturyStartYear(void) const;
|
||||
|
||||
/**
|
||||
* Initializes the 100-year window that dates with 2-digit years
|
||||
* are considered to fall within so that its start date is 80 years
|
||||
* before the current time.
|
||||
*/
|
||||
static void initializeSystemDefaultCentury(void);
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
|
||||
#if !UCONFIG_NO_SERVICE
|
||||
static icu::ICULocaleService* gService = NULL;
|
||||
static UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER;
|
||||
#endif
|
||||
|
||||
// INTERNAL - for cleanup
|
||||
|
@ -71,6 +72,7 @@ static UBool calendar_cleanup(void) {
|
|||
delete gService;
|
||||
gService = NULL;
|
||||
}
|
||||
gServiceInitOnce.reset();
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -517,64 +519,51 @@ CalendarService::~CalendarService() {}
|
|||
|
||||
static inline UBool
|
||||
isCalendarServiceUsed() {
|
||||
UBool retVal;
|
||||
UMTX_CHECK(NULL, gService != NULL, retVal);
|
||||
return retVal;
|
||||
return !gServiceInitOnce.isReset();
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
static void U_CALLCONV
|
||||
initCalendarService(UErrorCode &status)
|
||||
{
|
||||
#ifdef U_DEBUG_CALSVC
|
||||
fprintf(stderr, "Spinning up Calendar Service\n");
|
||||
#endif
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_CALENDAR, calendar_cleanup);
|
||||
gService = new CalendarService();
|
||||
if (gService == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
#ifdef U_DEBUG_CALSVC
|
||||
fprintf(stderr, "Registering classes..\n");
|
||||
#endif
|
||||
|
||||
// Register all basic instances.
|
||||
gService->registerFactory(new BasicCalendarFactory(),status);
|
||||
|
||||
#ifdef U_DEBUG_CALSVC
|
||||
fprintf(stderr, "Done..\n");
|
||||
#endif
|
||||
|
||||
if(U_FAILURE(status)) {
|
||||
#ifdef U_DEBUG_CALSVC
|
||||
fprintf(stderr, "err (%s) registering classes, deleting service.....\n", u_errorName(status));
|
||||
#endif
|
||||
delete gService;
|
||||
gService = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static ICULocaleService*
|
||||
getCalendarService(UErrorCode &status)
|
||||
{
|
||||
UBool needInit;
|
||||
UMTX_CHECK(NULL, (UBool)(gService == NULL), needInit);
|
||||
if (needInit) {
|
||||
#ifdef U_DEBUG_CALSVC
|
||||
fprintf(stderr, "Spinning up Calendar Service\n");
|
||||
#endif
|
||||
ICULocaleService * newservice = new CalendarService();
|
||||
if (newservice == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return newservice;
|
||||
}
|
||||
#ifdef U_DEBUG_CALSVC
|
||||
fprintf(stderr, "Registering classes..\n");
|
||||
#endif
|
||||
|
||||
// Register all basic instances.
|
||||
newservice->registerFactory(new BasicCalendarFactory(),status);
|
||||
|
||||
#ifdef U_DEBUG_CALSVC
|
||||
fprintf(stderr, "Done..\n");
|
||||
#endif
|
||||
|
||||
if(U_FAILURE(status)) {
|
||||
#ifdef U_DEBUG_CALSVC
|
||||
fprintf(stderr, "err (%s) registering classes, deleting service.....\n", u_errorName(status));
|
||||
#endif
|
||||
delete newservice;
|
||||
newservice = NULL;
|
||||
}
|
||||
|
||||
if (newservice) {
|
||||
umtx_lock(NULL);
|
||||
if (gService == NULL) {
|
||||
gService = newservice;
|
||||
newservice = NULL;
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
}
|
||||
if (newservice) {
|
||||
delete newservice;
|
||||
} else {
|
||||
// we won the contention - we can register the cleanup.
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_CALENDAR, calendar_cleanup);
|
||||
}
|
||||
}
|
||||
umtx_initOnce(gServiceInitOnce, &initCalendarService, status);
|
||||
return gService;
|
||||
}
|
||||
|
||||
|
||||
URegistryKey Calendar::registerFactory(ICUServiceFactory* toAdopt, UErrorCode& status)
|
||||
{
|
||||
return getCalendarService(status)->registerFactory(toAdopt, status);
|
||||
|
|
|
@ -54,7 +54,7 @@ static icu::CalendarAstronomer *gChineseCalendarAstro = NULL;
|
|||
static icu::CalendarCache *gChineseCalendarWinterSolsticeCache = NULL;
|
||||
static icu::CalendarCache *gChineseCalendarNewYearCache = NULL;
|
||||
static icu::TimeZone *gChineseCalendarZoneAstroCalc = NULL;
|
||||
static UBool gChineseCalendarZoneAstroCalcInitialized = FALSE;
|
||||
static UInitOnce gChineseCalendarZoneAstroCalcInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
/**
|
||||
* The start year of the Chinese calendar, the 61st year of the reign
|
||||
|
@ -97,7 +97,7 @@ static UBool calendar_chinese_cleanup(void) {
|
|||
delete gChineseCalendarZoneAstroCalc;
|
||||
gChineseCalendarZoneAstroCalc = NULL;
|
||||
}
|
||||
gChineseCalendarZoneAstroCalcInitialized = FALSE;
|
||||
gChineseCalendarZoneAstroCalcInitOnce.reset();
|
||||
return TRUE;
|
||||
}
|
||||
U_CDECL_END
|
||||
|
@ -150,20 +150,13 @@ const char *ChineseCalendar::getType() const {
|
|||
return "chinese";
|
||||
}
|
||||
|
||||
static void U_CALLCONV initChineseCalZoneAstroCalc() {
|
||||
gChineseCalendarZoneAstroCalc = new SimpleTimeZone(CHINA_OFFSET, UNICODE_STRING_SIMPLE("CHINA_ZONE") );
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup);
|
||||
}
|
||||
|
||||
const TimeZone* ChineseCalendar::getChineseCalZoneAstroCalc(void) const {
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&astroLock, gChineseCalendarZoneAstroCalcInitialized, initialized);
|
||||
if (!initialized) {
|
||||
umtx_lock(&astroLock);
|
||||
{
|
||||
if (!gChineseCalendarZoneAstroCalcInitialized) {
|
||||
gChineseCalendarZoneAstroCalc = new SimpleTimeZone(CHINA_OFFSET, UNICODE_STRING_SIMPLE("CHINA_ZONE") );
|
||||
gChineseCalendarZoneAstroCalcInitialized = TRUE;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup);
|
||||
}
|
||||
}
|
||||
umtx_unlock(&astroLock);
|
||||
}
|
||||
umtx_initOnce(gChineseCalendarZoneAstroCalcInitOnce, &initChineseCalZoneAstroCalc);
|
||||
return gChineseCalendarZoneAstroCalc;
|
||||
}
|
||||
|
||||
|
@ -842,11 +835,10 @@ ChineseCalendar::inDaylightTime(UErrorCode& status) const
|
|||
}
|
||||
|
||||
// default century
|
||||
const UDate ChineseCalendar::fgSystemDefaultCentury = DBL_MIN;
|
||||
const int32_t ChineseCalendar::fgSystemDefaultCenturyYear = -1;
|
||||
|
||||
UDate ChineseCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
|
||||
int32_t ChineseCalendar::fgSystemDefaultCenturyStartYear = -1;
|
||||
static UDate gSystemDefaultCenturyStart = DBL_MIN;
|
||||
static int32_t gSystemDefaultCenturyStartYear = -1;
|
||||
static UInitOnce gSystemDefaultCenturyInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
|
||||
UBool ChineseCalendar::haveDefaultCentury() const
|
||||
|
@ -864,66 +856,39 @@ int32_t ChineseCalendar::defaultCenturyStartYear() const
|
|||
return internalGetDefaultCenturyStartYear();
|
||||
}
|
||||
|
||||
UDate
|
||||
ChineseCalendar::internalGetDefaultCenturyStart() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (needsUpdate) {
|
||||
initializeSystemDefaultCentury();
|
||||
}
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStart
|
||||
|
||||
return fgSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t
|
||||
ChineseCalendar::internalGetDefaultCenturyStartYear() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStartYear
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (needsUpdate) {
|
||||
initializeSystemDefaultCentury();
|
||||
}
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStartYear
|
||||
|
||||
return fgSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
void
|
||||
ChineseCalendar::initializeSystemDefaultCentury()
|
||||
static void U_CALLCONV initializeSystemDefaultCentury()
|
||||
{
|
||||
// initialize systemDefaultCentury and systemDefaultCenturyYear based
|
||||
// on the current time. They'll be set to 80 years before
|
||||
// the current time.
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
ChineseCalendar calendar(Locale("@calendar=chinese"),status);
|
||||
if (U_SUCCESS(status))
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
calendar.setTime(Calendar::getNow(), status);
|
||||
calendar.add(UCAL_YEAR, -80, status);
|
||||
UDate newStart = calendar.getTime(status);
|
||||
int32_t newYear = calendar.get(UCAL_YEAR, status);
|
||||
umtx_lock(NULL);
|
||||
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
|
||||
{
|
||||
fgSystemDefaultCenturyStartYear = newYear;
|
||||
fgSystemDefaultCenturyStart = newStart;
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
gSystemDefaultCenturyStart = calendar.getTime(status);
|
||||
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
|
||||
}
|
||||
// We have no recourse upon failure unless we want to propagate the failure
|
||||
// out.
|
||||
}
|
||||
|
||||
UDate
|
||||
ChineseCalendar::internalGetDefaultCenturyStart() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
umtx_initOnce(gSystemDefaultCenturyInitOnce, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t
|
||||
ChineseCalendar::internalGetDefaultCenturyStartYear() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStartYear
|
||||
umtx_initOnce(gSystemDefaultCenturyInitOnce, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ChineseCalendar)
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -259,28 +259,6 @@ class U_I18N_API ChineseCalendar : public Calendar {
|
|||
virtual int32_t defaultCenturyStartYear() const;
|
||||
|
||||
private: // default century stuff.
|
||||
/**
|
||||
* The system maintains a static default century start date. This is initialized
|
||||
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
|
||||
* indicate an uninitialized state. Once the system default century date and year
|
||||
* are set, they do not change.
|
||||
*/
|
||||
static UDate fgSystemDefaultCenturyStart;
|
||||
|
||||
/**
|
||||
* See documentation for systemDefaultCenturyStart.
|
||||
*/
|
||||
static int32_t fgSystemDefaultCenturyStartYear;
|
||||
|
||||
/**
|
||||
* Default value that indicates the defaultCenturyStartYear is unitialized
|
||||
*/
|
||||
static const int32_t fgSystemDefaultCenturyYear;
|
||||
|
||||
/**
|
||||
* start of default century, as a date
|
||||
*/
|
||||
static const UDate fgSystemDefaultCentury;
|
||||
|
||||
/**
|
||||
* Returns the beginning date of the 100-year window that dates
|
||||
|
@ -294,13 +272,6 @@ class U_I18N_API ChineseCalendar : public Calendar {
|
|||
*/
|
||||
int32_t internalGetDefaultCenturyStartYear(void) const;
|
||||
|
||||
/**
|
||||
* Initializes the 100-year window that dates with 2-digit years
|
||||
* are considered to fall within so that its start date is 80 years
|
||||
* before the current time.
|
||||
*/
|
||||
static void initializeSystemDefaultCentury(void);
|
||||
|
||||
ChineseCalendar(); // default constructor not implemented
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 1996-2012, International Business Machines Corporation and
|
||||
* Copyright (C) 1996-2013, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
@ -50,6 +50,7 @@
|
|||
#include "cmemory.h"
|
||||
#include "umutex.h"
|
||||
#include "servloc.h"
|
||||
#include "uassert.h"
|
||||
#include "ustrenum.h"
|
||||
#include "uresimp.h"
|
||||
#include "ucln_in.h"
|
||||
|
@ -57,6 +58,8 @@
|
|||
static icu::Locale* availableLocaleList = NULL;
|
||||
static int32_t availableLocaleListCount;
|
||||
static icu::ICULocaleService* gService = NULL;
|
||||
static UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER;
|
||||
static UInitOnce gAvailableLocaleListInitOnce;
|
||||
|
||||
/**
|
||||
* Release all static memory held by collator.
|
||||
|
@ -68,13 +71,14 @@ static UBool U_CALLCONV collator_cleanup(void) {
|
|||
delete gService;
|
||||
gService = NULL;
|
||||
}
|
||||
gServiceInitOnce.reset();
|
||||
#endif
|
||||
if (availableLocaleList) {
|
||||
delete []availableLocaleList;
|
||||
availableLocaleList = NULL;
|
||||
}
|
||||
availableLocaleListCount = 0;
|
||||
|
||||
gAvailableLocaleListInitOnce.reset();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -199,28 +203,16 @@ ICUCollatorService::~ICUCollatorService() {}
|
|||
|
||||
// -------------------------------------
|
||||
|
||||
static void U_CALLCONV initService() {
|
||||
gService = new ICUCollatorService();
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
|
||||
}
|
||||
|
||||
|
||||
static ICULocaleService*
|
||||
getService(void)
|
||||
{
|
||||
UBool needInit;
|
||||
UMTX_CHECK(NULL, (UBool)(gService == NULL), needInit);
|
||||
if(needInit) {
|
||||
ICULocaleService *newservice = new ICUCollatorService();
|
||||
if(newservice) {
|
||||
umtx_lock(NULL);
|
||||
if(gService == NULL) {
|
||||
gService = newservice;
|
||||
newservice = NULL;
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
}
|
||||
if(newservice) {
|
||||
delete newservice;
|
||||
}
|
||||
else {
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
|
||||
}
|
||||
}
|
||||
umtx_initOnce(gServiceInitOnce, &initService);
|
||||
return gService;
|
||||
}
|
||||
|
||||
|
@ -229,8 +221,7 @@ getService(void)
|
|||
static inline UBool
|
||||
hasService(void)
|
||||
{
|
||||
UBool retVal;
|
||||
UMTX_CHECK(NULL, gService != NULL, retVal);
|
||||
UBool retVal = !gServiceInitOnce.isReset() && (getService() != NULL);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -270,57 +261,44 @@ Collator::createUCollator(const char *loc,
|
|||
}
|
||||
#endif /* UCONFIG_NO_SERVICE */
|
||||
|
||||
static UBool isAvailableLocaleListInitialized(UErrorCode &status) {
|
||||
static void U_CALLCONV
|
||||
initAvailableLocaleList(UErrorCode &status) {
|
||||
U_ASSERT(availableLocaleListCount == 0);
|
||||
U_ASSERT(availableLocaleList == NULL);
|
||||
// for now, there is a hardcoded list, so just walk through that list and set it up.
|
||||
UBool needInit;
|
||||
UMTX_CHECK(NULL, availableLocaleList == NULL, needInit);
|
||||
|
||||
if (needInit) {
|
||||
UResourceBundle *index = NULL;
|
||||
UResourceBundle installed;
|
||||
Locale * temp;
|
||||
int32_t i = 0;
|
||||
int32_t localeCount;
|
||||
UResourceBundle *index = NULL;
|
||||
UResourceBundle installed;
|
||||
int32_t i = 0;
|
||||
|
||||
ures_initStackObject(&installed);
|
||||
index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status);
|
||||
ures_getByKey(index, "InstalledLocales", &installed, &status);
|
||||
|
||||
if(U_SUCCESS(status)) {
|
||||
availableLocaleListCount = ures_getSize(&installed);
|
||||
availableLocaleList = new Locale[availableLocaleListCount];
|
||||
|
||||
ures_initStackObject(&installed);
|
||||
index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status);
|
||||
ures_getByKey(index, "InstalledLocales", &installed, &status);
|
||||
|
||||
if(U_SUCCESS(status)) {
|
||||
localeCount = ures_getSize(&installed);
|
||||
temp = new Locale[localeCount];
|
||||
|
||||
if (temp != NULL) {
|
||||
ures_resetIterator(&installed);
|
||||
while(ures_hasNext(&installed)) {
|
||||
const char *tempKey = NULL;
|
||||
ures_getNextString(&installed, NULL, &tempKey, &status);
|
||||
temp[i++] = Locale(tempKey);
|
||||
}
|
||||
|
||||
umtx_lock(NULL);
|
||||
if (availableLocaleList == NULL)
|
||||
{
|
||||
availableLocaleListCount = localeCount;
|
||||
availableLocaleList = temp;
|
||||
temp = NULL;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
|
||||
needInit = FALSE;
|
||||
if (temp) {
|
||||
delete []temp;
|
||||
}
|
||||
if (availableLocaleList != NULL) {
|
||||
ures_resetIterator(&installed);
|
||||
while(ures_hasNext(&installed)) {
|
||||
const char *tempKey = NULL;
|
||||
ures_getNextString(&installed, NULL, &tempKey, &status);
|
||||
availableLocaleList[i++] = Locale(tempKey);
|
||||
}
|
||||
|
||||
ures_close(&installed);
|
||||
}
|
||||
ures_close(index);
|
||||
U_ASSERT(availableLocaleListCount == i);
|
||||
ures_close(&installed);
|
||||
}
|
||||
return !needInit;
|
||||
ures_close(index);
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
|
||||
}
|
||||
|
||||
static UBool isAvailableLocaleListInitialized(UErrorCode &status) {
|
||||
umtx_initOnce(gAvailableLocaleListInitOnce, &initAvailableLocaleList, status);
|
||||
return U_SUCCESS(status);
|
||||
}
|
||||
|
||||
|
||||
// Collator public methods -----------------------------------------------
|
||||
|
||||
Collator* U_EXPORT2 Collator::createInstance(UErrorCode& success)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2003 - 2009, International Business Machines Corporation and *
|
||||
* Copyright (C) 2003 - 2013, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -94,62 +94,46 @@ CopticCalendar::handleComputeFields(int32_t julianDay, UErrorCode &/*status*/)
|
|||
internalSet(UCAL_DAY_OF_YEAR, (30 * month) + day);
|
||||
}
|
||||
|
||||
const UDate CopticCalendar::fgSystemDefaultCentury = DBL_MIN;
|
||||
const int32_t CopticCalendar::fgSystemDefaultCenturyYear = -1;
|
||||
/**
|
||||
* The system maintains a static default century start date and Year. They are
|
||||
* initialized the first time they are used. Once the system default century date
|
||||
* and year are set, they do not change.
|
||||
*/
|
||||
static UDate gSystemDefaultCenturyStart = DBL_MIN;
|
||||
static int32_t gSystemDefaultCenturyStartYear = -1;
|
||||
static UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
|
||||
|
||||
UDate CopticCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
|
||||
int32_t CopticCalendar::fgSystemDefaultCenturyStartYear = -1;
|
||||
|
||||
static void U_CALLCONV initializeSystemDefaultCentury() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
CopticCalendar calendar(Locale("@calendar=coptic"), status);
|
||||
if (U_SUCCESS(status)) {
|
||||
calendar.setTime(Calendar::getNow(), status);
|
||||
calendar.add(UCAL_YEAR, -80, status);
|
||||
gSystemDefaultCenturyStart = calendar.getTime(status);
|
||||
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
|
||||
}
|
||||
// We have no recourse upon failure unless we want to propagate the failure
|
||||
// out.
|
||||
}
|
||||
|
||||
UDate
|
||||
CopticCalendar::defaultCenturyStart() const
|
||||
{
|
||||
initializeSystemDefaultCentury();
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStart
|
||||
return fgSystemDefaultCenturyStart;
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t
|
||||
CopticCalendar::defaultCenturyStartYear() const
|
||||
{
|
||||
initializeSystemDefaultCentury();
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStart
|
||||
return fgSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
void
|
||||
CopticCalendar::initializeSystemDefaultCentury()
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (!needsUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
CopticCalendar calendar(Locale("@calendar=coptic"), status);
|
||||
if (U_SUCCESS(status)) {
|
||||
calendar.setTime(Calendar::getNow(), status);
|
||||
calendar.add(UCAL_YEAR, -80, status);
|
||||
UDate newStart = calendar.getTime(status);
|
||||
int32_t newYear = calendar.get(UCAL_YEAR, status);
|
||||
{
|
||||
umtx_lock(NULL);
|
||||
fgSystemDefaultCenturyStartYear = newYear;
|
||||
fgSystemDefaultCenturyStart = newStart;
|
||||
umtx_unlock(NULL);
|
||||
}
|
||||
}
|
||||
// We have no recourse upon failure unless we want to propagate the failure
|
||||
// out.
|
||||
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
CopticCalendar::getJDEpochOffset() const
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2003 - 2008, International Business Machines Corporation and *
|
||||
* Copyright (C) 2003 - 2013, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -188,36 +188,6 @@ protected:
|
|||
*/
|
||||
virtual int32_t getJDEpochOffset() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* The system maintains a static default century start date. This is initialized
|
||||
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
|
||||
* indicate an uninitialized state. Once the system default century date and year
|
||||
* are set, they do not change.
|
||||
*/
|
||||
static UDate fgSystemDefaultCenturyStart;
|
||||
|
||||
/**
|
||||
* See documentation for systemDefaultCenturyStart.
|
||||
*/
|
||||
static int32_t fgSystemDefaultCenturyStartYear;
|
||||
|
||||
/**
|
||||
* Default value that indicates the defaultCenturyStartYear is unitialized
|
||||
*/
|
||||
static const int32_t fgSystemDefaultCenturyYear;
|
||||
|
||||
/**
|
||||
* start of default century, as a date
|
||||
*/
|
||||
static const UDate fgSystemDefaultCentury;
|
||||
|
||||
/**
|
||||
* Initializes the 100-year window that dates with 2-digit years
|
||||
* are considered to fall within so that its start date is 80 years
|
||||
* before the current time.
|
||||
*/
|
||||
static void initializeSystemDefaultCentury(void);
|
||||
|
||||
public:
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
**********************************************************************
|
||||
* Copyright (C) 2005-2012, International Business Machines
|
||||
* Copyright (C) 2005-2013, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
**********************************************************************
|
||||
*/
|
||||
|
@ -32,13 +32,14 @@
|
|||
#define NEW_ARRAY(type,count) (type *) uprv_malloc((count) * sizeof(type))
|
||||
#define DELETE_ARRAY(array) uprv_free((void *) (array))
|
||||
|
||||
U_CDECL_BEGIN
|
||||
static icu::CharsetRecognizer **fCSRecognizers = NULL;
|
||||
|
||||
static UInitOnce gCSRecognizersInitOnce;
|
||||
static int32_t fCSRecognizers_size = 0;
|
||||
|
||||
U_CDECL_BEGIN
|
||||
static UBool U_CALLCONV csdet_cleanup(void)
|
||||
{
|
||||
U_NAMESPACE_USE
|
||||
if (fCSRecognizers != NULL) {
|
||||
for(int32_t r = 0; r < fCSRecognizers_size; r += 1) {
|
||||
delete fCSRecognizers[r];
|
||||
|
@ -49,6 +50,7 @@ static UBool U_CALLCONV csdet_cleanup(void)
|
|||
fCSRecognizers = NULL;
|
||||
fCSRecognizers_size = 0;
|
||||
}
|
||||
gCSRecognizersInitOnce.reset();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -65,96 +67,67 @@ charsetMatchComparator(const void * /*context*/, const void *left, const void *r
|
|||
return (*csm_r)->getConfidence() - (*csm_l)->getConfidence();
|
||||
}
|
||||
|
||||
static void U_CALLCONV initRecognizers(UErrorCode &status) {
|
||||
U_NAMESPACE_USE
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_CSDET, csdet_cleanup);
|
||||
CharsetRecognizer *tempArray[] = {
|
||||
new CharsetRecog_UTF8(),
|
||||
|
||||
new CharsetRecog_UTF_16_BE(),
|
||||
new CharsetRecog_UTF_16_LE(),
|
||||
new CharsetRecog_UTF_32_BE(),
|
||||
new CharsetRecog_UTF_32_LE(),
|
||||
|
||||
new CharsetRecog_8859_1(),
|
||||
new CharsetRecog_8859_2(),
|
||||
new CharsetRecog_8859_5_ru(),
|
||||
new CharsetRecog_8859_6_ar(),
|
||||
new CharsetRecog_8859_7_el(),
|
||||
new CharsetRecog_8859_8_I_he(),
|
||||
new CharsetRecog_8859_8_he(),
|
||||
new CharsetRecog_windows_1251(),
|
||||
new CharsetRecog_windows_1256(),
|
||||
new CharsetRecog_KOI8_R(),
|
||||
new CharsetRecog_8859_9_tr(),
|
||||
new CharsetRecog_sjis(),
|
||||
new CharsetRecog_gb_18030(),
|
||||
new CharsetRecog_euc_jp(),
|
||||
new CharsetRecog_euc_kr(),
|
||||
new CharsetRecog_big5(),
|
||||
|
||||
new CharsetRecog_2022JP(),
|
||||
new CharsetRecog_2022KR(),
|
||||
new CharsetRecog_2022CN(),
|
||||
|
||||
new CharsetRecog_IBM424_he_rtl(),
|
||||
new CharsetRecog_IBM424_he_ltr(),
|
||||
new CharsetRecog_IBM420_ar_rtl(),
|
||||
new CharsetRecog_IBM420_ar_ltr()
|
||||
};
|
||||
int32_t rCount = ARRAY_SIZE(tempArray);
|
||||
|
||||
fCSRecognizers = NEW_ARRAY(CharsetRecognizer *, rCount);
|
||||
|
||||
if (fCSRecognizers == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else {
|
||||
fCSRecognizers_size = rCount;
|
||||
for (int32_t r = 0; r < rCount; r += 1) {
|
||||
fCSRecognizers[r] = tempArray[r];
|
||||
if (fCSRecognizers[r] == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
U_CDECL_END
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
void CharsetDetector::setRecognizers(UErrorCode &status)
|
||||
{
|
||||
UBool needsInit;
|
||||
CharsetRecognizer **recognizers;
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
UMTX_CHECK(NULL, (UBool) (fCSRecognizers == NULL), needsInit);
|
||||
|
||||
if (needsInit) {
|
||||
CharsetRecognizer *tempArray[] = {
|
||||
new CharsetRecog_UTF8(),
|
||||
|
||||
new CharsetRecog_UTF_16_BE(),
|
||||
new CharsetRecog_UTF_16_LE(),
|
||||
new CharsetRecog_UTF_32_BE(),
|
||||
new CharsetRecog_UTF_32_LE(),
|
||||
|
||||
new CharsetRecog_8859_1(),
|
||||
new CharsetRecog_8859_2(),
|
||||
new CharsetRecog_8859_5_ru(),
|
||||
new CharsetRecog_8859_6_ar(),
|
||||
new CharsetRecog_8859_7_el(),
|
||||
new CharsetRecog_8859_8_I_he(),
|
||||
new CharsetRecog_8859_8_he(),
|
||||
new CharsetRecog_windows_1251(),
|
||||
new CharsetRecog_windows_1256(),
|
||||
new CharsetRecog_KOI8_R(),
|
||||
new CharsetRecog_8859_9_tr(),
|
||||
new CharsetRecog_sjis(),
|
||||
new CharsetRecog_gb_18030(),
|
||||
new CharsetRecog_euc_jp(),
|
||||
new CharsetRecog_euc_kr(),
|
||||
new CharsetRecog_big5(),
|
||||
|
||||
new CharsetRecog_2022JP(),
|
||||
new CharsetRecog_2022KR(),
|
||||
new CharsetRecog_2022CN(),
|
||||
|
||||
new CharsetRecog_IBM424_he_rtl(),
|
||||
new CharsetRecog_IBM424_he_ltr(),
|
||||
new CharsetRecog_IBM420_ar_rtl(),
|
||||
new CharsetRecog_IBM420_ar_ltr()
|
||||
};
|
||||
int32_t rCount = ARRAY_SIZE(tempArray);
|
||||
int32_t r;
|
||||
|
||||
recognizers = NEW_ARRAY(CharsetRecognizer *, rCount);
|
||||
|
||||
if (recognizers == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
} else {
|
||||
for (r = 0; r < rCount; r += 1) {
|
||||
recognizers[r] = tempArray[r];
|
||||
|
||||
if (recognizers[r] == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (U_SUCCESS(status)) {
|
||||
umtx_lock(NULL);
|
||||
if (fCSRecognizers == NULL) {
|
||||
fCSRecognizers_size = rCount;
|
||||
fCSRecognizers = recognizers;
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
}
|
||||
|
||||
if (fCSRecognizers != recognizers) {
|
||||
for (r = 0; r < rCount; r += 1) {
|
||||
delete recognizers[r];
|
||||
recognizers[r] = NULL;
|
||||
}
|
||||
|
||||
DELETE_ARRAY(recognizers);
|
||||
}
|
||||
|
||||
recognizers = NULL;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_CSDET, csdet_cleanup);
|
||||
}
|
||||
umtx_initOnce(gCSRecognizersInitOnce, &initRecognizers, status);
|
||||
}
|
||||
|
||||
CharsetDetector::CharsetDetector(UErrorCode &status)
|
||||
|
|
|
@ -13,16 +13,16 @@
|
|||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "umutex.h"
|
||||
#include "gregoimp.h" // Math
|
||||
#include "uassert.h"
|
||||
#include "ucln_in.h"
|
||||
#include "umutex.h"
|
||||
#include "unicode/rbtz.h"
|
||||
#include "unicode/tzrule.h"
|
||||
#include "ucln_in.h"
|
||||
|
||||
// --- The cache --
|
||||
static UMutex dangiLock = U_MUTEX_INITIALIZER;
|
||||
static icu::TimeZone *gDangiCalendarZoneAstroCalc = NULL;
|
||||
static UBool gDangiCalendarZoneAstroCalcInitialized = FALSE;
|
||||
static UInitOnce gDangiCalendarInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
/**
|
||||
* The start year of the Korean traditional calendar (Dan-gi) is the inaugural
|
||||
|
@ -36,7 +36,7 @@ static UBool calendar_dangi_cleanup(void) {
|
|||
delete gDangiCalendarZoneAstroCalc;
|
||||
gDangiCalendarZoneAstroCalc = NULL;
|
||||
}
|
||||
gDangiCalendarZoneAstroCalcInitialized = FALSE;
|
||||
gDangiCalendarInitOnce.reset();
|
||||
return TRUE;
|
||||
}
|
||||
U_CDECL_END
|
||||
|
@ -101,41 +101,36 @@ const char *DangiCalendar::getType() const {
|
|||
* 1898-1911: GMT+8
|
||||
* 1912- : GMT+9
|
||||
*/
|
||||
const TimeZone* DangiCalendar::getDangiCalZoneAstroCalc(void) const {
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&dangiLock, gDangiCalendarZoneAstroCalcInitialized, initialized);
|
||||
if (!initialized) {
|
||||
umtx_lock(&dangiLock);
|
||||
{
|
||||
if (!gDangiCalendarZoneAstroCalcInitialized) {
|
||||
const UDate millis1897[] = { (UDate)((1897 - 1970) * 365 * kOneDay) }; // some days of error is not a problem here
|
||||
const UDate millis1898[] = { (UDate)((1898 - 1970) * 365 * kOneDay) }; // some days of error is not a problem here
|
||||
const UDate millis1912[] = { (UDate)((1912 - 1970) * 365 * kOneDay) }; // this doesn't create an issue for 1911/12/20
|
||||
InitialTimeZoneRule* initialTimeZone = new InitialTimeZoneRule(UNICODE_STRING_SIMPLE("GMT+8"), 8*kOneHour, 0);
|
||||
TimeZoneRule* rule1897 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1897"), 7*kOneHour, 0, millis1897, 1, DateTimeRule::STANDARD_TIME);
|
||||
TimeZoneRule* rule1898to1911 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1898-1911"), 8*kOneHour, 0, millis1898, 1, DateTimeRule::STANDARD_TIME);
|
||||
TimeZoneRule* ruleFrom1912 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1912-"), 9*kOneHour, 0, millis1912, 1, DateTimeRule::STANDARD_TIME);
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
RuleBasedTimeZone* dangiCalZoneAstroCalc = new RuleBasedTimeZone(UNICODE_STRING_SIMPLE("KOREA_ZONE"), initialTimeZone); // adopts initialTimeZone
|
||||
dangiCalZoneAstroCalc->addTransitionRule(rule1897, status); // adopts rule1897
|
||||
dangiCalZoneAstroCalc->addTransitionRule(rule1898to1911, status);
|
||||
dangiCalZoneAstroCalc->addTransitionRule(ruleFrom1912, status);
|
||||
dangiCalZoneAstroCalc->complete(status);
|
||||
if (U_SUCCESS(status)) {
|
||||
gDangiCalendarZoneAstroCalc = dangiCalZoneAstroCalc;
|
||||
} else {
|
||||
delete dangiCalZoneAstroCalc;
|
||||
gDangiCalendarZoneAstroCalc = NULL;
|
||||
}
|
||||
gDangiCalendarZoneAstroCalcInitialized = TRUE;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_DANGI_CALENDAR, calendar_dangi_cleanup);
|
||||
}
|
||||
}
|
||||
umtx_unlock(&dangiLock);
|
||||
static void U_CALLCONV initDangiCalZoneAstroCalc(void) {
|
||||
U_ASSERT(gDangiCalendarZoneAstroCalc == NULL);
|
||||
const UDate millis1897[] = { (UDate)((1897 - 1970) * 365 * kOneDay) }; // some days of error is not a problem here
|
||||
const UDate millis1898[] = { (UDate)((1898 - 1970) * 365 * kOneDay) }; // some days of error is not a problem here
|
||||
const UDate millis1912[] = { (UDate)((1912 - 1970) * 365 * kOneDay) }; // this doesn't create an issue for 1911/12/20
|
||||
InitialTimeZoneRule* initialTimeZone = new InitialTimeZoneRule(UNICODE_STRING_SIMPLE("GMT+8"), 8*kOneHour, 0);
|
||||
TimeZoneRule* rule1897 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1897"), 7*kOneHour, 0, millis1897, 1, DateTimeRule::STANDARD_TIME);
|
||||
TimeZoneRule* rule1898to1911 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1898-1911"), 8*kOneHour, 0, millis1898, 1, DateTimeRule::STANDARD_TIME);
|
||||
TimeZoneRule* ruleFrom1912 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1912-"), 9*kOneHour, 0, millis1912, 1, DateTimeRule::STANDARD_TIME);
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
RuleBasedTimeZone* dangiCalZoneAstroCalc = new RuleBasedTimeZone(UNICODE_STRING_SIMPLE("KOREA_ZONE"), initialTimeZone); // adopts initialTimeZone
|
||||
dangiCalZoneAstroCalc->addTransitionRule(rule1897, status); // adopts rule1897
|
||||
dangiCalZoneAstroCalc->addTransitionRule(rule1898to1911, status);
|
||||
dangiCalZoneAstroCalc->addTransitionRule(ruleFrom1912, status);
|
||||
dangiCalZoneAstroCalc->complete(status);
|
||||
if (U_SUCCESS(status)) {
|
||||
gDangiCalendarZoneAstroCalc = dangiCalZoneAstroCalc;
|
||||
} else {
|
||||
delete dangiCalZoneAstroCalc;
|
||||
gDangiCalendarZoneAstroCalc = NULL;
|
||||
}
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_DANGI_CALENDAR, calendar_dangi_cleanup);
|
||||
}
|
||||
|
||||
const TimeZone* DangiCalendar::getDangiCalZoneAstroCalc(void) const {
|
||||
umtx_initOnce(gDangiCalendarInitOnce, &initDangiCalZoneAstroCalc);
|
||||
return gDangiCalendarZoneAstroCalc;
|
||||
}
|
||||
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DangiCalendar)
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2011, International Business Machines Corporation and *
|
||||
* Copyright (C) 2009-2013, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -70,9 +70,7 @@ static const UChar gStrictDashEquivalentsPattern[] = {
|
|||
0x005B, 0x005C, 0x002D, 0x2212, 0x005D, 0x0000};
|
||||
|
||||
|
||||
DecimalFormatStaticSets *DecimalFormatStaticSets::gStaticSets = NULL;
|
||||
|
||||
DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status)
|
||||
DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode &status)
|
||||
: fDotEquivalents(NULL),
|
||||
fCommaEquivalents(NULL),
|
||||
fOtherGroupingSeparators(NULL),
|
||||
|
@ -84,15 +82,15 @@ DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status)
|
|||
fDefaultGroupingSeparators(NULL),
|
||||
fStrictDefaultGroupingSeparators(NULL)
|
||||
{
|
||||
fDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gDotEquivalentsPattern, -1), *status);
|
||||
fCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gCommaEquivalentsPattern, -1), *status);
|
||||
fOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gOtherGroupingSeparatorsPattern, -1), *status);
|
||||
fDashEquivalents = new UnicodeSet(UnicodeString(TRUE, gDashEquivalentsPattern, -1), *status);
|
||||
fDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gDotEquivalentsPattern, -1), status);
|
||||
fCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gCommaEquivalentsPattern, -1), status);
|
||||
fOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gOtherGroupingSeparatorsPattern, -1), status);
|
||||
fDashEquivalents = new UnicodeSet(UnicodeString(TRUE, gDashEquivalentsPattern, -1), status);
|
||||
|
||||
fStrictDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDotEquivalentsPattern, -1), *status);
|
||||
fStrictCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictCommaEquivalentsPattern, -1), *status);
|
||||
fStrictOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gStrictOtherGroupingSeparatorsPattern, -1), *status);
|
||||
fStrictDashEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDashEquivalentsPattern, -1), *status);
|
||||
fStrictDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDotEquivalentsPattern, -1), status);
|
||||
fStrictCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictCommaEquivalentsPattern, -1), status);
|
||||
fStrictOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gStrictOtherGroupingSeparatorsPattern, -1), status);
|
||||
fStrictDashEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDashEquivalentsPattern, -1), status);
|
||||
|
||||
|
||||
fDefaultGroupingSeparators = new UnicodeSet(*fDotEquivalents);
|
||||
|
@ -137,7 +135,7 @@ ExitConstrDeleteAll: // Remove fPropSets and fRuleSets and return error
|
|||
delete fStrictDefaultGroupingSeparators; fStrictDefaultGroupingSeparators = NULL;
|
||||
delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
|
||||
|
||||
*status = U_MEMORY_ALLOCATION_ERROR;
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
@ -156,68 +154,50 @@ DecimalFormatStaticSets::~DecimalFormatStaticSets() {
|
|||
}
|
||||
|
||||
|
||||
static DecimalFormatStaticSets *gStaticSets;
|
||||
static UInitOnce gStaticSetsInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// decfmt_cleanup Memory cleanup function, free/delete all
|
||||
// cached memory. Called by ICU's u_cleanup() function.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
UBool
|
||||
DecimalFormatStaticSets::cleanup(void)
|
||||
{
|
||||
delete DecimalFormatStaticSets::gStaticSets;
|
||||
DecimalFormatStaticSets::gStaticSets = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
U_CDECL_BEGIN
|
||||
static UBool U_CALLCONV
|
||||
decimfmt_cleanup(void)
|
||||
{
|
||||
return DecimalFormatStaticSets::cleanup();
|
||||
delete gStaticSets;
|
||||
gStaticSets = NULL;
|
||||
gStaticSetsInitOnce.reset();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void U_CALLCONV initSets(UErrorCode &status) {
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_DECFMT, decimfmt_cleanup);
|
||||
gStaticSets = new DecimalFormatStaticSets(status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete gStaticSets;
|
||||
gStaticSets = NULL;
|
||||
return;
|
||||
}
|
||||
if (gStaticSets == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
}
|
||||
U_CDECL_END
|
||||
|
||||
void DecimalFormatStaticSets::initSets(UErrorCode *status)
|
||||
{
|
||||
DecimalFormatStaticSets *p;
|
||||
|
||||
UMTX_CHECK(NULL, gStaticSets, p);
|
||||
if (p == NULL) {
|
||||
p = new DecimalFormatStaticSets(status);
|
||||
|
||||
if (p == NULL) {
|
||||
*status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
if (U_FAILURE(*status)) {
|
||||
delete p;
|
||||
return;
|
||||
}
|
||||
|
||||
umtx_lock(NULL);
|
||||
if (gStaticSets == NULL) {
|
||||
gStaticSets = p;
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
umtx_unlock(NULL);
|
||||
if (p != NULL) {
|
||||
delete p;
|
||||
}
|
||||
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_DECFMT, decimfmt_cleanup);
|
||||
}
|
||||
const DecimalFormatStaticSets *DecimalFormatStaticSets::getStaticSets(UErrorCode &status) {
|
||||
umtx_initOnce(gStaticSetsInitOnce, initSets, status);
|
||||
return gStaticSets;
|
||||
}
|
||||
|
||||
|
||||
const UnicodeSet *DecimalFormatStaticSets::getSimilarDecimals(UChar32 decimal, UBool strictParse)
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
initSets(&status);
|
||||
|
||||
umtx_initOnce(gStaticSetsInitOnce, initSets, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2011, International Business Machines Corporation and *
|
||||
* Copyright (C) 2009-2013, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -26,14 +26,15 @@ class UnicodeSet;
|
|||
class DecimalFormatStaticSets : public UMemory
|
||||
{
|
||||
public:
|
||||
static DecimalFormatStaticSets *gStaticSets; // Ptr to all lazily initialized constant
|
||||
// shared sets.
|
||||
|
||||
DecimalFormatStaticSets(UErrorCode *status);
|
||||
// Constructor and Destructor not for general use.
|
||||
// Public to permit access from plain C implementation functions.
|
||||
DecimalFormatStaticSets(UErrorCode &status);
|
||||
~DecimalFormatStaticSets();
|
||||
|
||||
static void initSets(UErrorCode *status);
|
||||
static UBool cleanup();
|
||||
/**
|
||||
* Return a pointer to a lazy-initialized singleton instance of this class.
|
||||
*/
|
||||
static const DecimalFormatStaticSets *getStaticSets(UErrorCode &status);
|
||||
|
||||
static const UnicodeSet *getSimilarDecimals(UChar32 decimal, UBool strictParse);
|
||||
|
||||
|
|
|
@ -269,7 +269,7 @@ inline int32_t _max(int32_t a, int32_t b) { return (a<b) ? b : a; }
|
|||
// Constructs a DecimalFormat instance in the default locale.
|
||||
|
||||
DecimalFormat::DecimalFormat(UErrorCode& status) {
|
||||
init(status);
|
||||
init();
|
||||
UParseError parseError;
|
||||
construct(status, parseError);
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ DecimalFormat::DecimalFormat(UErrorCode& status) {
|
|||
|
||||
DecimalFormat::DecimalFormat(const UnicodeString& pattern,
|
||||
UErrorCode& status) {
|
||||
init(status);
|
||||
init();
|
||||
UParseError parseError;
|
||||
construct(status, parseError, &pattern);
|
||||
}
|
||||
|
@ -293,7 +293,7 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern,
|
|||
DecimalFormat::DecimalFormat(const UnicodeString& pattern,
|
||||
DecimalFormatSymbols* symbolsToAdopt,
|
||||
UErrorCode& status) {
|
||||
init(status);
|
||||
init();
|
||||
UParseError parseError;
|
||||
if (symbolsToAdopt == NULL)
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
|
@ -304,7 +304,7 @@ DecimalFormat::DecimalFormat( const UnicodeString& pattern,
|
|||
DecimalFormatSymbols* symbolsToAdopt,
|
||||
UParseError& parseErr,
|
||||
UErrorCode& status) {
|
||||
init(status);
|
||||
init();
|
||||
if (symbolsToAdopt == NULL)
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
construct(status,parseErr, &pattern, symbolsToAdopt);
|
||||
|
@ -318,7 +318,7 @@ DecimalFormat::DecimalFormat( const UnicodeString& pattern,
|
|||
DecimalFormat::DecimalFormat(const UnicodeString& pattern,
|
||||
const DecimalFormatSymbols& symbols,
|
||||
UErrorCode& status) {
|
||||
init(status);
|
||||
init();
|
||||
UParseError parseError;
|
||||
construct(status, parseError, &pattern, new DecimalFormatSymbols(symbols));
|
||||
}
|
||||
|
@ -332,7 +332,7 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern,
|
|||
DecimalFormatSymbols* symbolsToAdopt,
|
||||
UNumberFormatStyle style,
|
||||
UErrorCode& status) {
|
||||
init(status);
|
||||
init();
|
||||
fStyle = style;
|
||||
UParseError parseError;
|
||||
construct(status, parseError, &pattern, symbolsToAdopt);
|
||||
|
@ -342,8 +342,10 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern,
|
|||
// Common DecimalFormat initialization.
|
||||
// Put all fields of an uninitialized object into a known state.
|
||||
// Common code, shared by all constructors.
|
||||
// Can not fail. Leave the object in good enough shape that the destructor
|
||||
// or assignment operator can run successfully.
|
||||
void
|
||||
DecimalFormat::init(UErrorCode &status) {
|
||||
DecimalFormat::init() {
|
||||
fPosPrefixPattern = 0;
|
||||
fPosSuffixPattern = 0;
|
||||
fNegPrefixPattern = 0;
|
||||
|
@ -382,8 +384,7 @@ DecimalFormat::init(UErrorCode &status) {
|
|||
data.fFastFormatStatus=kFastpathUNKNOWN; // don't try to calculate the fastpath until later.
|
||||
data.fFastParseStatus=kFastpathUNKNOWN; // don't try to calculate the fastpath until later.
|
||||
#endif
|
||||
// only do this once per obj.
|
||||
DecimalFormatStaticSets::initSets(&status);
|
||||
fStaticSets = NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -392,7 +393,7 @@ DecimalFormat::init(UErrorCode &status) {
|
|||
// created instance owns the symbols.
|
||||
|
||||
void
|
||||
DecimalFormat::construct(UErrorCode& status,
|
||||
DecimalFormat::construct(UErrorCode& status,
|
||||
UParseError& parseErr,
|
||||
const UnicodeString* pattern,
|
||||
DecimalFormatSymbols* symbolsToAdopt)
|
||||
|
@ -417,12 +418,15 @@ DecimalFormat::construct(UErrorCode& status,
|
|||
if (fSymbols == NULL)
|
||||
{
|
||||
fSymbols = new DecimalFormatSymbols(Locale::getDefault(), status);
|
||||
/* test for NULL */
|
||||
if (fSymbols == 0) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
fStaticSets = DecimalFormatStaticSets::getStaticSets(status);
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
UErrorCode nsStatus = U_ZERO_ERROR;
|
||||
NumberingSystem *ns = NumberingSystem::createInstance(nsStatus);
|
||||
if (U_FAILURE(nsStatus)) {
|
||||
|
@ -695,8 +699,7 @@ DecimalFormat::~DecimalFormat()
|
|||
|
||||
DecimalFormat::DecimalFormat(const DecimalFormat &source) :
|
||||
NumberFormat(source) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
init(status); // if this fails, 'source' isn't initialized properly either.
|
||||
init();
|
||||
*this = source;
|
||||
}
|
||||
|
||||
|
@ -729,7 +732,9 @@ DecimalFormat&
|
|||
DecimalFormat::operator=(const DecimalFormat& rhs)
|
||||
{
|
||||
if(this != &rhs) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
NumberFormat::operator=(rhs);
|
||||
fStaticSets = DecimalFormatStaticSets::getStaticSets(status);
|
||||
fPositivePrefix = rhs.fPositivePrefix;
|
||||
fPositiveSuffix = rhs.fPositiveSuffix;
|
||||
fNegativePrefix = rhs.fNegativePrefix;
|
||||
|
@ -2432,9 +2437,9 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
|
|||
|
||||
if (groupingCharLength == groupingStringLength) {
|
||||
if (strictParse) {
|
||||
groupingSet = DecimalFormatStaticSets::gStaticSets->fStrictDefaultGroupingSeparators;
|
||||
groupingSet = fStaticSets->fStrictDefaultGroupingSeparators;
|
||||
} else {
|
||||
groupingSet = DecimalFormatStaticSets::gStaticSets->fDefaultGroupingSeparators;
|
||||
groupingSet = fStaticSets->fDefaultGroupingSeparators;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2837,9 +2842,14 @@ int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
|
|||
int32_t inputLength = input.length();
|
||||
int32_t affixCharLength = U16_LENGTH(affixChar);
|
||||
UnicodeSet *affixSet;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
const DecimalFormatStaticSets *staticSets = DecimalFormatStaticSets::getStaticSets(status);
|
||||
if (U_FAILURE(status)) {
|
||||
return -1;
|
||||
}
|
||||
if (!lenient) {
|
||||
affixSet = DecimalFormatStaticSets::gStaticSets->fStrictDashEquivalents;
|
||||
affixSet = staticSets->fStrictDashEquivalents;
|
||||
|
||||
// If the affix is exactly one character long and that character
|
||||
// is in the dash set and the very next input character is also
|
||||
|
@ -2905,7 +2915,7 @@ int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
|
|||
} else {
|
||||
UBool match = FALSE;
|
||||
|
||||
affixSet = DecimalFormatStaticSets::gStaticSets->fDashEquivalents;
|
||||
affixSet = staticSets->fDashEquivalents;
|
||||
|
||||
if (affixCharLength == affixLength && affixSet->contains(affixChar)) {
|
||||
pos = skipUWhiteSpace(input, pos);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2003 - 2009, International Business Machines Corporation and *
|
||||
* Copyright (C) 2003 - 2013, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -134,58 +134,49 @@ EthiopicCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType
|
|||
return CECalendar::handleGetLimit(field, limitType);
|
||||
}
|
||||
|
||||
const UDate EthiopicCalendar::fgSystemDefaultCentury = DBL_MIN;
|
||||
const int32_t EthiopicCalendar::fgSystemDefaultCenturyYear = -1;
|
||||
/**
|
||||
* The system maintains a static default century start date and Year. They are
|
||||
* initialized the first time they are used. Once the system default century date
|
||||
* and year are set, they do not change.
|
||||
*/
|
||||
static UDate gSystemDefaultCenturyStart = DBL_MIN;
|
||||
static int32_t gSystemDefaultCenturyStartYear = -1;
|
||||
static UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
|
||||
|
||||
UDate EthiopicCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
|
||||
int32_t EthiopicCalendar::fgSystemDefaultCenturyStartYear = -1;
|
||||
static void U_CALLCONV initializeSystemDefaultCentury()
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
EthiopicCalendar calendar(Locale("@calendar=ethiopic"), status);
|
||||
if (U_SUCCESS(status)) {
|
||||
calendar.setTime(Calendar::getNow(), status);
|
||||
calendar.add(UCAL_YEAR, -80, status);
|
||||
|
||||
gSystemDefaultCenturyStart = calendar.getTime(status);
|
||||
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
|
||||
}
|
||||
// We have no recourse upon failure unless we want to propagate the failure
|
||||
// out.
|
||||
}
|
||||
|
||||
UDate
|
||||
EthiopicCalendar::defaultCenturyStart() const
|
||||
{
|
||||
initializeSystemDefaultCentury();
|
||||
return fgSystemDefaultCenturyStart;
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t
|
||||
EthiopicCalendar::defaultCenturyStartYear() const
|
||||
{
|
||||
initializeSystemDefaultCentury();
|
||||
// lazy-evaluate systemDefaultCenturyStartYear
|
||||
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
|
||||
if (isAmeteAlemEra()) {
|
||||
return fgSystemDefaultCenturyStartYear + AMETE_MIHRET_DELTA;
|
||||
return gSystemDefaultCenturyStartYear + AMETE_MIHRET_DELTA;
|
||||
}
|
||||
return fgSystemDefaultCenturyStartYear;
|
||||
return gSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
void
|
||||
EthiopicCalendar::initializeSystemDefaultCentury()
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (!needsUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
EthiopicCalendar calendar(Locale("@calendar=ethiopic"), status);
|
||||
if (U_SUCCESS(status)) {
|
||||
calendar.setTime(Calendar::getNow(), status);
|
||||
calendar.add(UCAL_YEAR, -80, status);
|
||||
UDate newStart = calendar.getTime(status);
|
||||
int32_t newYear = calendar.get(UCAL_YEAR, status);
|
||||
{
|
||||
umtx_lock(NULL);
|
||||
fgSystemDefaultCenturyStartYear = newYear;
|
||||
fgSystemDefaultCenturyStart = newStart;
|
||||
umtx_unlock(NULL);
|
||||
}
|
||||
}
|
||||
// We have no recourse upon failure unless we want to propagate the failure
|
||||
// out.
|
||||
}
|
||||
|
||||
int32_t
|
||||
EthiopicCalendar::getJDEpochOffset() const
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2003 - 2008, International Business Machines Corporation and *
|
||||
* Copyright (C) 2003 - 2013, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -205,36 +205,6 @@ protected:
|
|||
virtual int32_t getJDEpochOffset() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* The system maintains a static default century start date. This is initialized
|
||||
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
|
||||
* indicate an uninitialized state. Once the system default century date and year
|
||||
* are set, they do not change.
|
||||
*/
|
||||
static UDate fgSystemDefaultCenturyStart;
|
||||
|
||||
/**
|
||||
* See documentation for systemDefaultCenturyStart.
|
||||
*/
|
||||
static int32_t fgSystemDefaultCenturyStartYear;
|
||||
|
||||
/**
|
||||
* Default value that indicates the defaultCenturyStartYear is unitialized
|
||||
*/
|
||||
static const int32_t fgSystemDefaultCenturyYear;
|
||||
|
||||
/**
|
||||
* start of default century, as a date
|
||||
*/
|
||||
static const UDate fgSystemDefaultCentury;
|
||||
|
||||
/**
|
||||
* Initializes the 100-year window that dates with 2-digit years
|
||||
* are considered to fall within so that its start date is 80 years
|
||||
* before the current time.
|
||||
*/
|
||||
static void initializeSystemDefaultCentury(void);
|
||||
|
||||
/**
|
||||
* When eraType is AMETE_ALEM_ERA, then this calendar use only AMETE_ALEM
|
||||
* for the era. Otherwise (default), this calendar uses both AMETE_ALEM
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2008-2012, International Business Machines Corporation and
|
||||
* Copyright (C) 2008-2013, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -24,6 +24,7 @@
|
|||
#include "cmemory.h"
|
||||
#include "cstring.h"
|
||||
#include "mutex.h"
|
||||
#include "uassert.h"
|
||||
#include "ucln_in.h"
|
||||
#include "umutex.h"
|
||||
#include "uhash.h"
|
||||
|
@ -34,6 +35,7 @@ static const char* gNeutralStr = "neutral";
|
|||
static const char* gMailTaintsStr = "maleTaints";
|
||||
static const char* gMixedNeutralStr = "mixedNeutral";
|
||||
static icu::GenderInfo* gObjs = NULL;
|
||||
static UInitOnce gGenderInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
enum GenderStyle {
|
||||
NEUTRAL,
|
||||
|
@ -50,6 +52,7 @@ static UBool U_CALLCONV gender_cleanup(void) {
|
|||
gGenderInfoCache = NULL;
|
||||
delete [] gObjs;
|
||||
}
|
||||
gGenderInitOnce.reset();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -57,6 +60,29 @@ U_CDECL_END
|
|||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
void U_CALLCONV GenderInfo_initCache(UErrorCode &status) {
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_GENDERINFO, gender_cleanup);
|
||||
U_ASSERT(gGenderInfoCache == NULL);
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
gObjs = new GenderInfo[GENDER_STYLE_LENGTH];
|
||||
if (gObjs == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < GENDER_STYLE_LENGTH; i++) {
|
||||
gObjs[i]._style = i;
|
||||
}
|
||||
gGenderInfoCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete [] gObjs;
|
||||
return;
|
||||
}
|
||||
uhash_setKeyDeleter(gGenderInfoCache, uprv_free);
|
||||
}
|
||||
|
||||
|
||||
GenderInfo::GenderInfo() {
|
||||
}
|
||||
|
||||
|
@ -64,34 +90,12 @@ GenderInfo::~GenderInfo() {
|
|||
}
|
||||
|
||||
const GenderInfo* GenderInfo::getInstance(const Locale& locale, UErrorCode& status) {
|
||||
// Make sure our cache exists.
|
||||
umtx_initOnce(gGenderInitOnce, &GenderInfo_initCache, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Make sure our cache exists.
|
||||
UBool needed;
|
||||
UMTX_CHECK(&gGenderMetaLock, (gGenderInfoCache == NULL), needed);
|
||||
if (needed) {
|
||||
Mutex lock(&gGenderMetaLock);
|
||||
if (gGenderInfoCache == NULL) {
|
||||
gObjs = new GenderInfo[GENDER_STYLE_LENGTH];
|
||||
if (gObjs == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
for (int i = 0; i < GENDER_STYLE_LENGTH; i++) {
|
||||
gObjs[i]._style = i;
|
||||
}
|
||||
gGenderInfoCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete [] gObjs;
|
||||
return NULL;
|
||||
}
|
||||
uhash_setKeyDeleter(gGenderInfoCache, uprv_free);
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_GENDERINFO, gender_cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
const GenderInfo* result = NULL;
|
||||
const char* key = locale.getName();
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1997-2012, International Business Machines Corporation and *
|
||||
* Copyright (C) 1997-2013, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -1264,11 +1264,14 @@ GregorianCalendar::getType() const {
|
|||
return "gregorian";
|
||||
}
|
||||
|
||||
const UDate GregorianCalendar::fgSystemDefaultCentury = DBL_MIN;
|
||||
const int32_t GregorianCalendar::fgSystemDefaultCenturyYear = -1;
|
||||
|
||||
UDate GregorianCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
|
||||
int32_t GregorianCalendar::fgSystemDefaultCenturyStartYear = -1;
|
||||
/**
|
||||
* The system maintains a static default century start date and Year. They are
|
||||
* initialized the first time they are used. Once the system default century date
|
||||
* and year are set, they do not change.
|
||||
*/
|
||||
static UDate gSystemDefaultCenturyStart = DBL_MIN;
|
||||
static int32_t gSystemDefaultCenturyStartYear = -1;
|
||||
static UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
|
||||
|
||||
|
||||
UBool GregorianCalendar::haveDefaultCentury() const
|
||||
|
@ -1276,78 +1279,36 @@ UBool GregorianCalendar::haveDefaultCentury() const
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
UDate GregorianCalendar::defaultCenturyStart() const
|
||||
{
|
||||
return internalGetDefaultCenturyStart();
|
||||
}
|
||||
|
||||
int32_t GregorianCalendar::defaultCenturyStartYear() const
|
||||
{
|
||||
return internalGetDefaultCenturyStartYear();
|
||||
}
|
||||
|
||||
UDate
|
||||
GregorianCalendar::internalGetDefaultCenturyStart() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (needsUpdate) {
|
||||
initializeSystemDefaultCentury();
|
||||
}
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStart
|
||||
|
||||
return fgSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t
|
||||
GregorianCalendar::internalGetDefaultCenturyStartYear() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStartYear
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (needsUpdate) {
|
||||
initializeSystemDefaultCentury();
|
||||
}
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStartYear
|
||||
|
||||
return fgSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
void
|
||||
GregorianCalendar::initializeSystemDefaultCentury()
|
||||
static void U_CALLCONV
|
||||
initializeSystemDefaultCentury()
|
||||
{
|
||||
// initialize systemDefaultCentury and systemDefaultCenturyYear based
|
||||
// on the current time. They'll be set to 80 years before
|
||||
// the current time.
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
Calendar *calendar = new GregorianCalendar(status);
|
||||
if (calendar != NULL && U_SUCCESS(status))
|
||||
{
|
||||
calendar->setTime(Calendar::getNow(), status);
|
||||
calendar->add(UCAL_YEAR, -80, status);
|
||||
GregorianCalendar calendar(status);
|
||||
if (U_SUCCESS(status)) {
|
||||
calendar.setTime(Calendar::getNow(), status);
|
||||
calendar.add(UCAL_YEAR, -80, status);
|
||||
|
||||
UDate newStart = calendar->getTime(status);
|
||||
int32_t newYear = calendar->get(UCAL_YEAR, status);
|
||||
umtx_lock(NULL);
|
||||
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
|
||||
{
|
||||
fgSystemDefaultCenturyStartYear = newYear;
|
||||
fgSystemDefaultCenturyStart = newStart;
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
delete calendar;
|
||||
gSystemDefaultCenturyStart = calendar.getTime(status);
|
||||
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
|
||||
}
|
||||
// We have no recourse upon failure unless we want to propagate the failure
|
||||
// out.
|
||||
}
|
||||
|
||||
UDate GregorianCalendar::defaultCenturyStart() const {
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t GregorianCalendar::defaultCenturyStartYear() const {
|
||||
// lazy-evaluate systemDefaultCenturyStartYear
|
||||
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 2003-2011, International Business Machines Corporation
|
||||
* Copyright (C) 2003-2013, International Business Machines Corporation
|
||||
* and others. All Rights Reserved.
|
||||
******************************************************************************
|
||||
*
|
||||
|
@ -668,88 +668,52 @@ HebrewCalendar::inDaylightTime(UErrorCode& status) const
|
|||
return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE);
|
||||
}
|
||||
|
||||
// default century
|
||||
const UDate HebrewCalendar::fgSystemDefaultCentury = DBL_MIN;
|
||||
const int32_t HebrewCalendar::fgSystemDefaultCenturyYear = -1;
|
||||
|
||||
UDate HebrewCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
|
||||
int32_t HebrewCalendar::fgSystemDefaultCenturyStartYear = -1;
|
||||
|
||||
/**
|
||||
* The system maintains a static default century start date and Year. They are
|
||||
* initialized the first time they are used. Once the system default century date
|
||||
* and year are set, they do not change.
|
||||
*/
|
||||
static UDate gSystemDefaultCenturyStart = DBL_MIN;
|
||||
static int32_t gSystemDefaultCenturyStartYear = -1;
|
||||
static UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
|
||||
|
||||
UBool HebrewCalendar::haveDefaultCentury() const
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UDate HebrewCalendar::defaultCenturyStart() const
|
||||
{
|
||||
return internalGetDefaultCenturyStart();
|
||||
}
|
||||
|
||||
int32_t HebrewCalendar::defaultCenturyStartYear() const
|
||||
{
|
||||
return internalGetDefaultCenturyStartYear();
|
||||
}
|
||||
|
||||
UDate
|
||||
HebrewCalendar::internalGetDefaultCenturyStart() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (needsUpdate) {
|
||||
initializeSystemDefaultCentury();
|
||||
}
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStart
|
||||
|
||||
return fgSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t
|
||||
HebrewCalendar::internalGetDefaultCenturyStartYear() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStartYear
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (needsUpdate) {
|
||||
initializeSystemDefaultCentury();
|
||||
}
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStartYear
|
||||
|
||||
return fgSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
void
|
||||
HebrewCalendar::initializeSystemDefaultCentury()
|
||||
static void U_CALLCONV initializeSystemDefaultCentury()
|
||||
{
|
||||
// initialize systemDefaultCentury and systemDefaultCenturyYear based
|
||||
// on the current time. They'll be set to 80 years before
|
||||
// the current time.
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
HebrewCalendar calendar(Locale("@calendar=hebrew"),status);
|
||||
if (U_SUCCESS(status))
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
calendar.setTime(Calendar::getNow(), status);
|
||||
calendar.add(UCAL_YEAR, -80, status);
|
||||
UDate newStart = calendar.getTime(status);
|
||||
int32_t newYear = calendar.get(UCAL_YEAR, status);
|
||||
umtx_lock(NULL);
|
||||
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury) {
|
||||
fgSystemDefaultCenturyStartYear = newYear;
|
||||
fgSystemDefaultCenturyStart = newStart;
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
|
||||
gSystemDefaultCenturyStart = calendar.getTime(status);
|
||||
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
|
||||
}
|
||||
// We have no recourse upon failure unless we want to propagate the failure
|
||||
// out.
|
||||
}
|
||||
|
||||
|
||||
UDate HebrewCalendar::defaultCenturyStart() const {
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t HebrewCalendar::defaultCenturyStartYear() const {
|
||||
// lazy-evaluate systemDefaultCenturyStartYear
|
||||
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(HebrewCalendar)
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 2003-2009, International Business Machines Corporation
|
||||
* Copyright (C) 2003-2013, International Business Machines Corporation
|
||||
* and others. All Rights Reserved.
|
||||
******************************************************************************
|
||||
*
|
||||
|
@ -395,49 +395,6 @@ public:
|
|||
*/
|
||||
virtual int32_t defaultCenturyStartYear() const;
|
||||
|
||||
private: // default century stuff.
|
||||
/**
|
||||
* The system maintains a static default century start date. This is initialized
|
||||
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
|
||||
* indicate an uninitialized state. Once the system default century date and year
|
||||
* are set, they do not change.
|
||||
*/
|
||||
static UDate fgSystemDefaultCenturyStart;
|
||||
|
||||
/**
|
||||
* See documentation for systemDefaultCenturyStart.
|
||||
*/
|
||||
static int32_t fgSystemDefaultCenturyStartYear;
|
||||
|
||||
/**
|
||||
* Default value that indicates the defaultCenturyStartYear is unitialized
|
||||
*/
|
||||
static const int32_t fgSystemDefaultCenturyYear;
|
||||
|
||||
/**
|
||||
* start of default century, as a date
|
||||
*/
|
||||
static const UDate fgSystemDefaultCentury;
|
||||
|
||||
/**
|
||||
* Returns the beginning date of the 100-year window that dates
|
||||
* with 2-digit years are considered to fall within.
|
||||
*/
|
||||
UDate internalGetDefaultCenturyStart(void) const;
|
||||
|
||||
/**
|
||||
* Returns the first year of the 100-year window that dates with
|
||||
* 2-digit years are considered to fall within.
|
||||
*/
|
||||
int32_t internalGetDefaultCenturyStartYear(void) const;
|
||||
|
||||
/**
|
||||
* Initializes the 100-year window that dates with 2-digit years
|
||||
* are considered to fall within so that its start date is 80 years
|
||||
* before the current time.
|
||||
*/
|
||||
static void initializeSystemDefaultCentury(void);
|
||||
|
||||
private: // Calendar-specific implementation
|
||||
/**
|
||||
* Finds the day # of the first day in the given Hebrew year.
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<DisableLanguageExtensions>true</DisableLanguageExtensions>
|
||||
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<PrecompiledHeaderOutputFile>.\x86\Release/i18n.pch</PrecompiledHeaderOutputFile>
|
||||
<AssemblerListingLocation>.\x86\Release/</AssemblerListingLocation>
|
||||
|
@ -133,7 +133,7 @@
|
|||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<DisableLanguageExtensions>true</DisableLanguageExtensions>
|
||||
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<PrecompiledHeaderOutputFile>.\x86\Debug/i18n.pch</PrecompiledHeaderOutputFile>
|
||||
<AssemblerListingLocation>.\x86\Debug/</AssemblerListingLocation>
|
||||
|
@ -176,7 +176,7 @@
|
|||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<DisableLanguageExtensions>true</DisableLanguageExtensions>
|
||||
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<PrecompiledHeaderOutputFile>.\x64\Release/i18n.pch</PrecompiledHeaderOutputFile>
|
||||
<AssemblerListingLocation>.\x64\Release/</AssemblerListingLocation>
|
||||
|
@ -216,7 +216,7 @@
|
|||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<DisableLanguageExtensions>true</DisableLanguageExtensions>
|
||||
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
||||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<PrecompiledHeaderOutputFile>.\x64\Debug/i18n.pch</PrecompiledHeaderOutputFile>
|
||||
<AssemblerListingLocation>.\x64\Debug/</AssemblerListingLocation>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 2003-2012, International Business Machines Corporation
|
||||
* Copyright (C) 2003-2013, International Business Machines Corporation
|
||||
* and others. All Rights Reserved.
|
||||
******************************************************************************
|
||||
*
|
||||
|
@ -457,89 +457,51 @@ IslamicCalendar::inDaylightTime(UErrorCode& status) const
|
|||
return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE);
|
||||
}
|
||||
|
||||
// default century
|
||||
const UDate IslamicCalendar::fgSystemDefaultCentury = DBL_MIN;
|
||||
const int32_t IslamicCalendar::fgSystemDefaultCenturyYear = -1;
|
||||
|
||||
UDate IslamicCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
|
||||
int32_t IslamicCalendar::fgSystemDefaultCenturyStartYear = -1;
|
||||
|
||||
/**
|
||||
* The system maintains a static default century start date and Year. They are
|
||||
* initialized the first time they are used. Once the system default century date
|
||||
* and year are set, they do not change.
|
||||
*/
|
||||
static UDate gSystemDefaultCenturyStart = DBL_MIN;
|
||||
static int32_t gSystemDefaultCenturyStartYear = -1;
|
||||
static UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
|
||||
|
||||
UBool IslamicCalendar::haveDefaultCentury() const
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UDate IslamicCalendar::defaultCenturyStart() const
|
||||
{
|
||||
return internalGetDefaultCenturyStart();
|
||||
}
|
||||
|
||||
int32_t IslamicCalendar::defaultCenturyStartYear() const
|
||||
{
|
||||
return internalGetDefaultCenturyStartYear();
|
||||
}
|
||||
|
||||
UDate
|
||||
IslamicCalendar::internalGetDefaultCenturyStart() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (needsUpdate) {
|
||||
initializeSystemDefaultCentury();
|
||||
}
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStart
|
||||
|
||||
return fgSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t
|
||||
IslamicCalendar::internalGetDefaultCenturyStartYear() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStartYear
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (needsUpdate) {
|
||||
initializeSystemDefaultCentury();
|
||||
}
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStartYear
|
||||
|
||||
return fgSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
void
|
||||
IslamicCalendar::initializeSystemDefaultCentury()
|
||||
static void U_CALLCONV initializeSystemDefaultCentury()
|
||||
{
|
||||
// initialize systemDefaultCentury and systemDefaultCenturyYear based
|
||||
// on the current time. They'll be set to 80 years before
|
||||
// the current time.
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
IslamicCalendar calendar(Locale("@calendar=islamic-civil"),status);
|
||||
if (U_SUCCESS(status))
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
calendar.setTime(Calendar::getNow(), status);
|
||||
calendar.add(UCAL_YEAR, -80, status);
|
||||
UDate newStart = calendar.getTime(status);
|
||||
int32_t newYear = calendar.get(UCAL_YEAR, status);
|
||||
umtx_lock(NULL);
|
||||
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
|
||||
{
|
||||
fgSystemDefaultCenturyStartYear = newYear;
|
||||
fgSystemDefaultCenturyStart = newStart;
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
|
||||
gSystemDefaultCenturyStart = calendar.getTime(status);
|
||||
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
|
||||
}
|
||||
// We have no recourse upon failure unless we want to propagate the failure
|
||||
// out.
|
||||
}
|
||||
|
||||
UDate IslamicCalendar::defaultCenturyStart() const {
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t IslamicCalendar::defaultCenturyStartYear() const {
|
||||
// lazy-evaluate systemDefaultCenturyStartYear
|
||||
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicCalendar)
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
********************************************************************************
|
||||
* Copyright (C) 2003-2009, International Business Machines Corporation
|
||||
* Copyright (C) 2003-2013, International Business Machines Corporation
|
||||
* and others. All Rights Reserved.
|
||||
******************************************************************************
|
||||
*
|
||||
|
@ -409,49 +409,6 @@ class IslamicCalendar : public Calendar {
|
|||
* @internal
|
||||
*/
|
||||
virtual int32_t defaultCenturyStartYear() const;
|
||||
|
||||
private: // default century stuff.
|
||||
/**
|
||||
* The system maintains a static default century start date. This is initialized
|
||||
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
|
||||
* indicate an uninitialized state. Once the system default century date and year
|
||||
* are set, they do not change.
|
||||
*/
|
||||
static UDate fgSystemDefaultCenturyStart;
|
||||
|
||||
/**
|
||||
* See documentation for systemDefaultCenturyStart.
|
||||
*/
|
||||
static int32_t fgSystemDefaultCenturyStartYear;
|
||||
|
||||
/**
|
||||
* Default value that indicates the defaultCenturyStartYear is unitialized
|
||||
*/
|
||||
static const int32_t fgSystemDefaultCenturyYear;
|
||||
|
||||
/**
|
||||
* start of default century, as a date
|
||||
*/
|
||||
static const UDate fgSystemDefaultCentury;
|
||||
|
||||
/**
|
||||
* Returns the beginning date of the 100-year window that dates
|
||||
* with 2-digit years are considered to fall within.
|
||||
*/
|
||||
UDate internalGetDefaultCenturyStart(void) const;
|
||||
|
||||
/**
|
||||
* Returns the first year of the 100-year window that dates with
|
||||
* 2-digit years are considered to fall within.
|
||||
*/
|
||||
int32_t internalGetDefaultCenturyStartYear(void) const;
|
||||
|
||||
/**
|
||||
* Initializes the 100-year window that dates with 2-digit years
|
||||
* are considered to fall within so that its start date is 80 years
|
||||
* before the current time.
|
||||
*/
|
||||
static void initializeSystemDefaultCentury(void);
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1997-2012, International Business Machines Corporation and *
|
||||
* Copyright (C) 1997-2013, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -45,6 +45,7 @@
|
|||
#include "ucln_in.h"
|
||||
#include "cstring.h"
|
||||
#include "putilimp.h"
|
||||
#include "uassert.h"
|
||||
#include "umutex.h"
|
||||
#include "mutex.h"
|
||||
#include "digitlst.h"
|
||||
|
@ -138,11 +139,12 @@ static const char *gFormatKeys[UNUM_FORMAT_STYLE_COUNT] = {
|
|||
|
||||
// Static hashtable cache of NumberingSystem objects used by NumberFormat
|
||||
static UHashtable * NumberingSystem_cache = NULL;
|
||||
|
||||
static UMutex nscacheMutex = U_MUTEX_INITIALIZER;
|
||||
static UInitOnce gNSCacheInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
#if !UCONFIG_NO_SERVICE
|
||||
static icu::ICULocaleService* gService = NULL;
|
||||
static UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER;
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -156,11 +158,13 @@ deleteNumberingSystem(void *obj) {
|
|||
|
||||
static UBool U_CALLCONV numfmt_cleanup(void) {
|
||||
#if !UCONFIG_NO_SERVICE
|
||||
gServiceInitOnce.reset();
|
||||
if (gService) {
|
||||
delete gService;
|
||||
gService = NULL;
|
||||
}
|
||||
#endif
|
||||
gNSCacheInitOnce.reset();
|
||||
if (NumberingSystem_cache) {
|
||||
// delete NumberingSystem_cache;
|
||||
uhash_close(NumberingSystem_cache);
|
||||
|
@ -902,31 +906,23 @@ ICUNumberFormatService::~ICUNumberFormatService() {}
|
|||
|
||||
// -------------------------------------
|
||||
|
||||
static void U_CALLCONV initNumberFormatService() {
|
||||
U_ASSERT(gService == NULL);
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
|
||||
gService = new ICUNumberFormatService();
|
||||
}
|
||||
|
||||
static ICULocaleService*
|
||||
getNumberFormatService(void)
|
||||
{
|
||||
UBool needInit;
|
||||
UMTX_CHECK(NULL, (UBool)(gService == NULL), needInit);
|
||||
if (needInit) {
|
||||
ICULocaleService * newservice = new ICUNumberFormatService();
|
||||
if (newservice) {
|
||||
umtx_lock(NULL);
|
||||
if (gService == NULL) {
|
||||
gService = newservice;
|
||||
newservice = NULL;
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
}
|
||||
if (newservice) {
|
||||
delete newservice;
|
||||
} else {
|
||||
// we won the contention, this thread can register cleanup.
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
|
||||
}
|
||||
}
|
||||
umtx_initOnce(gServiceInitOnce, &initNumberFormatService);
|
||||
return gService;
|
||||
}
|
||||
|
||||
static UBool haveService() {
|
||||
return !gServiceInitOnce.isReset() && (getNumberFormatService() != NULL);
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
URegistryKey U_EXPORT2
|
||||
|
@ -948,15 +944,15 @@ NumberFormat::registerFactory(NumberFormatFactory* toAdopt, UErrorCode& status)
|
|||
UBool U_EXPORT2
|
||||
NumberFormat::unregister(URegistryKey key, UErrorCode& status)
|
||||
{
|
||||
if (U_SUCCESS(status)) {
|
||||
UBool haveService;
|
||||
UMTX_CHECK(NULL, gService != NULL, haveService);
|
||||
if (haveService) {
|
||||
return gService->unregister(key, status);
|
||||
}
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
if (U_FAILURE(status)) {
|
||||
return FALSE;
|
||||
}
|
||||
if (haveService()) {
|
||||
return gService->unregister(key, status);
|
||||
} else {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -965,7 +961,7 @@ NumberFormat::getAvailableLocales(void)
|
|||
{
|
||||
ICULocaleService *service = getNumberFormatService();
|
||||
if (service) {
|
||||
return service->getAvailableLocales();
|
||||
return service->getAvailableLocales();
|
||||
}
|
||||
return NULL; // no way to return error condition
|
||||
}
|
||||
|
@ -973,19 +969,13 @@ NumberFormat::getAvailableLocales(void)
|
|||
// -------------------------------------
|
||||
|
||||
NumberFormat* U_EXPORT2
|
||||
NumberFormat::createInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status)
|
||||
{
|
||||
NumberFormat::createInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) {
|
||||
#if !UCONFIG_NO_SERVICE
|
||||
UBool haveService;
|
||||
UMTX_CHECK(NULL, gService != NULL, haveService);
|
||||
if (haveService) {
|
||||
if (haveService()) {
|
||||
return (NumberFormat*)gService->get(loc, kind, status);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
return makeInstance(loc, kind, status);
|
||||
}
|
||||
return makeInstance(loc, kind, status);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1132,6 +1122,22 @@ void NumberFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
|
|||
// Creates the NumberFormat instance of the specified style (number, currency,
|
||||
// or percent) for the desired locale.
|
||||
|
||||
static void U_CALLCONV nscacheInit() {
|
||||
U_ASSERT(NumberingSystem_cache == NULL);
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
NumberingSystem_cache = uhash_open(uhash_hashLong,
|
||||
uhash_compareLong,
|
||||
NULL,
|
||||
&status);
|
||||
if (U_FAILURE(status)) {
|
||||
// Number Format code will run with no cache if creation fails.
|
||||
NumberingSystem_cache = NULL;
|
||||
return;
|
||||
}
|
||||
uhash_setValueDeleter(NumberingSystem_cache, deleteNumberingSystem);
|
||||
}
|
||||
|
||||
UBool
|
||||
NumberFormat::isStyleSupported(UNumberFormatStyle style) {
|
||||
return gLastResortNumberPatterns[style] != NULL;
|
||||
|
@ -1200,48 +1206,20 @@ NumberFormat::makeInstance(const Locale& desiredLocale,
|
|||
}
|
||||
#endif
|
||||
// Use numbering system cache hashtable
|
||||
UHashtable *cache;
|
||||
UMTX_CHECK(&nscacheMutex, NumberingSystem_cache, cache);
|
||||
|
||||
// Check cache we got, create if non-existant
|
||||
if (cache == NULL) {
|
||||
cache = uhash_open(uhash_hashLong,
|
||||
uhash_compareLong,
|
||||
NULL,
|
||||
&status);
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
// cache not created - out of memory
|
||||
status = U_ZERO_ERROR; // work without the cache
|
||||
cache = NULL;
|
||||
} else {
|
||||
// cache created
|
||||
uhash_setValueDeleter(cache, deleteNumberingSystem);
|
||||
|
||||
// set final NumberingSystem_cache value
|
||||
Mutex lock(&nscacheMutex);
|
||||
if (NumberingSystem_cache == NULL) {
|
||||
NumberingSystem_cache = cache;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
|
||||
} else {
|
||||
uhash_close(cache);
|
||||
cache = NumberingSystem_cache;
|
||||
}
|
||||
}
|
||||
}
|
||||
umtx_initOnce(gNSCacheInitOnce, &nscacheInit);
|
||||
|
||||
// Get cached numbering system
|
||||
LocalPointer<NumberingSystem> ownedNs;
|
||||
NumberingSystem *ns = NULL;
|
||||
if (cache != NULL) {
|
||||
if (NumberingSystem_cache != NULL) {
|
||||
// TODO: Bad hash key usage, see ticket #8504.
|
||||
int32_t hashKey = desiredLocale.hashCode();
|
||||
|
||||
Mutex lock(&nscacheMutex);
|
||||
ns = (NumberingSystem *)uhash_iget(cache, hashKey);
|
||||
ns = (NumberingSystem *)uhash_iget(NumberingSystem_cache, hashKey);
|
||||
if (ns == NULL) {
|
||||
ns = NumberingSystem::createInstance(desiredLocale,status);
|
||||
uhash_iput(cache, hashKey, (void*)ns, &status);
|
||||
uhash_iput(NumberingSystem_cache, hashKey, (void*)ns, &status);
|
||||
}
|
||||
} else {
|
||||
ownedNs.adoptInstead(NumberingSystem::createInstance(desiredLocale,status));
|
||||
|
|
|
@ -119,7 +119,7 @@ OlsonTimeZone::OlsonTimeZone(const UResourceBundle* top,
|
|||
const UResourceBundle* res,
|
||||
const UnicodeString& tzid,
|
||||
UErrorCode& ec) :
|
||||
BasicTimeZone(tzid), finalZone(NULL), transitionRulesInitialized(FALSE)
|
||||
BasicTimeZone(tzid), finalZone(NULL)
|
||||
{
|
||||
clearTransitionRules();
|
||||
U_DEBUG_TZ_MSG(("OlsonTimeZone(%s)\n", ures_getKey((UResourceBundle*)res)));
|
||||
|
@ -658,7 +658,7 @@ OlsonTimeZone::clearTransitionRules(void) {
|
|||
historicRuleCount = 0;
|
||||
finalZoneWithStartYear = NULL;
|
||||
firstTZTransitionIdx = 0;
|
||||
transitionRulesInitialized = FALSE;
|
||||
transitionRulesInitOnce.reset();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -689,23 +689,15 @@ OlsonTimeZone::deleteTransitionRules(void) {
|
|||
/*
|
||||
* Lazy transition rules initializer
|
||||
*/
|
||||
static UMutex gLock = U_MUTEX_INITIALIZER;
|
||||
|
||||
static void U_CALLCONV initRules(OlsonTimeZone *This, UErrorCode &status) {
|
||||
This->initTransitionRules(status);
|
||||
}
|
||||
|
||||
void
|
||||
OlsonTimeZone::checkTransitionRules(UErrorCode& status) const {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&gLock, transitionRulesInitialized, initialized);
|
||||
if (!initialized) {
|
||||
umtx_lock(&gLock);
|
||||
if (!transitionRulesInitialized) {
|
||||
OlsonTimeZone *ncThis = const_cast<OlsonTimeZone*>(this);
|
||||
ncThis->initTransitionRules(status);
|
||||
}
|
||||
umtx_unlock(&gLock);
|
||||
}
|
||||
OlsonTimeZone *ncThis = const_cast<OlsonTimeZone *>(this);
|
||||
umtx_initOnce(ncThis->transitionRulesInitOnce, &initRules, ncThis, status);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -713,9 +705,6 @@ OlsonTimeZone::initTransitionRules(UErrorCode& status) {
|
|||
if(U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
if (transitionRulesInitialized) {
|
||||
return;
|
||||
}
|
||||
deleteTransitionRules();
|
||||
UnicodeString tzid;
|
||||
getID(tzid);
|
||||
|
@ -884,7 +873,6 @@ OlsonTimeZone::initTransitionRules(UErrorCode& status) {
|
|||
firstFinalTZTransition->adoptFrom(prevRule->clone());
|
||||
firstFinalTZTransition->adoptTo(firstFinalRule);
|
||||
}
|
||||
transitionRulesInitialized = TRUE;
|
||||
}
|
||||
|
||||
UBool
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/basictz.h"
|
||||
#include "umutex.h"
|
||||
|
||||
struct UResourceBundle;
|
||||
|
||||
|
@ -383,7 +384,10 @@ private:
|
|||
void clearTransitionRules(void);
|
||||
void deleteTransitionRules(void);
|
||||
void checkTransitionRules(UErrorCode& status) const;
|
||||
|
||||
public: // Internal, for access from plain C code
|
||||
void initTransitionRules(UErrorCode& status);
|
||||
private:
|
||||
|
||||
InitialTimeZoneRule *initialRule;
|
||||
TimeZoneTransition *firstTZTransition;
|
||||
|
@ -392,7 +396,7 @@ private:
|
|||
TimeArrayTimeZoneRule **historicRules;
|
||||
int16_t historicRuleCount;
|
||||
SimpleTimeZone *finalZoneWithStartYear; // hack
|
||||
UBool transitionRulesInitialized;
|
||||
UInitOnce transitionRulesInitOnce;
|
||||
};
|
||||
|
||||
inline int16_t
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 2003-2012, International Business Machines Corporation
|
||||
* Copyright (C) 2003-2013, International Business Machines Corporation
|
||||
* and others. All Rights Reserved.
|
||||
******************************************************************************
|
||||
*
|
||||
|
@ -245,64 +245,17 @@ PersianCalendar::inDaylightTime(UErrorCode& status) const
|
|||
}
|
||||
|
||||
// default century
|
||||
const UDate PersianCalendar::fgSystemDefaultCentury = DBL_MIN;
|
||||
const int32_t PersianCalendar::fgSystemDefaultCenturyYear = -1;
|
||||
|
||||
UDate PersianCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
|
||||
int32_t PersianCalendar::fgSystemDefaultCenturyStartYear = -1;
|
||||
static UDate gSystemDefaultCenturyStart = DBL_MIN;
|
||||
static int32_t gSystemDefaultCenturyStartYear = -1;
|
||||
static UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
|
||||
|
||||
UBool PersianCalendar::haveDefaultCentury() const
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UDate PersianCalendar::defaultCenturyStart() const
|
||||
{
|
||||
return internalGetDefaultCenturyStart();
|
||||
}
|
||||
|
||||
int32_t PersianCalendar::defaultCenturyStartYear() const
|
||||
{
|
||||
return internalGetDefaultCenturyStartYear();
|
||||
}
|
||||
|
||||
UDate
|
||||
PersianCalendar::internalGetDefaultCenturyStart() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (needsUpdate) {
|
||||
initializeSystemDefaultCentury();
|
||||
}
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStart
|
||||
|
||||
return fgSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t
|
||||
PersianCalendar::internalGetDefaultCenturyStartYear() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStartYear
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (needsUpdate) {
|
||||
initializeSystemDefaultCentury();
|
||||
}
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStartYear
|
||||
|
||||
return fgSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
void
|
||||
PersianCalendar::initializeSystemDefaultCentury()
|
||||
{
|
||||
static void U_CALLCONV initializeSystemDefaultCentury() {
|
||||
// initialize systemDefaultCentury and systemDefaultCenturyYear based
|
||||
// on the current time. They'll be set to 80 years before
|
||||
// the current time.
|
||||
|
@ -312,20 +265,26 @@ PersianCalendar::initializeSystemDefaultCentury()
|
|||
{
|
||||
calendar.setTime(Calendar::getNow(), status);
|
||||
calendar.add(UCAL_YEAR, -80, status);
|
||||
UDate newStart = calendar.getTime(status);
|
||||
int32_t newYear = calendar.get(UCAL_YEAR, status);
|
||||
umtx_lock(NULL);
|
||||
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
|
||||
{
|
||||
fgSystemDefaultCenturyStartYear = newYear;
|
||||
fgSystemDefaultCenturyStart = newStart;
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
|
||||
gSystemDefaultCenturyStart = calendar.getTime(status);
|
||||
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
|
||||
}
|
||||
// We have no recourse upon failure unless we want to propagate the failure
|
||||
// out.
|
||||
}
|
||||
|
||||
UDate PersianCalendar::defaultCenturyStart() const {
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t PersianCalendar::defaultCenturyStartYear() const {
|
||||
// lazy-evaluate systemDefaultCenturyStartYear
|
||||
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(PersianCalendar)
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
* Copyright (C) 2003-2008, International Business Machines Corporation
|
||||
* Copyright (C) 2003-2013, International Business Machines Corporation
|
||||
* and others. All Rights Reserved.
|
||||
******************************************************************************
|
||||
*
|
||||
|
@ -310,49 +310,6 @@ class PersianCalendar : public Calendar {
|
|||
* @internal
|
||||
*/
|
||||
virtual int32_t defaultCenturyStartYear() const;
|
||||
|
||||
private: // default century stuff.
|
||||
/**
|
||||
* The system maintains a static default century start date. This is initialized
|
||||
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
|
||||
* indicate an uninitialized state. Once the system default century date and year
|
||||
* are set, they do not change.
|
||||
*/
|
||||
static UDate fgSystemDefaultCenturyStart;
|
||||
|
||||
/**
|
||||
* See documentation for systemDefaultCenturyStart.
|
||||
*/
|
||||
static int32_t fgSystemDefaultCenturyStartYear;
|
||||
|
||||
/**
|
||||
* Default value that indicates the defaultCenturyStartYear is unitialized
|
||||
*/
|
||||
static const int32_t fgSystemDefaultCenturyYear;
|
||||
|
||||
/**
|
||||
* start of default century, as a date
|
||||
*/
|
||||
static const UDate fgSystemDefaultCentury;
|
||||
|
||||
/**
|
||||
* Returns the beginning date of the 100-year window that dates
|
||||
* with 2-digit years are considered to fall within.
|
||||
*/
|
||||
UDate internalGetDefaultCenturyStart(void) const;
|
||||
|
||||
/**
|
||||
* Returns the first year of the 100-year window that dates with
|
||||
* 2-digit years are considered to fall within.
|
||||
*/
|
||||
int32_t internalGetDefaultCenturyStartYear(void) const;
|
||||
|
||||
/**
|
||||
* Initializes the 100-year window that dates with 2-digit years
|
||||
* are considered to fall within so that its start date is 80 years
|
||||
* before the current time.
|
||||
*/
|
||||
static void initializeSystemDefaultCentury(void);
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
**********************************************************************
|
||||
* Copyright (C) 1999-2012, International Business Machines
|
||||
* Copyright (C) 1999-2013, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
**********************************************************************
|
||||
* Date Name Description
|
||||
|
@ -248,8 +248,11 @@ RuleBasedTransliterator::handleTransliterate(Replaceable& text, UTransPosition&
|
|||
// some other transliteration that is still in progress and holding the
|
||||
// transliteration mutex. If so, do not lock the transliteration
|
||||
// mutex again.
|
||||
// TODO(andy): Need a better scheme for handling this.
|
||||
UBool needToLock;
|
||||
UMTX_CHECK(NULL, (&text != gLockedText), needToLock);
|
||||
umtx_lock(NULL);
|
||||
needToLock = (&text != gLockedText);
|
||||
umtx_unlock(NULL);
|
||||
if (needToLock) {
|
||||
umtx_lock(&transliteratorDataMutex);
|
||||
gLockedText = &text;
|
||||
|
|
|
@ -151,16 +151,12 @@ RuleBasedTimeZone::completeConst(UErrorCode& status) const {
|
|||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
UBool updated;
|
||||
UMTX_CHECK(&gLock, fUpToDate, updated);
|
||||
if (!updated) {
|
||||
umtx_lock(&gLock);
|
||||
if (!fUpToDate) {
|
||||
RuleBasedTimeZone *ncThis = const_cast<RuleBasedTimeZone*>(this);
|
||||
ncThis->complete(status);
|
||||
}
|
||||
umtx_unlock(&gLock);
|
||||
umtx_lock(&gLock);
|
||||
if (!fUpToDate) {
|
||||
RuleBasedTimeZone *ncThis = const_cast<RuleBasedTimeZone*>(this);
|
||||
ncThis->complete(status);
|
||||
}
|
||||
umtx_unlock(&gLock);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// regexst.h
|
||||
//
|
||||
// Copyright (C) 2004-2012, International Business Machines Corporation and others.
|
||||
// Copyright (C) 2004-2013, International Business Machines Corporation and others.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// This file contains class RegexStaticSets
|
||||
|
@ -144,6 +144,7 @@ static const UChar gGC_LVTPattern[] = {
|
|||
|
||||
|
||||
RegexStaticSets *RegexStaticSets::gStaticSets = NULL;
|
||||
UInitOnce gStaticSetsInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
RegexStaticSets::RegexStaticSets(UErrorCode *status)
|
||||
:
|
||||
|
@ -255,6 +256,7 @@ UBool
|
|||
RegexStaticSets::cleanup(void) {
|
||||
delete RegexStaticSets::gStaticSets;
|
||||
RegexStaticSets::gStaticSets = NULL;
|
||||
gStaticSetsInitOnce.reset();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -263,34 +265,24 @@ static UBool U_CALLCONV
|
|||
regex_cleanup(void) {
|
||||
return RegexStaticSets::cleanup();
|
||||
}
|
||||
|
||||
static void U_CALLCONV initStaticSets(UErrorCode &status) {
|
||||
U_ASSERT(RegexStaticSets::gStaticSets == NULL);
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_REGEX, regex_cleanup);
|
||||
RegexStaticSets::gStaticSets = new RegexStaticSets(&status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete RegexStaticSets::gStaticSets;
|
||||
RegexStaticSets::gStaticSets = NULL;
|
||||
}
|
||||
if (RegexStaticSets::gStaticSets == NULL && U_SUCCESS(status)) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
}
|
||||
U_CDECL_END
|
||||
|
||||
void RegexStaticSets::initGlobals(UErrorCode *status) {
|
||||
RegexStaticSets *p;
|
||||
UMTX_CHECK(NULL, gStaticSets, p);
|
||||
if (p == NULL) {
|
||||
p = new RegexStaticSets(status);
|
||||
if (p == NULL) {
|
||||
*status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
if (U_FAILURE(*status)) {
|
||||
delete p;
|
||||
return;
|
||||
}
|
||||
umtx_lock(NULL);
|
||||
if (gStaticSets == NULL) {
|
||||
gStaticSets = p;
|
||||
p = NULL;
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
if (p) {
|
||||
delete p;
|
||||
}
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_REGEX, regex_cleanup);
|
||||
}
|
||||
umtx_initOnce(gStaticSetsInitOnce, &initStaticSets, *status);
|
||||
}
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif // !UCONFIG_NO_REGULAR_EXPRESSIONS
|
||||
|
|
|
@ -1063,6 +1063,17 @@ SimpleTimeZone::deleteTransitionRules(void) {
|
|||
|
||||
/*
|
||||
* Lazy transition rules initializer
|
||||
*
|
||||
* Note On the removal of UMTX_CHECK from checkTransitionRules():
|
||||
*
|
||||
* It would be faster to have a UInitOnce as part of a SimpleTimeZone object,
|
||||
* which would avoid needing to lock a mutex to check the initialization state.
|
||||
* But we can't easily because simpletz.h is a public header, and including
|
||||
* a UInitOnce as a member of SimpleTimeZone would publicly expose internal ICU headers.
|
||||
*
|
||||
* Alternatively we could have a pointer to a UInitOnce in the SimpleTimeZone object,
|
||||
* allocate it in the constructors. This would be a more intrusive change, but doable
|
||||
* if performance turns out to be an issue.
|
||||
*/
|
||||
static UMutex gLock = U_MUTEX_INITIALIZER;
|
||||
|
||||
|
@ -1071,16 +1082,12 @@ SimpleTimeZone::checkTransitionRules(UErrorCode& status) const {
|
|||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&gLock, transitionRulesInitialized, initialized);
|
||||
if (!initialized) {
|
||||
umtx_lock(&gLock);
|
||||
if (!transitionRulesInitialized) {
|
||||
SimpleTimeZone *ncThis = const_cast<SimpleTimeZone*>(this);
|
||||
ncThis->initTransitionRules(status);
|
||||
}
|
||||
umtx_unlock(&gLock);
|
||||
umtx_lock(&gLock);
|
||||
if (!transitionRulesInitialized) {
|
||||
SimpleTimeZone *ncThis = const_cast<SimpleTimeZone*>(this);
|
||||
ncThis->initTransitionRules(status);
|
||||
}
|
||||
umtx_unlock(&gLock);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2011, International Business Machines Corporation and *
|
||||
* Copyright (C) 2009-2013, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -18,6 +18,7 @@
|
|||
#include "unicode/uniset.h"
|
||||
#include "unicode/udat.h"
|
||||
#include "cmemory.h"
|
||||
#include "uassert.h"
|
||||
#include "ucln_in.h"
|
||||
#include "umutex.h"
|
||||
|
||||
|
@ -26,16 +27,17 @@
|
|||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
SimpleDateFormatStaticSets *SimpleDateFormatStaticSets::gStaticSets = NULL;
|
||||
SimpleDateFormatStaticSets *gStaticSets = NULL;
|
||||
UInitOnce gSimpleDateFormatStaticSetsInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
SimpleDateFormatStaticSets::SimpleDateFormatStaticSets(UErrorCode *status)
|
||||
SimpleDateFormatStaticSets::SimpleDateFormatStaticSets(UErrorCode &status)
|
||||
: fDateIgnorables(NULL),
|
||||
fTimeIgnorables(NULL),
|
||||
fOtherIgnorables(NULL)
|
||||
{
|
||||
fDateIgnorables = new UnicodeSet(UNICODE_STRING("[-,./[:whitespace:]]", 20), *status);
|
||||
fTimeIgnorables = new UnicodeSet(UNICODE_STRING("[-.:[:whitespace:]]", 19), *status);
|
||||
fOtherIgnorables = new UnicodeSet(UNICODE_STRING("[:whitespace:]", 14), *status);
|
||||
fDateIgnorables = new UnicodeSet(UNICODE_STRING("[-,./[:whitespace:]]", 20), status);
|
||||
fTimeIgnorables = new UnicodeSet(UNICODE_STRING("[-.:[:whitespace:]]", 19), status);
|
||||
fOtherIgnorables = new UnicodeSet(UNICODE_STRING("[:whitespace:]", 14), status);
|
||||
|
||||
// Check for null pointers
|
||||
if (fDateIgnorables == NULL || fTimeIgnorables == NULL || fOtherIgnorables == NULL) {
|
||||
|
@ -54,7 +56,7 @@ ExitConstrDeleteAll: // Remove all sets and return error
|
|||
delete fTimeIgnorables; fTimeIgnorables = NULL;
|
||||
delete fOtherIgnorables; fOtherIgnorables = NULL;
|
||||
|
||||
*status = U_MEMORY_ALLOCATION_ERROR;
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
@ -74,9 +76,9 @@ SimpleDateFormatStaticSets::~SimpleDateFormatStaticSets() {
|
|||
UBool
|
||||
SimpleDateFormatStaticSets::cleanup(void)
|
||||
{
|
||||
delete SimpleDateFormatStaticSets::gStaticSets;
|
||||
SimpleDateFormatStaticSets::gStaticSets = NULL;
|
||||
|
||||
delete gStaticSets;
|
||||
gStaticSets = NULL;
|
||||
gSimpleDateFormatStaticSetsInitOnce.reset();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -86,50 +88,26 @@ smpdtfmt_cleanup(void)
|
|||
{
|
||||
return SimpleDateFormatStaticSets::cleanup();
|
||||
}
|
||||
U_CDECL_END
|
||||
|
||||
void SimpleDateFormatStaticSets::initSets(UErrorCode *status)
|
||||
{
|
||||
SimpleDateFormatStaticSets *p;
|
||||
|
||||
UMTX_CHECK(NULL, gStaticSets, p);
|
||||
if (p == NULL) {
|
||||
p = new SimpleDateFormatStaticSets(status);
|
||||
|
||||
if (p == NULL) {
|
||||
*status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
if (U_FAILURE(*status)) {
|
||||
delete p;
|
||||
return;
|
||||
}
|
||||
|
||||
umtx_lock(NULL);
|
||||
if (gStaticSets == NULL) {
|
||||
gStaticSets = p;
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
umtx_unlock(NULL);
|
||||
if (p != NULL) {
|
||||
delete p;
|
||||
}
|
||||
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_SMPDTFMT, smpdtfmt_cleanup);
|
||||
static void U_CALLCONV smpdtfmt_initSets(UErrorCode &status) {
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_SMPDTFMT, smpdtfmt_cleanup);
|
||||
U_ASSERT(gStaticSets == NULL);
|
||||
gStaticSets = new SimpleDateFormatStaticSets(status);
|
||||
if (gStaticSets == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
U_CDECL_END
|
||||
|
||||
UnicodeSet *SimpleDateFormatStaticSets::getIgnorables(UDateFormatField fieldIndex)
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
initSets(&status);
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
umtx_initOnce(gSimpleDateFormatStaticSetsInitOnce, &smpdtfmt_initSets, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (fieldIndex) {
|
||||
case UDAT_YEAR_FIELD:
|
||||
|
@ -152,7 +130,6 @@ UnicodeSet *SimpleDateFormatStaticSets::getIgnorables(UDateFormatField fieldInde
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif // #if !UCONFIG_NO_FORMATTING
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2009-2011, International Business Machines Corporation and *
|
||||
* Copyright (C) 2009-2013, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -28,10 +28,7 @@ class UnicodeSet;
|
|||
class SimpleDateFormatStaticSets : public UMemory
|
||||
{
|
||||
public:
|
||||
static SimpleDateFormatStaticSets *gStaticSets; // Ptr to all lazily initialized constant
|
||||
// shared sets.
|
||||
|
||||
SimpleDateFormatStaticSets(UErrorCode *status);
|
||||
SimpleDateFormatStaticSets(UErrorCode &status);
|
||||
~SimpleDateFormatStaticSets();
|
||||
|
||||
static void initSets(UErrorCode *status);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2003-2008, International Business Machines Corporation and *
|
||||
* Copyright (C) 2003-2013, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -131,65 +131,21 @@ void TaiwanCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& status
|
|||
}
|
||||
#endif
|
||||
|
||||
// default century
|
||||
const UDate TaiwanCalendar::fgSystemDefaultCentury = DBL_MIN;
|
||||
const int32_t TaiwanCalendar::fgSystemDefaultCenturyYear = -1;
|
||||
|
||||
UDate TaiwanCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
|
||||
int32_t TaiwanCalendar::fgSystemDefaultCenturyStartYear = -1;
|
||||
|
||||
/**
|
||||
* The system maintains a static default century start date and Year. They are
|
||||
* initialized the first time they are used. Once the system default century date
|
||||
* and year are set, they do not change.
|
||||
*/
|
||||
static UDate gSystemDefaultCenturyStart = DBL_MIN;
|
||||
static int32_t gSystemDefaultCenturyStartYear = -1;
|
||||
static UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
|
||||
|
||||
UBool TaiwanCalendar::haveDefaultCentury() const
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UDate TaiwanCalendar::defaultCenturyStart() const
|
||||
{
|
||||
return internalGetDefaultCenturyStart();
|
||||
}
|
||||
|
||||
int32_t TaiwanCalendar::defaultCenturyStartYear() const
|
||||
{
|
||||
return internalGetDefaultCenturyStartYear();
|
||||
}
|
||||
|
||||
UDate
|
||||
TaiwanCalendar::internalGetDefaultCenturyStart() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (needsUpdate) {
|
||||
initializeSystemDefaultCentury();
|
||||
}
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStart
|
||||
|
||||
return fgSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t
|
||||
TaiwanCalendar::internalGetDefaultCenturyStartYear() const
|
||||
{
|
||||
// lazy-evaluate systemDefaultCenturyStartYear
|
||||
UBool needsUpdate;
|
||||
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
|
||||
|
||||
if (needsUpdate) {
|
||||
initializeSystemDefaultCentury();
|
||||
}
|
||||
|
||||
// use defaultCenturyStart unless it's the flag value;
|
||||
// then use systemDefaultCenturyStartYear
|
||||
|
||||
return fgSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
void
|
||||
TaiwanCalendar::initializeSystemDefaultCentury()
|
||||
static void U_CALLCONV initializeSystemDefaultCentury()
|
||||
{
|
||||
// initialize systemDefaultCentury and systemDefaultCenturyYear based
|
||||
// on the current time. They'll be set to 80 years before
|
||||
|
@ -200,20 +156,25 @@ TaiwanCalendar::initializeSystemDefaultCentury()
|
|||
{
|
||||
calendar.setTime(Calendar::getNow(), status);
|
||||
calendar.add(UCAL_YEAR, -80, status);
|
||||
UDate newStart = calendar.getTime(status);
|
||||
int32_t newYear = calendar.get(UCAL_YEAR, status);
|
||||
umtx_lock(NULL);
|
||||
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
|
||||
{
|
||||
fgSystemDefaultCenturyStartYear = newYear;
|
||||
fgSystemDefaultCenturyStart = newStart;
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
|
||||
gSystemDefaultCenturyStart = calendar.getTime(status);
|
||||
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
|
||||
}
|
||||
// We have no recourse upon failure unless we want to propagate the failure
|
||||
// out.
|
||||
}
|
||||
|
||||
UDate TaiwanCalendar::defaultCenturyStart() const {
|
||||
// lazy-evaluate systemDefaultCenturyStart
|
||||
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStart;
|
||||
}
|
||||
|
||||
int32_t TaiwanCalendar::defaultCenturyStartYear() const {
|
||||
// lazy-evaluate systemDefaultCenturyStartYear
|
||||
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
|
||||
return gSystemDefaultCenturyStartYear;
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
********************************************************************************
|
||||
* Copyright (C) 2003-2007, International Business Machines Corporation
|
||||
* Copyright (C) 2003-2013, International Business Machines Corporation
|
||||
* and others. All Rights Reserved.
|
||||
********************************************************************************
|
||||
*
|
||||
|
@ -171,49 +171,6 @@ private:
|
|||
* @internal
|
||||
*/
|
||||
virtual int32_t defaultCenturyStartYear() const;
|
||||
|
||||
private: // default century stuff.
|
||||
/**
|
||||
* The system maintains a static default century start date. This is initialized
|
||||
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
|
||||
* indicate an uninitialized state. Once the system default century date and year
|
||||
* are set, they do not change.
|
||||
*/
|
||||
static UDate fgSystemDefaultCenturyStart;
|
||||
|
||||
/**
|
||||
* See documentation for systemDefaultCenturyStart.
|
||||
*/
|
||||
static int32_t fgSystemDefaultCenturyStartYear;
|
||||
|
||||
/**
|
||||
* Default value that indicates the defaultCenturyStartYear is unitialized
|
||||
*/
|
||||
static const int32_t fgSystemDefaultCenturyYear;
|
||||
|
||||
/**
|
||||
* start of default century, as a date
|
||||
*/
|
||||
static const UDate fgSystemDefaultCentury;
|
||||
|
||||
/**
|
||||
* Returns the beginning date of the 100-year window that dates
|
||||
* with 2-digit years are considered to fall within.
|
||||
*/
|
||||
UDate internalGetDefaultCenturyStart(void) const;
|
||||
|
||||
/**
|
||||
* Returns the first year of the 100-year window that dates with
|
||||
* 2-digit years are considered to fall within.
|
||||
*/
|
||||
int32_t internalGetDefaultCenturyStartYear(void) const;
|
||||
|
||||
/**
|
||||
* Initializes the 100-year window that dates with 2-digit years
|
||||
* are considered to fall within so that its start date is 80 years
|
||||
* before the current time.
|
||||
*/
|
||||
static void initializeSystemDefaultCentury(void);
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/ustring.h"
|
||||
#include "uassert.h"
|
||||
#include "ustr_imp.h"
|
||||
|
||||
#ifdef U_DEBUG_TZ
|
||||
|
@ -109,14 +110,15 @@ static const UChar UNKNOWN_ZONE_ID[] = {0x45, 0x74, 0x63, 0x2F, 0x55, 0x
|
|||
static const int32_t GMT_ID_LENGTH = 3;
|
||||
static const int32_t UNKNOWN_ZONE_ID_LENGTH = 11;
|
||||
|
||||
static UMutex LOCK = U_MUTEX_INITIALIZER;
|
||||
static UMutex TZSET_LOCK = U_MUTEX_INITIALIZER;
|
||||
static icu::TimeZone* DEFAULT_ZONE = NULL;
|
||||
static UInitOnce gDefaultZoneInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
static icu::TimeZone* _GMT = NULL;
|
||||
static icu::TimeZone* _UNKNOWN_ZONE = NULL;
|
||||
static UInitOnce gStaticZonesInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
static char TZDATA_VERSION[16];
|
||||
static UBool TZDataVersionInitialized = FALSE;
|
||||
static UInitOnce gTZDataVersionInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
static int32_t* MAP_SYSTEM_ZONES = NULL;
|
||||
static int32_t* MAP_CANONICAL_SYSTEM_ZONES = NULL;
|
||||
|
@ -126,32 +128,41 @@ static int32_t LEN_SYSTEM_ZONES = 0;
|
|||
static int32_t LEN_CANONICAL_SYSTEM_ZONES = 0;
|
||||
static int32_t LEN_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
|
||||
|
||||
static UInitOnce gSystemZonesInitOnce = U_INITONCE_INITIALIZER;
|
||||
static UInitOnce gCanonicalZonesInitOnce = U_INITONCE_INITIALIZER;
|
||||
static UInitOnce gCanonicalLocationZonesInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
U_CDECL_BEGIN
|
||||
static UBool U_CALLCONV timeZone_cleanup(void)
|
||||
{
|
||||
U_NAMESPACE_USE
|
||||
delete DEFAULT_ZONE;
|
||||
DEFAULT_ZONE = NULL;
|
||||
gDefaultZoneInitOnce.reset();
|
||||
|
||||
delete _GMT;
|
||||
_GMT = NULL;
|
||||
|
||||
delete _UNKNOWN_ZONE;
|
||||
_UNKNOWN_ZONE = NULL;
|
||||
gStaticZonesInitOnce.reset();
|
||||
|
||||
uprv_memset(TZDATA_VERSION, 0, sizeof(TZDATA_VERSION));
|
||||
TZDataVersionInitialized = FALSE;
|
||||
gTZDataVersionInitOnce.reset();
|
||||
|
||||
LEN_SYSTEM_ZONES = 0;
|
||||
uprv_free(MAP_SYSTEM_ZONES);
|
||||
MAP_SYSTEM_ZONES = 0;
|
||||
gSystemZonesInitOnce.reset();
|
||||
|
||||
LEN_CANONICAL_SYSTEM_ZONES = 0;
|
||||
uprv_free(MAP_CANONICAL_SYSTEM_ZONES);
|
||||
MAP_CANONICAL_SYSTEM_ZONES = 0;
|
||||
gCanonicalZonesInitOnce.reset();
|
||||
|
||||
LEN_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
|
||||
uprv_free(MAP_CANONICAL_SYSTEM_LOCATION_ZONES);
|
||||
MAP_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
|
||||
gCanonicalLocationZonesInitOnce.reset();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -287,31 +298,12 @@ static UResourceBundle* openOlsonResource(const UnicodeString& id,
|
|||
|
||||
namespace {
|
||||
|
||||
void
|
||||
ensureStaticTimeZones() {
|
||||
UBool needsInit;
|
||||
UMTX_CHECK(&LOCK, (_GMT == NULL), needsInit); /* This is here to prevent race conditions. */
|
||||
|
||||
void U_CALLCONV initStaticTimeZones() {
|
||||
// Initialize _GMT independently of other static data; it should
|
||||
// be valid even if we can't load the time zone UDataMemory.
|
||||
if (needsInit) {
|
||||
SimpleTimeZone *tmpUnknown =
|
||||
new SimpleTimeZone(0, UnicodeString(TRUE, UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH));
|
||||
SimpleTimeZone *tmpGMT = new SimpleTimeZone(0, UnicodeString(TRUE, GMT_ID, GMT_ID_LENGTH));
|
||||
umtx_lock(&LOCK);
|
||||
if (_UNKNOWN_ZONE == 0) {
|
||||
_UNKNOWN_ZONE = tmpUnknown;
|
||||
tmpUnknown = NULL;
|
||||
}
|
||||
if (_GMT == 0) {
|
||||
_GMT = tmpGMT;
|
||||
tmpGMT = NULL;
|
||||
}
|
||||
umtx_unlock(&LOCK);
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
delete tmpUnknown;
|
||||
delete tmpGMT;
|
||||
}
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
_UNKNOWN_ZONE = new SimpleTimeZone(0, UnicodeString(TRUE, UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH));
|
||||
_GMT = new SimpleTimeZone(0, UnicodeString(TRUE, GMT_ID, GMT_ID_LENGTH));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -319,14 +311,14 @@ ensureStaticTimeZones() {
|
|||
const TimeZone& U_EXPORT2
|
||||
TimeZone::getUnknown()
|
||||
{
|
||||
ensureStaticTimeZones();
|
||||
umtx_initOnce(gStaticZonesInitOnce, &initStaticTimeZones);
|
||||
return *_UNKNOWN_ZONE;
|
||||
}
|
||||
|
||||
const TimeZone* U_EXPORT2
|
||||
TimeZone::getGMT(void)
|
||||
{
|
||||
ensureStaticTimeZones();
|
||||
umtx_initOnce(gStaticZonesInitOnce, &initStaticTimeZones);
|
||||
return _GMT;
|
||||
}
|
||||
|
||||
|
@ -381,43 +373,9 @@ TimeZone::operator==(const TimeZone& that) const
|
|||
|
||||
// -------------------------------------
|
||||
|
||||
TimeZone* U_EXPORT2
|
||||
TimeZone::createTimeZone(const UnicodeString& ID)
|
||||
{
|
||||
/* We first try to lookup the zone ID in our system list. If this
|
||||
* fails, we try to parse it as a custom string GMT[+-]hh:mm. If
|
||||
* all else fails, we return GMT, which is probably not what the
|
||||
* user wants, but at least is a functioning TimeZone object.
|
||||
*
|
||||
* We cannot return NULL, because that would break compatibility
|
||||
* with the JDK.
|
||||
*/
|
||||
TimeZone* result = createSystemTimeZone(ID);
|
||||
|
||||
if (result == 0) {
|
||||
U_DEBUG_TZ_MSG(("failed to load system time zone with id - falling to custom"));
|
||||
result = createCustomTimeZone(ID);
|
||||
}
|
||||
if (result == 0) {
|
||||
U_DEBUG_TZ_MSG(("failed to load time zone with id - falling to Etc/Unknown(GMT)"));
|
||||
result = getUnknown().clone();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the given name in our system zone table. If found,
|
||||
* instantiate a new zone of that name and return it. If not
|
||||
* found, return 0.
|
||||
*/
|
||||
namespace {
|
||||
TimeZone*
|
||||
TimeZone::createSystemTimeZone(const UnicodeString& id) {
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
return createSystemTimeZone(id, ec);
|
||||
}
|
||||
|
||||
TimeZone*
|
||||
TimeZone::createSystemTimeZone(const UnicodeString& id, UErrorCode& ec) {
|
||||
createSystemTimeZone(const UnicodeString& id, UErrorCode& ec) {
|
||||
if (U_FAILURE(ec)) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -443,19 +401,60 @@ TimeZone::createSystemTimeZone(const UnicodeString& id, UErrorCode& ec) {
|
|||
return z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the given name in our system zone table. If found,
|
||||
* instantiate a new zone of that name and return it. If not
|
||||
* found, return 0.
|
||||
*/
|
||||
TimeZone*
|
||||
createSystemTimeZone(const UnicodeString& id) {
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
return createSystemTimeZone(id, ec);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TimeZone* U_EXPORT2
|
||||
TimeZone::createTimeZone(const UnicodeString& ID)
|
||||
{
|
||||
/* We first try to lookup the zone ID in our system list. If this
|
||||
* fails, we try to parse it as a custom string GMT[+-]hh:mm. If
|
||||
* all else fails, we return GMT, which is probably not what the
|
||||
* user wants, but at least is a functioning TimeZone object.
|
||||
*
|
||||
* We cannot return NULL, because that would break compatibility
|
||||
* with the JDK.
|
||||
*/
|
||||
TimeZone* result = createSystemTimeZone(ID);
|
||||
|
||||
if (result == 0) {
|
||||
U_DEBUG_TZ_MSG(("failed to load system time zone with id - falling to custom"));
|
||||
result = createCustomTimeZone(ID);
|
||||
}
|
||||
if (result == 0) {
|
||||
U_DEBUG_TZ_MSG(("failed to load time zone with id - falling to Etc/Unknown(GMT)"));
|
||||
result = getUnknown().clone();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
/**
|
||||
* Initialize DEFAULT_ZONE from the system default time zone. The
|
||||
* caller should confirm that DEFAULT_ZONE is NULL before calling.
|
||||
* Initialize DEFAULT_ZONE from the system default time zone.
|
||||
* Upon return, DEFAULT_ZONE will not be NULL, unless operator new()
|
||||
* returns NULL.
|
||||
*
|
||||
* Must be called OUTSIDE mutex.
|
||||
*/
|
||||
void
|
||||
TimeZone::initDefault()
|
||||
static void U_CALLCONV initDefault()
|
||||
{
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
|
||||
// If setDefault() has already been called we can skip getting the
|
||||
// default zone information from the system.
|
||||
if (DEFAULT_ZONE != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We access system timezone data through TPlatformUtilities,
|
||||
// including tzset(), timezone, and tzname[].
|
||||
int32_t rawOffset = 0;
|
||||
|
@ -463,38 +462,27 @@ TimeZone::initDefault()
|
|||
|
||||
// First, try to create a system timezone, based
|
||||
// on the string ID in tzname[0].
|
||||
{
|
||||
// NOTE: Local mutex here. TimeZone mutex below
|
||||
// mutexed to avoid threading issues in the platform functions.
|
||||
// Some of the locale/timezone OS functions may not be thread safe,
|
||||
// so the intent is that any setting from anywhere within ICU
|
||||
// happens while the ICU mutex is held.
|
||||
// The operating system might actually use ICU to implement timezones.
|
||||
// So we may have ICU calling ICU here, like on AIX.
|
||||
// In order to prevent a double lock of a non-reentrant mutex in a
|
||||
// different part of ICU, we use TZSET_LOCK to allow only one instance
|
||||
// of ICU to query these thread unsafe OS functions at any given time.
|
||||
Mutex lock(&TZSET_LOCK);
|
||||
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
uprv_tzset(); // Initialize tz... system data
|
||||
// NOTE: this code is safely single threaded, being only
|
||||
// run via umtx_initOnce().
|
||||
//
|
||||
// Some of the locale/timezone OS functions may not be thread safe,
|
||||
//
|
||||
// The operating system might actually use ICU to implement timezones.
|
||||
// So we may have ICU calling ICU here, like on AIX.
|
||||
// There shouldn't be a problem with this; initOnce does not hold a mutex
|
||||
// while the init function is being run.
|
||||
|
||||
// Get the timezone ID from the host. This function should do
|
||||
// any required host-specific remapping; e.g., on Windows this
|
||||
// function maps the Date and Time control panel setting to an
|
||||
// ICU timezone ID.
|
||||
hostID = uprv_tzname(0);
|
||||
uprv_tzset(); // Initialize tz... system data
|
||||
|
||||
// Invert sign because UNIX semantics are backwards
|
||||
rawOffset = uprv_timezone() * -U_MILLIS_PER_SECOND;
|
||||
}
|
||||
// Get the timezone ID from the host. This function should do
|
||||
// any required host-specific remapping; e.g., on Windows this
|
||||
// function maps the Date and Time control panel setting to an
|
||||
// ICU timezone ID.
|
||||
hostID = uprv_tzname(0);
|
||||
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&LOCK, (DEFAULT_ZONE != NULL), initialized);
|
||||
if (initialized) {
|
||||
/* Hrmph? Either a race condition happened, or tzset initialized ICU. */
|
||||
return;
|
||||
}
|
||||
// Invert sign because UNIX semantics are backwards
|
||||
rawOffset = uprv_timezone() * -U_MILLIS_PER_SECOND;
|
||||
|
||||
TimeZone* default_zone = NULL;
|
||||
|
||||
|
@ -527,7 +515,7 @@ TimeZone::initDefault()
|
|||
|
||||
// If we _still_ don't have a time zone, use GMT.
|
||||
if (default_zone == NULL) {
|
||||
const TimeZone* temptz = getGMT();
|
||||
const TimeZone* temptz = TimeZone::getGMT();
|
||||
// If we can't use GMT, get out.
|
||||
if (temptz == NULL) {
|
||||
return;
|
||||
|
@ -535,16 +523,12 @@ TimeZone::initDefault()
|
|||
default_zone = temptz->clone();
|
||||
}
|
||||
|
||||
// If DEFAULT_ZONE is still NULL, set it up.
|
||||
umtx_lock(&LOCK);
|
||||
if (DEFAULT_ZONE == NULL) {
|
||||
DEFAULT_ZONE = default_zone;
|
||||
default_zone = NULL;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
}
|
||||
umtx_unlock(&LOCK);
|
||||
// The only way for DEFAULT_ZONE to be non-null at this point is if the user
|
||||
// made a thread-unsafe call to setDefault() or adoptDefault() in another
|
||||
// thread while this thread was doing something that required getting the default.
|
||||
U_ASSERT(DEFAULT_ZONE == NULL);
|
||||
|
||||
delete default_zone;
|
||||
DEFAULT_ZONE = default_zone;
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
@ -552,14 +536,7 @@ TimeZone::initDefault()
|
|||
TimeZone* U_EXPORT2
|
||||
TimeZone::createDefault()
|
||||
{
|
||||
/* This is here to prevent race conditions. */
|
||||
UBool needsInit;
|
||||
UMTX_CHECK(&LOCK, (DEFAULT_ZONE == NULL), needsInit);
|
||||
if (needsInit) {
|
||||
initDefault();
|
||||
}
|
||||
|
||||
Mutex lock(&LOCK); // In case adoptDefault is called
|
||||
umtx_initOnce(gDefaultZoneInitOnce, initDefault);
|
||||
return (DEFAULT_ZONE != NULL) ? DEFAULT_ZONE->clone() : NULL;
|
||||
}
|
||||
|
||||
|
@ -570,13 +547,8 @@ TimeZone::adoptDefault(TimeZone* zone)
|
|||
{
|
||||
if (zone != NULL)
|
||||
{
|
||||
TimeZone* old = NULL;
|
||||
|
||||
umtx_lock(&LOCK);
|
||||
old = DEFAULT_ZONE;
|
||||
TimeZone *old = DEFAULT_ZONE;
|
||||
DEFAULT_ZONE = zone;
|
||||
umtx_unlock(&LOCK);
|
||||
|
||||
delete old;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
}
|
||||
|
@ -591,6 +563,84 @@ TimeZone::setDefault(const TimeZone& zone)
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
||||
static void U_CALLCONV initMap(USystemTimeZoneType type, UErrorCode& ec) {
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
|
||||
UResourceBundle *res = ures_openDirect(0, kZONEINFO, &ec);
|
||||
res = ures_getByKey(res, kNAMES, res, &ec); // dereference Zones section
|
||||
if (U_SUCCESS(ec)) {
|
||||
int32_t size = ures_getSize(res);
|
||||
int32_t *m = (int32_t *)uprv_malloc(size * sizeof(int32_t));
|
||||
if (m == NULL) {
|
||||
ec = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else {
|
||||
int32_t numEntries = 0;
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
UnicodeString id = ures_getUnicodeStringByIndex(res, i, &ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (0 == id.compare(UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH)) {
|
||||
// exclude Etc/Unknown
|
||||
continue;
|
||||
}
|
||||
if (type == UCAL_ZONE_TYPE_CANONICAL || type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
|
||||
UnicodeString canonicalID;
|
||||
ZoneMeta::getCanonicalCLDRID(id, canonicalID, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (canonicalID != id) {
|
||||
// exclude aliases
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
|
||||
const UChar *region = TimeZone::getRegion(id, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (u_strcmp(region, WORLD) == 0) {
|
||||
// exclude non-location ("001")
|
||||
continue;
|
||||
}
|
||||
}
|
||||
m[numEntries++] = i;
|
||||
}
|
||||
if (U_SUCCESS(ec)) {
|
||||
int32_t *tmp = m;
|
||||
m = (int32_t *)uprv_realloc(tmp, numEntries * sizeof(int32_t));
|
||||
if (m == NULL) {
|
||||
// realloc failed.. use the original one even it has unused
|
||||
// area at the end
|
||||
m = tmp;
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case UCAL_ZONE_TYPE_ANY:
|
||||
U_ASSERT(MAP_SYSTEM_ZONES == NULL);
|
||||
MAP_SYSTEM_ZONES = m;
|
||||
LEN_SYSTEM_ZONES = numEntries;
|
||||
break;
|
||||
case UCAL_ZONE_TYPE_CANONICAL:
|
||||
U_ASSERT(MAP_CANONICAL_SYSTEM_ZONES == NULL);
|
||||
MAP_CANONICAL_SYSTEM_ZONES = m;
|
||||
LEN_CANONICAL_SYSTEM_ZONES = numEntries;
|
||||
break;
|
||||
case UCAL_ZONE_TYPE_CANONICAL_LOCATION:
|
||||
U_ASSERT(MAP_CANONICAL_SYSTEM_LOCATION_ZONES == NULL);
|
||||
MAP_CANONICAL_SYSTEM_LOCATION_ZONES = m;
|
||||
LEN_CANONICAL_SYSTEM_LOCATION_ZONES = numEntries;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ures_close(res);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is the default implementation for subclasses that do not
|
||||
* override this method. This implementation calls through to the
|
||||
|
@ -688,129 +738,29 @@ private:
|
|||
int32_t* m = NULL;
|
||||
switch (type) {
|
||||
case UCAL_ZONE_TYPE_ANY:
|
||||
umtx_initOnce(gSystemZonesInitOnce, &initMap, type, ec);
|
||||
m = MAP_SYSTEM_ZONES;
|
||||
len = LEN_SYSTEM_ZONES;
|
||||
break;
|
||||
case UCAL_ZONE_TYPE_CANONICAL:
|
||||
umtx_initOnce(gCanonicalZonesInitOnce, &initMap, type, ec);
|
||||
m = MAP_CANONICAL_SYSTEM_ZONES;
|
||||
len = LEN_CANONICAL_SYSTEM_ZONES;
|
||||
break;
|
||||
case UCAL_ZONE_TYPE_CANONICAL_LOCATION:
|
||||
umtx_initOnce(gCanonicalLocationZonesInitOnce, &initMap, type, ec);
|
||||
m = MAP_CANONICAL_SYSTEM_LOCATION_ZONES;
|
||||
len = LEN_CANONICAL_SYSTEM_LOCATION_ZONES;
|
||||
break;
|
||||
}
|
||||
UBool needsInit = FALSE;
|
||||
UMTX_CHECK(&LOCK, (len == 0), needsInit);
|
||||
if (needsInit) {
|
||||
m = initMap(type, len, ec);
|
||||
default:
|
||||
ec = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
m = NULL;
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static int32_t* initMap(USystemTimeZoneType type, int32_t& len, UErrorCode& ec) {
|
||||
len = 0;
|
||||
if (U_FAILURE(ec)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t *result = NULL;
|
||||
|
||||
UResourceBundle *res = ures_openDirect(0, kZONEINFO, &ec);
|
||||
res = ures_getByKey(res, kNAMES, res, &ec); // dereference Zones section
|
||||
if (U_SUCCESS(ec)) {
|
||||
int32_t size = ures_getSize(res);
|
||||
int32_t *m = (int32_t *)uprv_malloc(size * sizeof(int32_t));
|
||||
if (m == NULL) {
|
||||
ec = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else {
|
||||
int32_t numEntries = 0;
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
UnicodeString id = ures_getUnicodeStringByIndex(res, i, &ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (0 == id.compare(UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH)) {
|
||||
// exclude Etc/Unknown
|
||||
continue;
|
||||
}
|
||||
if (type == UCAL_ZONE_TYPE_CANONICAL || type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
|
||||
UnicodeString canonicalID;
|
||||
ZoneMeta::getCanonicalCLDRID(id, canonicalID, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (canonicalID != id) {
|
||||
// exclude aliases
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
|
||||
const UChar *region = TimeZone::getRegion(id, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (u_strcmp(region, WORLD) == 0) {
|
||||
// exclude non-location ("001")
|
||||
continue;
|
||||
}
|
||||
}
|
||||
m[numEntries++] = i;
|
||||
}
|
||||
if (U_SUCCESS(ec)) {
|
||||
int32_t *tmp = m;
|
||||
m = (int32_t *)uprv_realloc(tmp, numEntries * sizeof(int32_t));
|
||||
if (m == NULL) {
|
||||
// realloc failed.. use the original one even it has unused
|
||||
// area at the end
|
||||
m = tmp;
|
||||
}
|
||||
|
||||
umtx_lock(&LOCK);
|
||||
{
|
||||
switch(type) {
|
||||
case UCAL_ZONE_TYPE_ANY:
|
||||
if (MAP_SYSTEM_ZONES == NULL) {
|
||||
MAP_SYSTEM_ZONES = m;
|
||||
LEN_SYSTEM_ZONES = numEntries;
|
||||
m = NULL;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
}
|
||||
result = MAP_SYSTEM_ZONES;
|
||||
len = LEN_SYSTEM_ZONES;
|
||||
break;
|
||||
case UCAL_ZONE_TYPE_CANONICAL:
|
||||
if (MAP_CANONICAL_SYSTEM_ZONES == NULL) {
|
||||
MAP_CANONICAL_SYSTEM_ZONES = m;
|
||||
LEN_CANONICAL_SYSTEM_ZONES = numEntries;
|
||||
m = NULL;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
}
|
||||
result = MAP_CANONICAL_SYSTEM_ZONES;
|
||||
len = LEN_CANONICAL_SYSTEM_ZONES;
|
||||
break;
|
||||
case UCAL_ZONE_TYPE_CANONICAL_LOCATION:
|
||||
if (MAP_CANONICAL_SYSTEM_LOCATION_ZONES == NULL) {
|
||||
MAP_CANONICAL_SYSTEM_LOCATION_ZONES = m;
|
||||
LEN_CANONICAL_SYSTEM_LOCATION_ZONES = numEntries;
|
||||
m = NULL;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
}
|
||||
result = MAP_CANONICAL_SYSTEM_LOCATION_ZONES;
|
||||
len = LEN_CANONICAL_SYSTEM_LOCATION_ZONES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
umtx_unlock(&LOCK);
|
||||
}
|
||||
uprv_free(m);
|
||||
}
|
||||
}
|
||||
|
||||
ures_close(res);
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
#define DEFAULT_FILTERED_MAP_SIZE 8
|
||||
|
@ -866,7 +816,7 @@ public:
|
|||
if (rawOffset != NULL) {
|
||||
// Filter by raw offset
|
||||
// Note: This is VERY inefficient
|
||||
TimeZone *z = TimeZone::createSystemTimeZone(id, ec);
|
||||
TimeZone *z = createSystemTimeZone(id, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
|
@ -1516,37 +1466,27 @@ TimeZone::hasSameRules(const TimeZone& other) const
|
|||
useDaylightTime() == other.useDaylightTime());
|
||||
}
|
||||
|
||||
static void U_CALLCONV initTZDataVersion(UErrorCode &status) {
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
int32_t len = 0;
|
||||
UResourceBundle *bundle = ures_openDirect(NULL, kZONEINFO, &status);
|
||||
const UChar *tzver = ures_getStringByKey(bundle, kTZVERSION, &len, &status);
|
||||
|
||||
if (U_SUCCESS(status)) {
|
||||
if (len >= (int32_t)sizeof(TZDATA_VERSION)) {
|
||||
// Ensure that there is always space for a trailing nul in TZDATA_VERSION
|
||||
len = sizeof(TZDATA_VERSION) - 1;
|
||||
}
|
||||
u_UCharsToChars(tzver, TZDATA_VERSION, len);
|
||||
}
|
||||
ures_close(bundle);
|
||||
|
||||
}
|
||||
|
||||
const char*
|
||||
TimeZone::getTZDataVersion(UErrorCode& status)
|
||||
{
|
||||
/* This is here to prevent race conditions. */
|
||||
UBool needsInit;
|
||||
UMTX_CHECK(&LOCK, !TZDataVersionInitialized, needsInit);
|
||||
if (needsInit) {
|
||||
int32_t len = 0;
|
||||
UResourceBundle *bundle = ures_openDirect(NULL, kZONEINFO, &status);
|
||||
const UChar *tzver = ures_getStringByKey(bundle, kTZVERSION,
|
||||
&len, &status);
|
||||
|
||||
if (U_SUCCESS(status)) {
|
||||
if (len >= (int32_t)sizeof(TZDATA_VERSION)) {
|
||||
// Ensure that there is always space for a trailing nul in TZDATA_VERSION
|
||||
len = sizeof(TZDATA_VERSION) - 1;
|
||||
}
|
||||
umtx_lock(&LOCK);
|
||||
if (!TZDataVersionInitialized) {
|
||||
u_UCharsToChars(tzver, TZDATA_VERSION, len);
|
||||
TZDataVersionInitialized = TRUE;
|
||||
}
|
||||
umtx_unlock(&LOCK);
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
}
|
||||
|
||||
ures_close(bundle);
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
umtx_initOnce(gTZDataVersionInitOnce, &initTZDataVersion, status);
|
||||
return (const char*)TZDATA_VERSION;
|
||||
}
|
||||
|
||||
|
|
|
@ -136,10 +136,10 @@ static const int32_t ALL_GENERIC_NAME_TYPES = UTZGNM_LOCATION | UTZGNM_LONG | UT
|
|||
|
||||
// Time Zone ID/Short ID trie
|
||||
static TextTrieMap *gZoneIdTrie = NULL;
|
||||
static UBool gZoneIdTrieInitialized = FALSE;
|
||||
static UInitOnce gZoneIdTrieInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
static TextTrieMap *gShortZoneIdTrie = NULL;
|
||||
static UBool gShortZoneIdTrieInitialized = FALSE;
|
||||
static UInitOnce gShortZoneIdTrieInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
static UMutex gLock = U_MUTEX_INITIALIZER;
|
||||
|
||||
|
@ -153,13 +153,13 @@ static UBool U_CALLCONV tzfmt_cleanup(void)
|
|||
delete gZoneIdTrie;
|
||||
}
|
||||
gZoneIdTrie = NULL;
|
||||
gZoneIdTrieInitialized = FALSE;
|
||||
gZoneIdTrieInitOnce.reset();
|
||||
|
||||
if (gShortZoneIdTrie != NULL) {
|
||||
delete gShortZoneIdTrie;
|
||||
}
|
||||
gShortZoneIdTrie = NULL;
|
||||
gShortZoneIdTrieInitialized = FALSE;
|
||||
gShortZoneIdTrieInitOnce.reset();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -438,6 +438,7 @@ TimeZoneFormat::operator=(const TimeZoneFormat& other) {
|
|||
|
||||
fTimeZoneNames = other.fTimeZoneNames->clone();
|
||||
if (other.fTimeZoneGenericNames) {
|
||||
// TODO: this test has dubious thread safety.
|
||||
fTimeZoneGenericNames = other.fTimeZoneGenericNames->clone();
|
||||
}
|
||||
|
||||
|
@ -1291,18 +1292,12 @@ TimeZoneFormat::getTimeZoneGenericNames(UErrorCode& status) const {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
UBool create;
|
||||
UMTX_CHECK(&gZoneMetaLock, (fTimeZoneGenericNames == NULL), create);
|
||||
if (create) {
|
||||
umtx_lock(&gLock);
|
||||
if (fTimeZoneGenericNames == NULL) {
|
||||
TimeZoneFormat *nonConstThis = const_cast<TimeZoneFormat *>(this);
|
||||
umtx_lock(&gLock);
|
||||
{
|
||||
if (fTimeZoneGenericNames == NULL) {
|
||||
nonConstThis->fTimeZoneGenericNames = TimeZoneGenericNames::createInstance(fLocale, status);
|
||||
}
|
||||
}
|
||||
umtx_unlock(&gLock);
|
||||
nonConstThis->fTimeZoneGenericNames = TimeZoneGenericNames::createInstance(fLocale, status);
|
||||
}
|
||||
umtx_unlock(&gLock);
|
||||
|
||||
return fTimeZoneGenericNames;
|
||||
}
|
||||
|
@ -2634,44 +2629,37 @@ ZoneIdMatchHandler::getMatchLen() {
|
|||
return fLen;
|
||||
}
|
||||
|
||||
|
||||
static void U_CALLCONV initZoneIdTrie(UErrorCode &status) {
|
||||
U_ASSERT(gZoneIdTrie == NULL);
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONEFORMAT, tzfmt_cleanup);
|
||||
gZoneIdTrie = new TextTrieMap(TRUE, NULL); // No deleter, because values are pooled by ZoneMeta
|
||||
if (gZoneIdTrie == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
return;
|
||||
}
|
||||
StringEnumeration *tzenum = TimeZone::createEnumeration();
|
||||
const UnicodeString *id;
|
||||
while ((id = tzenum->snext(status))) {
|
||||
const UChar* uid = ZoneMeta::findTimeZoneID(*id);
|
||||
if (uid) {
|
||||
gZoneIdTrie->put(uid, const_cast<UChar *>(uid), status);
|
||||
}
|
||||
}
|
||||
delete tzenum;
|
||||
}
|
||||
|
||||
|
||||
UnicodeString&
|
||||
TimeZoneFormat::parseZoneID(const UnicodeString& text, ParsePosition& pos, UnicodeString& tzID) const {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&gLock, gZoneIdTrieInitialized, initialized);
|
||||
if (!initialized) {
|
||||
umtx_lock(&gLock);
|
||||
{
|
||||
if (!gZoneIdTrieInitialized) {
|
||||
StringEnumeration *tzenum = TimeZone::createEnumeration();
|
||||
TextTrieMap* trie = new TextTrieMap(TRUE, NULL); // No deleter, because values are pooled by ZoneMeta
|
||||
if (trie) {
|
||||
const UnicodeString *id;
|
||||
while ((id = tzenum->snext(status))) {
|
||||
const UChar* uid = ZoneMeta::findTimeZoneID(*id);
|
||||
if (uid) {
|
||||
trie->put(uid, const_cast<UChar *>(uid), status);
|
||||
}
|
||||
}
|
||||
if (U_SUCCESS(status)) {
|
||||
gZoneIdTrie = trie;
|
||||
gZoneIdTrieInitialized = initialized = TRUE;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONEFORMAT, tzfmt_cleanup);
|
||||
} else {
|
||||
delete trie;
|
||||
}
|
||||
}
|
||||
delete tzenum;
|
||||
}
|
||||
}
|
||||
umtx_unlock(&gLock);
|
||||
}
|
||||
umtx_initOnce(gZoneIdTrieInitOnce, &initZoneIdTrie, status);
|
||||
|
||||
int32_t start = pos.getIndex();
|
||||
int32_t len = 0;
|
||||
tzID.setToBogus();
|
||||
|
||||
if (initialized) {
|
||||
if (U_SUCCESS(status)) {
|
||||
LocalPointer<ZoneIdMatchHandler> handler(new ZoneIdMatchHandler());
|
||||
gZoneIdTrie->search(text, start, handler.getAlias(), status);
|
||||
len = handler->getMatchLen();
|
||||
|
@ -2689,47 +2677,39 @@ TimeZoneFormat::parseZoneID(const UnicodeString& text, ParsePosition& pos, Unico
|
|||
return tzID;
|
||||
}
|
||||
|
||||
static void U_CALLCONV initShortZoneIdTrie(UErrorCode &status) {
|
||||
U_ASSERT(gShortZoneIdTrie == NULL);
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONEFORMAT, tzfmt_cleanup);
|
||||
StringEnumeration *tzenum = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, status);
|
||||
if (U_SUCCESS(status)) {
|
||||
gShortZoneIdTrie = new TextTrieMap(TRUE, NULL); // No deleter, because values are pooled by ZoneMeta
|
||||
if (gShortZoneIdTrie == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else {
|
||||
const UnicodeString *id;
|
||||
while ((id = tzenum->snext(status))) {
|
||||
const UChar* uID = ZoneMeta::findTimeZoneID(*id);
|
||||
const UChar* shortID = ZoneMeta::getShortID(*id);
|
||||
if (shortID && uID) {
|
||||
gShortZoneIdTrie->put(shortID, const_cast<UChar *>(uID), status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete tzenum;
|
||||
}
|
||||
|
||||
|
||||
UnicodeString&
|
||||
TimeZoneFormat::parseShortZoneID(const UnicodeString& text, ParsePosition& pos, UnicodeString& tzID) const {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&gLock, gShortZoneIdTrieInitialized, initialized);
|
||||
if (!initialized) {
|
||||
umtx_lock(&gLock);
|
||||
{
|
||||
if (!gShortZoneIdTrieInitialized) {
|
||||
StringEnumeration *tzenum = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, status);
|
||||
if (U_SUCCESS(status)) {
|
||||
TextTrieMap* trie = new TextTrieMap(TRUE, NULL); // No deleter, because values are pooled by ZoneMeta
|
||||
if (trie) {
|
||||
const UnicodeString *id;
|
||||
while ((id = tzenum->snext(status))) {
|
||||
const UChar* uID = ZoneMeta::findTimeZoneID(*id);
|
||||
const UChar* shortID = ZoneMeta::getShortID(*id);
|
||||
if (shortID && uID) {
|
||||
trie->put(shortID, const_cast<UChar *>(uID), status);
|
||||
}
|
||||
}
|
||||
if (U_SUCCESS(status)) {
|
||||
gShortZoneIdTrie = trie;
|
||||
gShortZoneIdTrieInitialized = initialized = TRUE;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONEFORMAT, tzfmt_cleanup);
|
||||
} else {
|
||||
delete trie;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete tzenum;
|
||||
}
|
||||
}
|
||||
umtx_unlock(&gLock);
|
||||
}
|
||||
umtx_initOnce(gShortZoneIdTrieInitOnce, &initShortZoneIdTrie, status);
|
||||
|
||||
int32_t start = pos.getIndex();
|
||||
int32_t len = 0;
|
||||
tzID.setToBogus();
|
||||
|
||||
if (initialized) {
|
||||
if (U_SUCCESS(status)) {
|
||||
LocalPointer<ZoneIdMatchHandler> handler(new ZoneIdMatchHandler());
|
||||
gShortZoneIdTrie->search(text, start, handler.getAlias(), status);
|
||||
len = handler->getMatchLen();
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "cmemory.h"
|
||||
#include "cstring.h"
|
||||
#include "mutex.h"
|
||||
#include "uhash.h"
|
||||
#include "uassert.h"
|
||||
#include "umutex.h"
|
||||
|
@ -1222,33 +1223,25 @@ TimeZoneGenericNames::createInstance(const Locale& locale, UErrorCode& status) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&gTZGNLock, gTZGNCoreCacheInitialized, initialized);
|
||||
if (!initialized) {
|
||||
// Create empty hashtable
|
||||
umtx_lock(&gTZGNLock);
|
||||
{
|
||||
if (!gTZGNCoreCacheInitialized) {
|
||||
gTZGNCoreCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
uhash_setKeyDeleter(gTZGNCoreCache, uprv_free);
|
||||
uhash_setValueDeleter(gTZGNCoreCache, deleteTZGNCoreRef);
|
||||
gTZGNCoreCacheInitialized = TRUE;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONEGENERICNAMES, tzgnCore_cleanup);
|
||||
}
|
||||
TZGNCoreRef *cacheEntry = NULL;
|
||||
{
|
||||
Mutex lock(&gTZGNLock);
|
||||
|
||||
if (!gTZGNCoreCacheInitialized) {
|
||||
// Create empty hashtable
|
||||
gTZGNCoreCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
uhash_setKeyDeleter(gTZGNCoreCache, uprv_free);
|
||||
uhash_setValueDeleter(gTZGNCoreCache, deleteTZGNCoreRef);
|
||||
gTZGNCoreCacheInitialized = TRUE;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONEGENERICNAMES, tzgnCore_cleanup);
|
||||
}
|
||||
}
|
||||
umtx_unlock(&gTZGNLock);
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the cache, if not available, create new one and cache
|
||||
TZGNCoreRef *cacheEntry = NULL;
|
||||
umtx_lock(&gTZGNLock);
|
||||
{
|
||||
// Check the cache, if not available, create new one and cache
|
||||
const char *key = locale.getName();
|
||||
cacheEntry = (TZGNCoreRef *)uhash_get(gTZGNCoreCache, key);
|
||||
if (cacheEntry == NULL) {
|
||||
|
@ -1302,8 +1295,7 @@ TimeZoneGenericNames::createInstance(const Locale& locale, UErrorCode& status) {
|
|||
sweepCache();
|
||||
gAccessCount = 0;
|
||||
}
|
||||
}
|
||||
umtx_unlock(&gTZGNLock);
|
||||
} // End of mutex locked block
|
||||
|
||||
if (cacheEntry == NULL) {
|
||||
delete instance;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "unicode/uenum.h"
|
||||
#include "cmemory.h"
|
||||
#include "cstring.h"
|
||||
#include "mutex.h"
|
||||
#include "putilimp.h"
|
||||
#include "tznames_impl.h"
|
||||
#include "uassert.h"
|
||||
|
@ -126,89 +127,78 @@ TimeZoneNamesDelegate::TimeZoneNamesDelegate()
|
|||
}
|
||||
|
||||
TimeZoneNamesDelegate::TimeZoneNamesDelegate(const Locale& locale, UErrorCode& status) {
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&gTimeZoneNamesLock, gTimeZoneNamesCacheInitialized, initialized);
|
||||
if (!initialized) {
|
||||
// Create empty hashtable
|
||||
umtx_lock(&gTimeZoneNamesLock);
|
||||
{
|
||||
if (!gTimeZoneNamesCacheInitialized) {
|
||||
gTimeZoneNamesCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
uhash_setKeyDeleter(gTimeZoneNamesCache, uprv_free);
|
||||
uhash_setValueDeleter(gTimeZoneNamesCache, deleteTimeZoneNamesCacheEntry);
|
||||
gTimeZoneNamesCacheInitialized = TRUE;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONENAMES, timeZoneNames_cleanup);
|
||||
}
|
||||
}
|
||||
Mutex lock(&gTimeZoneNamesLock);
|
||||
if (!gTimeZoneNamesCacheInitialized) {
|
||||
// Create empty hashtable if it is not already initialized.
|
||||
gTimeZoneNamesCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
uhash_setKeyDeleter(gTimeZoneNamesCache, uprv_free);
|
||||
uhash_setValueDeleter(gTimeZoneNamesCache, deleteTimeZoneNamesCacheEntry);
|
||||
gTimeZoneNamesCacheInitialized = TRUE;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONENAMES, timeZoneNames_cleanup);
|
||||
}
|
||||
umtx_unlock(&gTimeZoneNamesLock);
|
||||
}
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the cache, if not available, create new one and cache
|
||||
TimeZoneNamesCacheEntry *cacheEntry = NULL;
|
||||
umtx_lock(&gTimeZoneNamesLock);
|
||||
{
|
||||
const char *key = locale.getName();
|
||||
cacheEntry = (TimeZoneNamesCacheEntry *)uhash_get(gTimeZoneNamesCache, key);
|
||||
if (cacheEntry == NULL) {
|
||||
TimeZoneNames *tznames = NULL;
|
||||
char *newKey = NULL;
|
||||
|
||||
tznames = new TimeZoneNamesImpl(locale, status);
|
||||
if (tznames == NULL) {
|
||||
const char *key = locale.getName();
|
||||
cacheEntry = (TimeZoneNamesCacheEntry *)uhash_get(gTimeZoneNamesCache, key);
|
||||
if (cacheEntry == NULL) {
|
||||
TimeZoneNames *tznames = NULL;
|
||||
char *newKey = NULL;
|
||||
|
||||
tznames = new TimeZoneNamesImpl(locale, status);
|
||||
if (tznames == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
if (U_SUCCESS(status)) {
|
||||
newKey = (char *)uprv_malloc(uprv_strlen(key) + 1);
|
||||
if (newKey == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else {
|
||||
uprv_strcpy(newKey, key);
|
||||
}
|
||||
if (U_SUCCESS(status)) {
|
||||
newKey = (char *)uprv_malloc(uprv_strlen(key) + 1);
|
||||
if (newKey == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else {
|
||||
uprv_strcpy(newKey, key);
|
||||
}
|
||||
}
|
||||
if (U_SUCCESS(status)) {
|
||||
cacheEntry = (TimeZoneNamesCacheEntry *)uprv_malloc(sizeof(TimeZoneNamesCacheEntry));
|
||||
if (cacheEntry == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else {
|
||||
cacheEntry->names = tznames;
|
||||
cacheEntry->refCount = 1;
|
||||
cacheEntry->lastAccess = (double)uprv_getUTCtime();
|
||||
}
|
||||
if (U_SUCCESS(status)) {
|
||||
cacheEntry = (TimeZoneNamesCacheEntry *)uprv_malloc(sizeof(TimeZoneNamesCacheEntry));
|
||||
if (cacheEntry == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else {
|
||||
cacheEntry->names = tznames;
|
||||
cacheEntry->refCount = 1;
|
||||
cacheEntry->lastAccess = (double)uprv_getUTCtime();
|
||||
|
||||
uhash_put(gTimeZoneNamesCache, newKey, cacheEntry, &status);
|
||||
}
|
||||
uhash_put(gTimeZoneNamesCache, newKey, cacheEntry, &status);
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
if (tznames != NULL) {
|
||||
delete tznames;
|
||||
}
|
||||
if (newKey != NULL) {
|
||||
uprv_free(newKey);
|
||||
}
|
||||
if (cacheEntry != NULL) {
|
||||
uprv_free(cacheEntry);
|
||||
}
|
||||
cacheEntry = NULL;
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
if (tznames != NULL) {
|
||||
delete tznames;
|
||||
}
|
||||
} else {
|
||||
// Update the reference count
|
||||
cacheEntry->refCount++;
|
||||
cacheEntry->lastAccess = (double)uprv_getUTCtime();
|
||||
}
|
||||
gAccessCount++;
|
||||
if (gAccessCount >= SWEEP_INTERVAL) {
|
||||
// sweep
|
||||
sweepCache();
|
||||
gAccessCount = 0;
|
||||
if (newKey != NULL) {
|
||||
uprv_free(newKey);
|
||||
}
|
||||
if (cacheEntry != NULL) {
|
||||
uprv_free(cacheEntry);
|
||||
}
|
||||
cacheEntry = NULL;
|
||||
}
|
||||
} else {
|
||||
// Update the reference count
|
||||
cacheEntry->refCount++;
|
||||
cacheEntry->lastAccess = (double)uprv_getUTCtime();
|
||||
}
|
||||
gAccessCount++;
|
||||
if (gAccessCount >= SWEEP_INTERVAL) {
|
||||
// sweep
|
||||
sweepCache();
|
||||
gAccessCount = 0;
|
||||
}
|
||||
umtx_unlock(&gTimeZoneNamesLock);
|
||||
|
||||
fTZnamesCacheEntry = cacheEntry;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "cmemory.h"
|
||||
#include "cstring.h"
|
||||
#include "uassert.h"
|
||||
#include "mutex.h"
|
||||
#include "uresimp.h"
|
||||
#include "ureslocs.h"
|
||||
#include "zonemeta.h"
|
||||
|
@ -290,7 +291,6 @@ static UMutex TextTrieMutex = U_MUTEX_INITIALIZER;
|
|||
// needed for parsing operations, which are less common than formatting,
|
||||
// and the Trie is big, which is why its creation is deferred until first use.
|
||||
void TextTrieMap::buildTrie(UErrorCode &status) {
|
||||
umtx_lock(&TextTrieMutex);
|
||||
if (fLazyContents != NULL) {
|
||||
for (int32_t i=0; i<fLazyContents->size(); i+=2) {
|
||||
const UChar *key = (UChar *)fLazyContents->elementAt(i);
|
||||
|
@ -301,17 +301,22 @@ void TextTrieMap::buildTrie(UErrorCode &status) {
|
|||
delete fLazyContents;
|
||||
fLazyContents = NULL;
|
||||
}
|
||||
umtx_unlock(&TextTrieMutex);
|
||||
}
|
||||
|
||||
void
|
||||
TextTrieMap::search(const UnicodeString &text, int32_t start,
|
||||
TextTrieMapSearchResultHandler *handler, UErrorCode &status) const {
|
||||
UBool trieNeedsInitialization = FALSE;
|
||||
UMTX_CHECK(&TextTrieMutex, fLazyContents != NULL, trieNeedsInitialization);
|
||||
if (trieNeedsInitialization) {
|
||||
TextTrieMap *nonConstThis = const_cast<TextTrieMap *>(this);
|
||||
nonConstThis->buildTrie(status);
|
||||
{
|
||||
// TODO: if locking the mutex for each check proves to be a performance problem,
|
||||
// add a flag of type atomic_int32_t to class TextTrieMap, and use only
|
||||
// the ICU atomic safe functions for assigning and testing.
|
||||
// Don't test the pointer fLazyContents.
|
||||
// Don't do unless it's really required.
|
||||
Mutex lock(&TextTrieMutex);
|
||||
if (fLazyContents != NULL) {
|
||||
TextTrieMap *nonConstThis = const_cast<TextTrieMap *>(this);
|
||||
nonConstThis->buildTrie(status);
|
||||
}
|
||||
}
|
||||
if (fNodes == NULL) {
|
||||
return;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "unicode/ustring.h"
|
||||
#include "unicode/utf16.h"
|
||||
#include "normalizer2impl.h"
|
||||
#include "uassert.h"
|
||||
#include "ucol_bld.h"
|
||||
#include "ucol_elm.h"
|
||||
#include "ucol_cnt.h"
|
||||
|
@ -41,6 +42,7 @@
|
|||
|
||||
static const InverseUCATableHeader* _staticInvUCA = NULL;
|
||||
static UDataMemory* invUCA_DATA_MEM = NULL;
|
||||
static UInitOnce gStaticInvUCAInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
U_CDECL_BEGIN
|
||||
static UBool U_CALLCONV
|
||||
|
@ -1330,61 +1332,48 @@ ucol_bld_cleanup(void)
|
|||
udata_close(invUCA_DATA_MEM);
|
||||
invUCA_DATA_MEM = NULL;
|
||||
_staticInvUCA = NULL;
|
||||
gStaticInvUCAInitOnce.reset();
|
||||
return TRUE;
|
||||
}
|
||||
U_CDECL_END
|
||||
|
||||
static void U_CALLCONV initInverseUCA(UErrorCode &status) {
|
||||
U_ASSERT(invUCA_DATA_MEM == NULL);
|
||||
U_ASSERT(_staticInvUCA == NULL);
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_UCOL_BLD, ucol_bld_cleanup);
|
||||
InverseUCATableHeader *newInvUCA = NULL;
|
||||
UDataMemory *result = udata_openChoice(U_ICUDATA_COLL, INVC_DATA_TYPE, INVC_DATA_NAME, isAcceptableInvUCA, NULL, &status);
|
||||
|
||||
if(U_FAILURE(status)) {
|
||||
if (result) {
|
||||
udata_close(result);
|
||||
}
|
||||
// This is not needed, as we are talking about
|
||||
// memory we got from UData
|
||||
//uprv_free(newInvUCA);
|
||||
return;
|
||||
}
|
||||
|
||||
if(result != NULL) { /* It looks like sometimes we can fail to find the data file */
|
||||
newInvUCA = (InverseUCATableHeader *)udata_getMemory(result);
|
||||
UCollator *UCA = ucol_initUCA(&status);
|
||||
// UCA versions of UCA and inverse UCA should match
|
||||
if(uprv_memcmp(newInvUCA->UCAVersion, UCA->image->UCAVersion, sizeof(UVersionInfo)) != 0) {
|
||||
status = U_INVALID_FORMAT_ERROR;
|
||||
udata_close(result);
|
||||
return;
|
||||
}
|
||||
|
||||
invUCA_DATA_MEM = result;
|
||||
_staticInvUCA = newInvUCA;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
U_CAPI const InverseUCATableHeader * U_EXPORT2
|
||||
ucol_initInverseUCA(UErrorCode *status)
|
||||
{
|
||||
if(U_FAILURE(*status)) return NULL;
|
||||
|
||||
UBool needsInit;
|
||||
UMTX_CHECK(NULL, (_staticInvUCA == NULL), needsInit);
|
||||
|
||||
if(needsInit) {
|
||||
InverseUCATableHeader *newInvUCA = NULL;
|
||||
UDataMemory *result = udata_openChoice(U_ICUDATA_COLL, INVC_DATA_TYPE, INVC_DATA_NAME, isAcceptableInvUCA, NULL, status);
|
||||
|
||||
if(U_FAILURE(*status)) {
|
||||
if (result) {
|
||||
udata_close(result);
|
||||
}
|
||||
// This is not needed, as we are talking about
|
||||
// memory we got from UData
|
||||
//uprv_free(newInvUCA);
|
||||
}
|
||||
|
||||
if(result != NULL) { /* It looks like sometimes we can fail to find the data file */
|
||||
newInvUCA = (InverseUCATableHeader *)udata_getMemory(result);
|
||||
UCollator *UCA = ucol_initUCA(status);
|
||||
// UCA versions of UCA and inverse UCA should match
|
||||
if(uprv_memcmp(newInvUCA->UCAVersion, UCA->image->UCAVersion, sizeof(UVersionInfo)) != 0) {
|
||||
*status = U_INVALID_FORMAT_ERROR;
|
||||
udata_close(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
umtx_lock(NULL);
|
||||
if(_staticInvUCA == NULL) {
|
||||
invUCA_DATA_MEM = result;
|
||||
_staticInvUCA = newInvUCA;
|
||||
result = NULL;
|
||||
newInvUCA = NULL;
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
|
||||
if(newInvUCA != NULL) {
|
||||
udata_close(result);
|
||||
// This is not needed, as we are talking about
|
||||
// memory we got from UData
|
||||
//uprv_free(newInvUCA);
|
||||
}
|
||||
else {
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_UCOL_BLD, ucol_bld_cleanup);
|
||||
}
|
||||
}
|
||||
}
|
||||
umtx_initOnce(gStaticInvUCAInitOnce, &initInverseUCA, *status);
|
||||
return _staticInvUCA;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "putilimp.h"
|
||||
#include "utracimp.h"
|
||||
#include "cmemory.h"
|
||||
#include "uassert.h"
|
||||
#include "uenumimp.h"
|
||||
#include "ulist.h"
|
||||
|
||||
|
@ -54,6 +55,7 @@ static void ucol_setReorderCodesFromParser(UCollator *coll, UColTokenParser *par
|
|||
// static UCA. There is only one. Collators don't use it.
|
||||
// It is referenced only in ucol_initUCA and ucol_cleanup
|
||||
static UCollator* _staticUCA = NULL;
|
||||
static UInitOnce gStaticUCAInitOnce = U_INITONCE_INITIALIZER;
|
||||
// static pointer to udata memory. Inited in ucol_initUCA
|
||||
// used for cleanup in ucol_cleanup
|
||||
static UDataMemory* UCA_DATA_MEM = NULL;
|
||||
|
@ -70,6 +72,7 @@ ucol_res_cleanup(void)
|
|||
ucol_close(_staticUCA);
|
||||
_staticUCA = NULL;
|
||||
}
|
||||
gStaticUCAInitOnce.reset();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -106,47 +109,35 @@ isAcceptableUCA(void * /*context*/,
|
|||
}
|
||||
U_CDECL_END
|
||||
|
||||
static void U_CALLCONV ucol_initStaticUCA(UErrorCode &status) {
|
||||
U_ASSERT(_staticUCA == NULL);
|
||||
U_ASSERT(UCA_DATA_MEM == NULL);
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_UCOL_RES, ucol_res_cleanup);
|
||||
|
||||
UDataMemory *result = udata_openChoice(U_ICUDATA_COLL, UCA_DATA_TYPE, UCA_DATA_NAME, isAcceptableUCA, NULL, &status);
|
||||
if(U_FAILURE(status)){
|
||||
udata_close(result);
|
||||
return;
|
||||
}
|
||||
|
||||
_staticUCA = ucol_initCollator((const UCATableHeader *)udata_getMemory(result), NULL, NULL, &status);
|
||||
if(U_SUCCESS(status)){
|
||||
// Initalize variables for implicit generation
|
||||
uprv_uca_initImplicitConstants(&status);
|
||||
UCA_DATA_MEM = result;
|
||||
|
||||
}else{
|
||||
ucol_close(_staticUCA);
|
||||
_staticUCA = NULL;
|
||||
udata_close(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* do not close UCA returned by ucol_initUCA! */
|
||||
UCollator *
|
||||
ucol_initUCA(UErrorCode *status) {
|
||||
if(U_FAILURE(*status)) {
|
||||
return NULL;
|
||||
}
|
||||
UBool needsInit;
|
||||
UMTX_CHECK(NULL, (_staticUCA == NULL), needsInit);
|
||||
|
||||
if(needsInit) {
|
||||
UDataMemory *result = udata_openChoice(U_ICUDATA_COLL, UCA_DATA_TYPE, UCA_DATA_NAME, isAcceptableUCA, NULL, status);
|
||||
|
||||
if(U_SUCCESS(*status)){
|
||||
UCollator *newUCA = ucol_initCollator((const UCATableHeader *)udata_getMemory(result), NULL, NULL, status);
|
||||
if(U_SUCCESS(*status)){
|
||||
// Initalize variables for implicit generation
|
||||
uprv_uca_initImplicitConstants(status);
|
||||
|
||||
umtx_lock(NULL);
|
||||
if(_staticUCA == NULL) {
|
||||
UCA_DATA_MEM = result;
|
||||
_staticUCA = newUCA;
|
||||
newUCA = NULL;
|
||||
result = NULL;
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_UCOL_RES, ucol_res_cleanup);
|
||||
if(newUCA != NULL) {
|
||||
ucol_close(newUCA);
|
||||
udata_close(result);
|
||||
}
|
||||
}else{
|
||||
ucol_close(newUCA);
|
||||
udata_close(result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
udata_close(result);
|
||||
}
|
||||
}
|
||||
umtx_initOnce(gStaticUCAInitOnce, &ucol_initStaticUCA, *status);
|
||||
return _staticUCA;
|
||||
}
|
||||
|
||||
|
@ -155,6 +146,7 @@ ucol_forgetUCA(void)
|
|||
{
|
||||
_staticUCA = NULL;
|
||||
UCA_DATA_MEM = NULL;
|
||||
gStaticUCAInitOnce.reset();
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
|
|
@ -99,10 +99,8 @@ static const UChar CHOICE_FORMAT_MARK = 0x003D; // Equals sign
|
|||
static const UChar EUR_STR[] = {0x0045,0x0055,0x0052,0};
|
||||
|
||||
// ISO codes mapping table
|
||||
static UHashtable* gIsoCodes = NULL;
|
||||
static UBool gIsoCodesInitialized = FALSE;
|
||||
|
||||
static UMutex gIsoCodesLock = U_MUTEX_INITIALIZER;
|
||||
static const UHashtable* gIsoCodes = NULL;
|
||||
static UInitOnce gIsoCodesInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Code
|
||||
|
@ -114,11 +112,10 @@ static UBool U_CALLCONV
|
|||
isoCodes_cleanup(void)
|
||||
{
|
||||
if (gIsoCodes != NULL) {
|
||||
uhash_close(gIsoCodes);
|
||||
uhash_close(const_cast<UHashtable *>(gIsoCodes));
|
||||
gIsoCodes = NULL;
|
||||
}
|
||||
gIsoCodesInitialized = FALSE;
|
||||
|
||||
gIsoCodesInitOnce.reset();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1227,6 +1224,8 @@ static CurrencyNameCacheEntry* currCache[CURRENCY_NAME_CACHE_NUM] = {NULL};
|
|||
// It is a simple round-robin replacement strategy.
|
||||
static int8_t currentCacheEntryIndex = 0;
|
||||
|
||||
static UMutex gCurrencyCacheMutex = U_MUTEX_INITIALIZER;
|
||||
|
||||
// Cache deletion
|
||||
static void
|
||||
deleteCurrencyNames(CurrencyNameStruct* currencyNames, int32_t count) {
|
||||
|
@ -1280,9 +1279,9 @@ uprv_parseCurrency(const char* locale,
|
|||
CurrencyNameStruct* currencySymbols = NULL;
|
||||
CurrencyNameCacheEntry* cacheEntry = NULL;
|
||||
|
||||
umtx_lock(NULL);
|
||||
umtx_lock(&gCurrencyCacheMutex);
|
||||
// in order to handle racing correctly,
|
||||
// not putting 'search' in a separate function and using UMTX.
|
||||
// not putting 'search' in a separate function.
|
||||
int8_t found = -1;
|
||||
for (int8_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) {
|
||||
if (currCache[i]!= NULL &&
|
||||
|
@ -1299,13 +1298,13 @@ uprv_parseCurrency(const char* locale,
|
|||
total_currency_symbol_count = cacheEntry->totalCurrencySymbolCount;
|
||||
++(cacheEntry->refCount);
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
umtx_unlock(&gCurrencyCacheMutex);
|
||||
if (found == -1) {
|
||||
collectCurrencyNames(locale, ¤cyNames, &total_currency_name_count, ¤cySymbols, &total_currency_symbol_count, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
return;
|
||||
}
|
||||
umtx_lock(NULL);
|
||||
umtx_lock(&gCurrencyCacheMutex);
|
||||
// check again.
|
||||
int8_t found = -1;
|
||||
for (int8_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) {
|
||||
|
@ -1350,7 +1349,7 @@ uprv_parseCurrency(const char* locale,
|
|||
total_currency_symbol_count = cacheEntry->totalCurrencySymbolCount;
|
||||
++(cacheEntry->refCount);
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
umtx_unlock(&gCurrencyCacheMutex);
|
||||
}
|
||||
|
||||
int32_t start = pos.getIndex();
|
||||
|
@ -1394,12 +1393,12 @@ uprv_parseCurrency(const char* locale,
|
|||
}
|
||||
|
||||
// decrease reference count
|
||||
umtx_lock(NULL);
|
||||
umtx_lock(&gCurrencyCacheMutex);
|
||||
--(cacheEntry->refCount);
|
||||
if (cacheEntry->refCount == 0) { // remove
|
||||
deleteCacheEntry(cacheEntry);
|
||||
}
|
||||
umtx_unlock(NULL);
|
||||
umtx_unlock(&gCurrencyCacheMutex);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1842,7 +1841,7 @@ ucurr_closeCurrencyList(UEnumeration *enumerator) {
|
|||
}
|
||||
|
||||
static void U_CALLCONV
|
||||
ucurr_createCurrencyList(UErrorCode* status){
|
||||
ucurr_createCurrencyList(UHashtable *isoCodes, UErrorCode* status){
|
||||
UErrorCode localStatus = U_ZERO_ERROR;
|
||||
|
||||
// Look up the CurrencyMap element in the root bundle.
|
||||
|
@ -1908,7 +1907,7 @@ ucurr_createCurrencyList(UErrorCode* status){
|
|||
entry->to = toDate;
|
||||
|
||||
localStatus = U_ZERO_ERROR;
|
||||
uhash_put(gIsoCodes, (UChar *)isoCode, entry, &localStatus);
|
||||
uhash_put(isoCodes, (UChar *)isoCode, entry, &localStatus);
|
||||
}
|
||||
} else {
|
||||
*status = localStatus;
|
||||
|
@ -1933,36 +1932,35 @@ static const UEnumeration gEnumCurrencyList = {
|
|||
};
|
||||
U_CDECL_END
|
||||
|
||||
|
||||
static void U_CALLCONV initIsoCodes(UErrorCode &status) {
|
||||
U_ASSERT(gIsoCodes == NULL);
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cleanup);
|
||||
|
||||
UHashtable *isoCodes = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
uhash_setValueDeleter(isoCodes, deleteIsoCodeEntry);
|
||||
|
||||
ucurr_createCurrencyList(isoCodes, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
uhash_close(isoCodes);
|
||||
return;
|
||||
}
|
||||
gIsoCodes = isoCodes; // Note: gIsoCodes is const. Once set up here it is never altered,
|
||||
// and read only access is safe without synchronization.
|
||||
}
|
||||
|
||||
|
||||
U_CAPI UBool U_EXPORT2
|
||||
ucurr_isAvailable(const UChar* isoCode, UDate from, UDate to, UErrorCode* eErrorCode) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&gIsoCodesLock, gIsoCodesInitialized, initialized);
|
||||
|
||||
if (!initialized) {
|
||||
umtx_lock(&gIsoCodesLock);
|
||||
gIsoCodes = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
umtx_unlock(&gIsoCodesLock);
|
||||
return FALSE;
|
||||
}
|
||||
uhash_setValueDeleter(gIsoCodes, deleteIsoCodeEntry);
|
||||
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cleanup);
|
||||
ucurr_createCurrencyList(&status);
|
||||
if (U_FAILURE(status)) {
|
||||
umtx_unlock(&gIsoCodesLock);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gIsoCodesInitialized = TRUE;
|
||||
umtx_unlock(&gIsoCodesLock);
|
||||
umtx_initOnce(gIsoCodesInitOnce, &initIsoCodes, *eErrorCode);
|
||||
if (U_FAILURE(*eErrorCode)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
umtx_lock(&gIsoCodesLock);
|
||||
IsoCodeEntry* result = (IsoCodeEntry *) uhash_get(gIsoCodes, isoCode);
|
||||
umtx_unlock(&gIsoCodesLock);
|
||||
|
||||
if (result == NULL) {
|
||||
return FALSE;
|
||||
} else if (from > to) {
|
||||
|
@ -1971,7 +1969,6 @@ ucurr_isAvailable(const UChar* isoCode, UDate from, UDate to, UErrorCode* eError
|
|||
} else if ((from > result->to) || (to < result->from)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ class CurrencyPluralInfo;
|
|||
class Hashtable;
|
||||
class UnicodeSet;
|
||||
class FieldPositionHandler;
|
||||
class DecimalFormatStaticSets;
|
||||
|
||||
// explicit template instantiation. see digitlst.h
|
||||
#if defined (_MSC_VER)
|
||||
|
@ -1882,15 +1883,15 @@ private:
|
|||
int32_t precision() const;
|
||||
|
||||
/**
|
||||
* Initialize all fields of a new DecimalFormatter.
|
||||
* Initialize all fields of a new DecimalFormatter to a safe default value.
|
||||
* Common code for use by constructors.
|
||||
*/
|
||||
void init(UErrorCode& status);
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Do real work of constructing a new DecimalFormat.
|
||||
*/
|
||||
void construct(UErrorCode& status,
|
||||
void construct(UErrorCode& status,
|
||||
UParseError& parseErr,
|
||||
const UnicodeString* pattern = 0,
|
||||
DecimalFormatSymbols* symbolsToAdopt = 0
|
||||
|
@ -2295,6 +2296,9 @@ private:
|
|||
UNumberFormatAttributeValue fParseAllInput;
|
||||
#endif
|
||||
|
||||
// Decimal Format Static Sets singleton.
|
||||
const DecimalFormatStaticSets *fStaticSets;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -29,6 +29,9 @@ class GenderInfoTest;
|
|||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
// Forward Declaration
|
||||
void GenderInfo_initCache(UErrorCode &status);
|
||||
|
||||
/**
|
||||
* GenderInfo computes the gender of a list as a whole given the gender of
|
||||
* each element.
|
||||
|
@ -96,7 +99,9 @@ private:
|
|||
static const GenderInfo* getMaleTaintsInstance();
|
||||
|
||||
static const GenderInfo* loadInstance(const Locale& locale, UErrorCode& status);
|
||||
|
||||
friend class ::GenderInfoTest;
|
||||
friend void GenderInfo_initCache(UErrorCode &status);
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -767,53 +767,6 @@ public:
|
|||
* @return the beginning year of the default century
|
||||
*/
|
||||
virtual int32_t defaultCenturyStartYear() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* The system maintains a static default century start date. This is initialized
|
||||
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
|
||||
* indicate an uninitialized state. Once the system default century date and year
|
||||
* are set, they do not change.
|
||||
*/
|
||||
static UDate fgSystemDefaultCenturyStart;
|
||||
|
||||
/**
|
||||
* See documentation for systemDefaultCenturyStart.
|
||||
*/
|
||||
static int32_t fgSystemDefaultCenturyStartYear;
|
||||
|
||||
/**
|
||||
* Default value that indicates the defaultCenturyStartYear is unitialized
|
||||
*/
|
||||
static const int32_t fgSystemDefaultCenturyYear;
|
||||
|
||||
/**
|
||||
* Default value that indicates the UDate of the beginning of the system default century
|
||||
*/
|
||||
static const UDate fgSystemDefaultCentury;
|
||||
|
||||
/**
|
||||
* Returns the beginning date of the 100-year window that dates with 2-digit years
|
||||
* are considered to fall within.
|
||||
* @return the beginning date of the 100-year window that dates with 2-digit years
|
||||
* are considered to fall within.
|
||||
*/
|
||||
UDate internalGetDefaultCenturyStart(void) const;
|
||||
|
||||
/**
|
||||
* Returns the first year of the 100-year window that dates with 2-digit years
|
||||
* are considered to fall within.
|
||||
* @return the first year of the 100-year window that dates with 2-digit years
|
||||
* are considered to fall within.
|
||||
*/
|
||||
int32_t internalGetDefaultCenturyStartYear(void) const;
|
||||
|
||||
/**
|
||||
* Initializes the 100-year window that dates with 2-digit years are considered
|
||||
* to fall within so that its start date is 80 years before the current time.
|
||||
*/
|
||||
static void initializeSystemDefaultCentury(void);
|
||||
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -291,7 +291,11 @@ public:
|
|||
* Sets the default time zone (i.e., what's returned by createDefault()) to be the
|
||||
* specified time zone. If NULL is specified for the time zone, the default time
|
||||
* zone is set to the default host time zone. This call adopts the TimeZone object
|
||||
* passed in; the clent is no longer responsible for deleting it.
|
||||
* passed in; the client is no longer responsible for deleting it.
|
||||
*
|
||||
* <p>This function is not thread safe. It is an error for multiple threads
|
||||
* to concurrently attempt to set the default time zone, or for any thread
|
||||
* to attempt to reference the default zone while another thread is setting it.
|
||||
*
|
||||
* @param zone A pointer to the new TimeZone object to use as the default.
|
||||
* @stable ICU 2.0
|
||||
|
@ -303,6 +307,8 @@ public:
|
|||
* Same as adoptDefault(), except that the TimeZone object passed in is NOT adopted;
|
||||
* the caller remains responsible for deleting it.
|
||||
*
|
||||
* <p>See the thread safety note under adoptDefault().
|
||||
*
|
||||
* @param zone The given timezone.
|
||||
* @system
|
||||
* @stable ICU 2.0
|
||||
|
@ -863,15 +869,18 @@ private:
|
|||
*/
|
||||
static const UChar* getRegion(const UnicodeString& id);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns the region code associated with the given zone,
|
||||
* or NULL if the zone is not known.
|
||||
* @param id zone id string
|
||||
* @param status Status parameter
|
||||
* @return the region associated with the given zone
|
||||
* @internal
|
||||
*/
|
||||
static const UChar* getRegion(const UnicodeString& id, UErrorCode& status);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Parses the given custom time zone identifier
|
||||
* @param id id A string of the form GMT[+-]hh:mm, GMT[+-]hhmm, or
|
||||
|
@ -910,24 +919,6 @@ private:
|
|||
static UnicodeString& formatCustomID(int32_t hour, int32_t min, int32_t sec,
|
||||
UBool negative, UnicodeString& id);
|
||||
|
||||
/**
|
||||
* Responsible for setting up DEFAULT_ZONE. Uses routines in TPlatformUtilities
|
||||
* (i.e., platform-specific calls) to get the current system time zone. Failing
|
||||
* that, uses the platform-specific default time zone. Failing that, uses GMT.
|
||||
*/
|
||||
static void initDefault(void);
|
||||
|
||||
// See source file for documentation
|
||||
/**
|
||||
* Lookup the given name in our system zone table. If found,
|
||||
* instantiate a new zone of that name and return it. If not
|
||||
* found, return 0.
|
||||
* @param name tthe given name of a system time zone.
|
||||
* @return the TimeZone indicated by the 'name'.
|
||||
*/
|
||||
static TimeZone* createSystemTimeZone(const UnicodeString& name);
|
||||
static TimeZone* createSystemTimeZone(const UnicodeString& name, UErrorCode& ec);
|
||||
|
||||
UnicodeString fID; // this time zone's ID
|
||||
|
||||
friend class TZEnumeration;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2004-2012, International Business Machines
|
||||
* Copyright (C) 2004-2013, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
* file name: regex.cpp
|
||||
* file name: uregex.cpp
|
||||
*/
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
@ -35,7 +35,7 @@ public:
|
|||
~RegularExpression();
|
||||
int32_t fMagic;
|
||||
RegexPattern *fPat;
|
||||
int32_t *fPatRefCount;
|
||||
atomic_int32_t *fPatRefCount;
|
||||
UChar *fPatString;
|
||||
int32_t fPatStringLen;
|
||||
RegexMatcher *fMatcher;
|
||||
|
@ -65,7 +65,7 @@ RegularExpression::~RegularExpression() {
|
|||
if (fPatRefCount!=NULL && umtx_atomic_dec(fPatRefCount)==0) {
|
||||
delete fPat;
|
||||
uprv_free(fPatString);
|
||||
uprv_free(fPatRefCount);
|
||||
uprv_free((void *)fPatRefCount);
|
||||
}
|
||||
if (fOwnsText && fText!=NULL) {
|
||||
uprv_free((void *)fText);
|
||||
|
@ -122,13 +122,13 @@ uregex_open( const UChar *pattern,
|
|||
actualPatLen = u_strlen(pattern);
|
||||
}
|
||||
|
||||
RegularExpression *re = new RegularExpression;
|
||||
int32_t *refC = (int32_t *)uprv_malloc(sizeof(int32_t));
|
||||
RegularExpression *re = new RegularExpression;
|
||||
atomic_int32_t *refC = (atomic_int32_t *)uprv_malloc(sizeof(int32_t));
|
||||
UChar *patBuf = (UChar *)uprv_malloc(sizeof(UChar)*(actualPatLen+1));
|
||||
if (re == NULL || refC == NULL || patBuf == NULL) {
|
||||
*status = U_MEMORY_ALLOCATION_ERROR;
|
||||
delete re;
|
||||
uprv_free(refC);
|
||||
uprv_free((void *)refC);
|
||||
uprv_free(patBuf);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -207,12 +207,12 @@ uregex_openUText(UText *pattern,
|
|||
UErrorCode lengthStatus = U_ZERO_ERROR;
|
||||
int32_t pattern16Length = utext_extract(pattern, 0, patternNativeLength, NULL, 0, &lengthStatus);
|
||||
|
||||
int32_t *refC = (int32_t *)uprv_malloc(sizeof(int32_t));
|
||||
atomic_int32_t *refC = (atomic_int32_t *)uprv_malloc(sizeof(int32_t));
|
||||
UChar *patBuf = (UChar *)uprv_malloc(sizeof(UChar)*(pattern16Length+1));
|
||||
if (re == NULL || refC == NULL || patBuf == NULL) {
|
||||
*status = U_MEMORY_ALLOCATION_ERROR;
|
||||
delete re;
|
||||
uprv_free(refC);
|
||||
uprv_free((void *)refC);
|
||||
uprv_free(patBuf);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -242,7 +242,7 @@ class SpoofData: public UMemory {
|
|||
// we are done.
|
||||
|
||||
uint32_t fMemLimit; // Limit of available raw data space
|
||||
int32_t fRefCount;
|
||||
atomic_int32_t fRefCount;
|
||||
|
||||
// Confusable data
|
||||
int32_t *fCFUKeys;
|
||||
|
|
|
@ -31,21 +31,21 @@ static UMutex gZoneMetaLock = U_MUTEX_INITIALIZER;
|
|||
|
||||
// CLDR Canonical ID mapping table
|
||||
static UHashtable *gCanonicalIDCache = NULL;
|
||||
static UBool gCanonicalIDCacheInitialized = FALSE;
|
||||
static UInitOnce gCanonicalIDCacheInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
// Metazone mapping table
|
||||
static UHashtable *gOlsonToMeta = NULL;
|
||||
static UBool gOlsonToMetaInitialized = FALSE;
|
||||
static UInitOnce gOlsonToMetaInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
// Available metazone IDs vector and table
|
||||
static icu::UVector *gMetaZoneIDs = NULL;
|
||||
static UHashtable *gMetaZoneIDTable = NULL;
|
||||
static UBool gMetaZoneIDsInitialized = FALSE;
|
||||
static UInitOnce gMetaZoneIDsInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
// Country info vectors
|
||||
static icu::UVector *gSingleZoneCountries = NULL;
|
||||
static icu::UVector *gMultiZonesCountries = NULL;
|
||||
static UBool gCountryInfoVectorsInitialized = FALSE;
|
||||
static UInitOnce gCountryInfoVectorsInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
U_CDECL_BEGIN
|
||||
|
||||
|
@ -58,25 +58,29 @@ static UBool U_CALLCONV zoneMeta_cleanup(void)
|
|||
uhash_close(gCanonicalIDCache);
|
||||
gCanonicalIDCache = NULL;
|
||||
}
|
||||
gCanonicalIDCacheInitialized = FALSE;
|
||||
gCanonicalIDCacheInitOnce.reset();
|
||||
|
||||
if (gOlsonToMeta != NULL) {
|
||||
uhash_close(gOlsonToMeta);
|
||||
gOlsonToMeta = NULL;
|
||||
}
|
||||
gOlsonToMetaInitialized = FALSE;
|
||||
gOlsonToMetaInitOnce.reset();
|
||||
|
||||
if (gMetaZoneIDTable != NULL) {
|
||||
uhash_close(gMetaZoneIDTable);
|
||||
gMetaZoneIDTable = NULL;
|
||||
}
|
||||
// delete after closing gMetaZoneIDTable, because it holds
|
||||
// value objects held by the hashtable
|
||||
delete gMetaZoneIDs;
|
||||
gMetaZoneIDsInitialized = FALSE;
|
||||
gMetaZoneIDs = NULL;
|
||||
gMetaZoneIDsInitOnce.reset();
|
||||
|
||||
delete gSingleZoneCountries;
|
||||
gSingleZoneCountries = NULL;
|
||||
delete gMultiZonesCountries;
|
||||
gCountryInfoVectorsInitialized = FALSE;
|
||||
gMultiZonesCountries = NULL;
|
||||
gCountryInfoVectorsInitOnce.reset();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -212,6 +216,19 @@ parseDate (const UChar *text, UErrorCode &status) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void U_CALLCONV initCanonicalIDCache(UErrorCode &status) {
|
||||
gCanonicalIDCache = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
|
||||
if (gCanonicalIDCache == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
gCanonicalIDCache = NULL;
|
||||
}
|
||||
// No key/value deleters - keys/values are from a resource bundle
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
|
||||
}
|
||||
|
||||
|
||||
const UChar* U_EXPORT2
|
||||
ZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) {
|
||||
|
@ -225,27 +242,9 @@ ZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UErrorCode& status) {
|
|||
}
|
||||
|
||||
// Checking the cached results
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&gZoneMetaLock, gCanonicalIDCacheInitialized, initialized);
|
||||
if (!initialized) {
|
||||
// Create empty hashtable
|
||||
umtx_lock(&gZoneMetaLock);
|
||||
{
|
||||
if (!gCanonicalIDCacheInitialized) {
|
||||
gCanonicalIDCache = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
|
||||
if (gCanonicalIDCache == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
gCanonicalIDCache = NULL;
|
||||
return NULL;
|
||||
}
|
||||
// No key/value deleters - keys/values are from a resource bundle
|
||||
gCanonicalIDCacheInitialized = TRUE;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
|
||||
}
|
||||
}
|
||||
umtx_unlock(&gZoneMetaLock);
|
||||
umtx_initOnce(gCanonicalIDCacheInitOnce, &initCanonicalIDCache, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const UChar *canonicalID = NULL;
|
||||
|
@ -393,6 +392,28 @@ ZoneMeta::getCanonicalCLDRID(const TimeZone& tz) {
|
|||
return getCanonicalCLDRID(tz.getID(tzID), status);
|
||||
}
|
||||
|
||||
static void U_CALLCONV countryInfoVectorsInit(UErrorCode &status) {
|
||||
// Create empty vectors
|
||||
// No deleters for these UVectors, it's a reference to a resource bundle string.
|
||||
gSingleZoneCountries = new UVector(NULL, uhash_compareUChars, status);
|
||||
if (gSingleZoneCountries == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
gMultiZonesCountries = new UVector(NULL, uhash_compareUChars, status);
|
||||
if (gMultiZonesCountries == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
delete gSingleZoneCountries;
|
||||
delete gMultiZonesCountries;
|
||||
gSingleZoneCountries = NULL;
|
||||
gMultiZonesCountries = NULL;
|
||||
}
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
|
||||
}
|
||||
|
||||
|
||||
UnicodeString& U_EXPORT2
|
||||
ZoneMeta::getCanonicalCountry(const UnicodeString &tzid, UnicodeString &country, UBool *isPrimary /* = NULL */) {
|
||||
if (isPrimary != NULL) {
|
||||
|
@ -412,39 +433,9 @@ ZoneMeta::getCanonicalCountry(const UnicodeString &tzid, UnicodeString &country,
|
|||
|
||||
// Checking the cached results
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&gZoneMetaLock, gCountryInfoVectorsInitialized, initialized);
|
||||
if (!initialized) {
|
||||
// Create empty vectors
|
||||
umtx_lock(&gZoneMetaLock);
|
||||
{
|
||||
if (!gCountryInfoVectorsInitialized) {
|
||||
// No deleters for these UVectors, it's a reference to a resource bundle string.
|
||||
gSingleZoneCountries = new UVector(NULL, uhash_compareUChars, status);
|
||||
if (gSingleZoneCountries == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
gMultiZonesCountries = new UVector(NULL, uhash_compareUChars, status);
|
||||
if (gMultiZonesCountries == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
|
||||
if (U_SUCCESS(status)) {
|
||||
gCountryInfoVectorsInitialized = TRUE;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
|
||||
} else {
|
||||
delete gSingleZoneCountries;
|
||||
delete gMultiZonesCountries;
|
||||
}
|
||||
}
|
||||
}
|
||||
umtx_unlock(&gZoneMetaLock);
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
return country;
|
||||
}
|
||||
U_ASSERT(gSingleZoneCountries != NULL);
|
||||
U_ASSERT(gMultiZonesCountries != NULL);
|
||||
umtx_initOnce(gCountryInfoVectorsInitOnce, &countryInfoVectorsInit, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return country;
|
||||
}
|
||||
|
||||
// Check if it was already cached
|
||||
|
@ -546,6 +537,19 @@ ZoneMeta::getMetazoneID(const UnicodeString &tzid, UDate date, UnicodeString &re
|
|||
return result;
|
||||
}
|
||||
|
||||
static void U_CALLCONV olsonToMetaInit(UErrorCode &status) {
|
||||
U_ASSERT(gOlsonToMeta == NULL);
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
|
||||
gOlsonToMeta = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
gOlsonToMeta = NULL;
|
||||
} else {
|
||||
uhash_setKeyDeleter(gOlsonToMeta, deleteUCharString);
|
||||
uhash_setValueDeleter(gOlsonToMeta, deleteUVector);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const UVector* U_EXPORT2
|
||||
ZoneMeta::getMetazoneMappings(const UnicodeString &tzid) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
@ -555,31 +559,9 @@ ZoneMeta::getMetazoneMappings(const UnicodeString &tzid) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&gZoneMetaLock, gOlsonToMetaInitialized, initialized);
|
||||
if (!initialized) {
|
||||
UHashtable *tmpOlsonToMeta = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
uhash_setKeyDeleter(tmpOlsonToMeta, deleteUCharString);
|
||||
uhash_setValueDeleter(tmpOlsonToMeta, deleteUVector);
|
||||
|
||||
umtx_lock(&gZoneMetaLock);
|
||||
{
|
||||
if (!gOlsonToMetaInitialized) {
|
||||
gOlsonToMeta = tmpOlsonToMeta;
|
||||
tmpOlsonToMeta = NULL;
|
||||
gOlsonToMetaInitialized = TRUE;
|
||||
}
|
||||
}
|
||||
umtx_unlock(&gZoneMetaLock);
|
||||
|
||||
// OK to call the following multiple times with the same function
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
|
||||
if (tmpOlsonToMeta != NULL) {
|
||||
uhash_close(tmpOlsonToMeta);
|
||||
}
|
||||
umtx_initOnce(gOlsonToMetaInitOnce, &olsonToMetaInit, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the mapping from cache
|
||||
|
@ -773,86 +755,79 @@ ZoneMeta::getZoneIdByMetazone(const UnicodeString &mzid, const UnicodeString &re
|
|||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
ZoneMeta::initAvailableMetaZoneIDs () {
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&gZoneMetaLock, gMetaZoneIDsInitialized, initialized);
|
||||
if (!initialized) {
|
||||
umtx_lock(&gZoneMetaLock);
|
||||
{
|
||||
if (!gMetaZoneIDsInitialized) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UHashtable *metaZoneIDTable = uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, &status);
|
||||
uhash_setKeyDeleter(metaZoneIDTable, uprv_deleteUObject);
|
||||
// No valueDeleter, because the vector maintain the value objects
|
||||
UVector *metaZoneIDs = NULL;
|
||||
if (U_SUCCESS(status)) {
|
||||
metaZoneIDs = new UVector(NULL, uhash_compareUChars, status);
|
||||
if (metaZoneIDs == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
} else {
|
||||
uhash_close(metaZoneIDTable);
|
||||
}
|
||||
if (U_SUCCESS(status)) {
|
||||
U_ASSERT(metaZoneIDs != NULL);
|
||||
metaZoneIDs->setDeleter(uprv_free);
|
||||
static void U_CALLCONV initAvailableMetaZoneIDs () {
|
||||
U_ASSERT(gMetaZoneIDs == NULL);
|
||||
U_ASSERT(gMetaZoneIDTable == NULL);
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
|
||||
|
||||
UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status);
|
||||
UResourceBundle *bundle = ures_getByKey(rb, gMapTimezonesTag, NULL, &status);
|
||||
UResourceBundle res;
|
||||
ures_initStackObject(&res);
|
||||
while (U_SUCCESS(status) && ures_hasNext(bundle)) {
|
||||
ures_getNextResource(bundle, &res, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
break;
|
||||
}
|
||||
const char *mzID = ures_getKey(&res);
|
||||
int32_t len = uprv_strlen(mzID);
|
||||
UChar *uMzID = (UChar*)uprv_malloc(sizeof(UChar) * (len + 1));
|
||||
if (uMzID == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
break;
|
||||
}
|
||||
u_charsToUChars(mzID, uMzID, len);
|
||||
uMzID[len] = 0;
|
||||
UnicodeString *usMzID = new UnicodeString(uMzID);
|
||||
if (uhash_get(metaZoneIDTable, usMzID) == NULL) {
|
||||
metaZoneIDs->addElement((void *)uMzID, status);
|
||||
uhash_put(metaZoneIDTable, (void *)usMzID, (void *)uMzID, &status);
|
||||
} else {
|
||||
uprv_free(uMzID);
|
||||
delete usMzID;
|
||||
}
|
||||
}
|
||||
if (U_SUCCESS(status)) {
|
||||
gMetaZoneIDs = metaZoneIDs;
|
||||
gMetaZoneIDTable = metaZoneIDTable;
|
||||
gMetaZoneIDsInitialized = TRUE;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
|
||||
} else {
|
||||
uhash_close(metaZoneIDTable);
|
||||
delete metaZoneIDs;
|
||||
}
|
||||
ures_close(&res);
|
||||
ures_close(bundle);
|
||||
ures_close(rb);
|
||||
}
|
||||
}
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
gMetaZoneIDTable = uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, &status);
|
||||
if (U_FAILURE(status) || gMetaZoneIDTable == NULL) {
|
||||
gMetaZoneIDTable = NULL;
|
||||
return;
|
||||
}
|
||||
uhash_setKeyDeleter(gMetaZoneIDTable, uprv_deleteUObject);
|
||||
// No valueDeleter, because the vector maintain the value objects
|
||||
gMetaZoneIDs = new UVector(NULL, uhash_compareUChars, status);
|
||||
if (U_FAILURE(status) || gMetaZoneIDs == NULL) {
|
||||
gMetaZoneIDs = NULL;
|
||||
uhash_close(gMetaZoneIDTable);
|
||||
gMetaZoneIDTable = NULL;
|
||||
return;
|
||||
}
|
||||
gMetaZoneIDs->setDeleter(uprv_free);
|
||||
|
||||
UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status);
|
||||
UResourceBundle *bundle = ures_getByKey(rb, gMapTimezonesTag, NULL, &status);
|
||||
UResourceBundle res;
|
||||
ures_initStackObject(&res);
|
||||
while (U_SUCCESS(status) && ures_hasNext(bundle)) {
|
||||
ures_getNextResource(bundle, &res, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
break;
|
||||
}
|
||||
umtx_unlock(&gZoneMetaLock);
|
||||
const char *mzID = ures_getKey(&res);
|
||||
int32_t len = uprv_strlen(mzID);
|
||||
UChar *uMzID = (UChar*)uprv_malloc(sizeof(UChar) * (len + 1));
|
||||
if (uMzID == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
break;
|
||||
}
|
||||
u_charsToUChars(mzID, uMzID, len);
|
||||
uMzID[len] = 0;
|
||||
UnicodeString *usMzID = new UnicodeString(uMzID);
|
||||
if (uhash_get(gMetaZoneIDTable, usMzID) == NULL) {
|
||||
gMetaZoneIDs->addElement((void *)uMzID, status);
|
||||
uhash_put(gMetaZoneIDTable, (void *)usMzID, (void *)uMzID, &status);
|
||||
} else {
|
||||
uprv_free(uMzID);
|
||||
delete usMzID;
|
||||
}
|
||||
}
|
||||
ures_close(&res);
|
||||
ures_close(bundle);
|
||||
ures_close(rb);
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
uhash_close(gMetaZoneIDTable);
|
||||
delete gMetaZoneIDs;
|
||||
gMetaZoneIDTable = NULL;
|
||||
gMetaZoneIDs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const UVector*
|
||||
ZoneMeta::getAvailableMetazoneIDs() {
|
||||
initAvailableMetaZoneIDs();
|
||||
umtx_initOnce(gMetaZoneIDsInitOnce, &initAvailableMetaZoneIDs);
|
||||
return gMetaZoneIDs;
|
||||
}
|
||||
|
||||
const UChar*
|
||||
ZoneMeta::findMetaZoneID(const UnicodeString& mzid) {
|
||||
initAvailableMetaZoneIDs();
|
||||
umtx_initOnce(gMetaZoneIDsInitOnce, &initAvailableMetaZoneIDs);
|
||||
if (gMetaZoneIDTable == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return (const UChar*)uhash_get(gMetaZoneIDTable, &mzid);
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,6 @@ public:
|
|||
private:
|
||||
ZoneMeta(); // Prevent construction.
|
||||
static UVector* createMetazoneMappings(const UnicodeString &tzid);
|
||||
static void initAvailableMetaZoneIDs();
|
||||
static UnicodeString& formatCustomID(uint8_t hour, uint8_t min, uint8_t sec, UBool negative, UnicodeString& id);
|
||||
static const UChar* getShortIDFromCanonical(const UChar* canonicalID);
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue