X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/729e4ab9bc6618bc3d8a898e575df7f4019e29ca..4f1e1a09ce4daed860e35d359ce2fceccb0764e8:/icuSources/i18n/simpletz.cpp diff --git a/icuSources/i18n/simpletz.cpp b/icuSources/i18n/simpletz.cpp index fb960bbf..57a7ba8e 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-2010, 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" @@ -32,6 +34,7 @@ #include "unicode/smpdtfmt.h" #include "gregoimp.h" +#include "umutex.h" U_NAMESPACE_BEGIN @@ -174,7 +177,7 @@ void SimpleTimeZone::construct(int32_t rawOffsetGMT, decodeRules(status); - if (savingsDST <= 0) { + if (savingsDST == 0) { status = U_ILLEGAL_ARGUMENT_ERROR; } } @@ -506,7 +509,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 +686,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 +970,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 +1004,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 +1063,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. + */ +static UMutex gLock = U_MUTEX_INITIALIZER; + +void +SimpleTimeZone::checkTransitionRules(UErrorCode& status) const { + if (U_FAILURE(status)) { + return; + } + 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,18 +1131,18 @@ 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+DST_STR, getRawOffset(), getDSTSavings(), + dstRule = new AnnualTimeZoneRule(tzid+UnicodeString(DST_STR), getRawOffset(), getDSTSavings(), dtRule, startYear, AnnualTimeZoneRule::MAX_YEAR); // 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,19 +1168,19 @@ 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+STD_STR, getRawOffset(), 0, + stdRule = new AnnualTimeZoneRule(tzid+UnicodeString(STD_STR), getRawOffset(), 0, dtRule, startYear, AnnualTimeZoneRule::MAX_YEAR); //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 @@ -1156,17 +1188,26 @@ SimpleTimeZone::initTransitionRules(UErrorCode& status) { // Create a TimeZoneRule for initial time if (firstStdStart < firstDstStart) { - initialRule = new InitialTimeZoneRule(tzid+DST_STR, getRawOffset(), dstRule->getDSTSavings()); + 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+STD_STR, getRawOffset(), 0); + 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 +1215,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 +1233,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; }