X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/4388f060552cc537e71e957d32f35e9d75a61233..3d1f044b704633e2e541231cd17ae9ecf9ad5c7a:/icuSources/i18n/simpletz.cpp diff --git a/icuSources/i18n/simpletz.cpp b/icuSources/i18n/simpletz.cpp index f04f85f0..9321fda3 100644 --- a/icuSources/i18n/simpletz.cpp +++ b/icuSources/i18n/simpletz.cpp @@ -1,6 +1,8 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /* ******************************************************************************* - * Copyright (C) 1997-2011, International Business Machines Corporation and + * Copyright (C) 1997-2013, International Business Machines Corporation and * others. All Rights Reserved. ******************************************************************************* * @@ -21,7 +23,7 @@ ******************************************************************************** */ -#include // for 'typeid' to work +#include "utypeinfo.h" // for 'typeid' to work #include "unicode/utypes.h" @@ -31,7 +33,9 @@ #include "unicode/gregocal.h" #include "unicode/smpdtfmt.h" +#include "cmemory.h" #include "gregoimp.h" +#include "umutex.h" U_NAMESPACE_BEGIN @@ -174,7 +178,7 @@ void SimpleTimeZone::construct(int32_t rawOffsetGMT, decodeRules(status); - if (savingsDST <= 0) { + if (savingsDST == 0) { status = U_ILLEGAL_ARGUMENT_ERROR; } } @@ -506,7 +510,7 @@ SimpleTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day, void SimpleTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, - int32_t& rawOffsetGMT, int32_t& savingsDST, UErrorCode& status) /*const*/ { + int32_t& rawOffsetGMT, int32_t& savingsDST, UErrorCode& status) const { if (U_FAILURE(status)) { return; } @@ -683,7 +687,7 @@ SimpleTimeZone::setRawOffset(int32_t offsetMillis) void SimpleTimeZone::setDSTSavings(int32_t millisSavedDuringDST, UErrorCode& status) { - if (millisSavedDuringDST <= 0) { + if (millisSavedDuringDST == 0) { status = U_ILLEGAL_ARGUMENT_ERROR; } else { @@ -967,13 +971,13 @@ SimpleTimeZone::decodeEndRule(UErrorCode& status) } UBool -SimpleTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) /*const*/ { +SimpleTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const { if (!useDaylight) { return FALSE; } UErrorCode status = U_ZERO_ERROR; - initTransitionRules(status); + checkTransitionRules(status); if (U_FAILURE(status)) { return FALSE; } @@ -1001,13 +1005,13 @@ SimpleTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransitio } UBool -SimpleTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) /*const*/ { +SimpleTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const { if (!useDaylight) { return FALSE; } UErrorCode status = U_ZERO_ERROR; - initTransitionRules(status); + checkTransitionRules(status); if (U_FAILURE(status)) { return FALSE; } @@ -1060,6 +1064,35 @@ SimpleTimeZone::deleteTransitionRules(void) { clearTransitionRules(); } +/* + * 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. + */ + +void +SimpleTimeZone::checkTransitionRules(UErrorCode& status) const { + if (U_FAILURE(status)) { + return; + } + static UMutex *gLock = STATIC_NEW(UMutex); + umtx_lock(gLock); + if (!transitionRulesInitialized) { + SimpleTimeZone *ncThis = const_cast(this); + ncThis->initTransitionRules(status); + } + umtx_unlock(gLock); +} + void SimpleTimeZone::initTransitionRules(UErrorCode& status) { if (U_FAILURE(status)) { @@ -1099,8 +1132,8 @@ SimpleTimeZone::initTransitionRules(UErrorCode& status) { } // Check for Null pointer if (dtRule == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return; + status = U_MEMORY_ALLOCATION_ERROR; + return; } // For now, use ID + "(DST)" as the name dstRule = new AnnualTimeZoneRule(tzid+UnicodeString(DST_STR), getRawOffset(), getDSTSavings(), @@ -1108,9 +1141,9 @@ SimpleTimeZone::initTransitionRules(UErrorCode& status) { // Check for Null pointer if (dstRule == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - deleteTransitionRules(); - return; + status = U_MEMORY_ALLOCATION_ERROR; + deleteTransitionRules(); + return; } // Calculate the first DST start time @@ -1136,9 +1169,9 @@ SimpleTimeZone::initTransitionRules(UErrorCode& status) { // Check for Null pointer if (dtRule == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - deleteTransitionRules(); - return; + status = U_MEMORY_ALLOCATION_ERROR; + deleteTransitionRules(); + return; } // For now, use ID + "(STD)" as the name stdRule = new AnnualTimeZoneRule(tzid+UnicodeString(STD_STR), getRawOffset(), 0, @@ -1146,9 +1179,9 @@ SimpleTimeZone::initTransitionRules(UErrorCode& status) { //Check for Null pointer if (stdRule == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - deleteTransitionRules(); - return; + status = U_MEMORY_ALLOCATION_ERROR; + deleteTransitionRules(); + return; } // Calculate the first STD start time @@ -1157,16 +1190,25 @@ SimpleTimeZone::initTransitionRules(UErrorCode& status) { // Create a TimeZoneRule for initial time if (firstStdStart < firstDstStart) { initialRule = new InitialTimeZoneRule(tzid+UnicodeString(DST_STR), getRawOffset(), dstRule->getDSTSavings()); + if (initialRule == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + deleteTransitionRules(); + return; + } firstTransition = new TimeZoneTransition(firstStdStart, *initialRule, *stdRule); } else { initialRule = new InitialTimeZoneRule(tzid+UnicodeString(STD_STR), getRawOffset(), 0); + if (initialRule == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + deleteTransitionRules(); + return; + } firstTransition = new TimeZoneTransition(firstDstStart, *initialRule, *dstRule); } - // Check for null pointers. - if (initialRule == NULL || firstTransition == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - deleteTransitionRules(); - return; + if (firstTransition == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + deleteTransitionRules(); + return; } } else { @@ -1174,17 +1216,17 @@ SimpleTimeZone::initTransitionRules(UErrorCode& status) { initialRule = new InitialTimeZoneRule(tzid, getRawOffset(), 0); // Check for null pointer. if (initialRule == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - deleteTransitionRules(); - return; + status = U_MEMORY_ALLOCATION_ERROR; + deleteTransitionRules(); + return; } } - transitionRulesInitialized = true; + transitionRulesInitialized = TRUE; } int32_t -SimpleTimeZone::countTransitionRules(UErrorCode& /*status*/) /*const*/ { +SimpleTimeZone::countTransitionRules(UErrorCode& /*status*/) const { return (useDaylight) ? 2 : 0; } @@ -1192,11 +1234,11 @@ void SimpleTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial, const TimeZoneRule* trsrules[], int32_t& trscount, - UErrorCode& status) /*const*/ { + UErrorCode& status) const { if (U_FAILURE(status)) { return; } - initTransitionRules(status); + checkTransitionRules(status); if (U_FAILURE(status)) { return; }