Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / icu / source / i18n / vtzone.cpp
index eacd0bb..426810e 100644 (file)
@@ -1,11 +1,11 @@
 /*
 *******************************************************************************
-* Copyright (C) 2007-2010, International Business Machines Corporation and
+* Copyright (C) 2007-2013, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 */
 
-#include "unicode/utypeinfo.h"  // for 'typeid' to work
+#include "utypeinfo.h"  // for 'typeid' to work
 
 #include "unicode/utypes.h"
 
@@ -18,7 +18,7 @@
 #include "cmemory.h"
 #include "uvector.h"
 #include "gregoimp.h"
-#include "uhash.h"
+#include "uassert.h"
 
 U_NAMESPACE_BEGIN
 
@@ -414,20 +414,20 @@ static void parseRRULE(const UnicodeString& rrule, int32_t& month, int32_t& dow,
             goto rruleParseError;
         }
 
-        if (attr.compare(ICAL_FREQ) == 0) {
+        if (attr.compare(ICAL_FREQ, -1) == 0) {
             // only support YEARLY frequency type
-            if (value.compare(ICAL_YEARLY) == 0) {
+            if (value.compare(ICAL_YEARLY, -1) == 0) {
                 yearly = TRUE;
             } else {
                 goto rruleParseError;
             }
-        } else if (attr.compare(ICAL_UNTIL) == 0) {
+        } else if (attr.compare(ICAL_UNTIL, -1) == 0) {
             // ISO8601 UTC format, for example, "20060315T020000Z"
             until = parseDateTimeString(value, 0, status);
             if (U_FAILURE(status)) {
                 goto rruleParseError;
             }
-        } else if (attr.compare(ICAL_BYMONTH) == 0) {
+        } else if (attr.compare(ICAL_BYMONTH, -1) == 0) {
             // Note: BYMONTH may contain multiple months, but only single month make sense for
             // VTIMEZONE property.
             if (value.length() > 2) {
@@ -437,7 +437,7 @@ static void parseRRULE(const UnicodeString& rrule, int32_t& month, int32_t& dow,
             if (U_FAILURE(status) || month < 0 || month >= 12) {
                 goto rruleParseError;
             }
-        } else if (attr.compare(ICAL_BYDAY) == 0) {
+        } else if (attr.compare(ICAL_BYDAY, -1) == 0) {
             // Note: BYDAY may contain multiple day of week separated by comma.  It is unlikely used for
             // VTIMEZONE property.  We do not support the case.
 
@@ -476,7 +476,7 @@ static void parseRRULE(const UnicodeString& rrule, int32_t& month, int32_t& dow,
             } else {
                 goto rruleParseError;
             }
-        } else if (attr.compare(ICAL_BYMONTHDAY) == 0) {
+        } else if (attr.compare(ICAL_BYMONTHDAY, -1) == 0) {
             // Note: BYMONTHDAY may contain multiple days delimitted by comma
             //
             // A value of BYMONTHDAY could be negative, for example, -1 means
@@ -886,6 +886,7 @@ public:
 
     void write(const UnicodeString& str);
     void write(UChar ch);
+    void write(const UChar* str);
     //void write(const UChar* str, int32_t length);
 private:
     UnicodeString* out;
@@ -908,6 +909,11 @@ VTZWriter::write(UChar ch) {
     out->append(ch);
 }
 
+void
+VTZWriter::write(const UChar* str) {
+    out->append(str, -1);
+}
+
 /*
 void
 VTZWriter::write(const UChar* str, int32_t length) {
@@ -962,7 +968,7 @@ VTimeZone::VTimeZone(const VTimeZone& source)
     if (source.vtzlines != NULL) {
         UErrorCode status = U_ZERO_ERROR;
         int32_t size = source.vtzlines->size();
-        vtzlines = new UVector(uhash_deleteUnicodeString, uhash_compareUnicodeString, size, status);
+        vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, size, status);
         if (U_SUCCESS(status)) {
             for (int32_t i = 0; i < size; i++) {
                 UnicodeString *line = (UnicodeString*)source.vtzlines->elementAt(i);
@@ -1007,7 +1013,7 @@ VTimeZone::operator=(const VTimeZone& right) {
         if (right.vtzlines != NULL) {
             UErrorCode status = U_ZERO_ERROR;
             int32_t size = right.vtzlines->size();
-            vtzlines = new UVector(uhash_deleteUnicodeString, uhash_compareUnicodeString, size, status);
+            vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, size, status);
             if (U_SUCCESS(status)) {
                 for (int32_t i = 0; i < size; i++) {
                     UnicodeString *line = (UnicodeString*)right.vtzlines->elementAt(i);
@@ -1156,14 +1162,14 @@ VTimeZone::write(UnicodeString& result, UErrorCode& status) const {
 }
 
 void
-VTimeZone::write(UDate start, UnicodeString& result, UErrorCode& status) /*const*/ {
+VTimeZone::write(UDate start, UnicodeString& result, UErrorCode& status) const {
     result.remove();
     VTZWriter writer(result);
     write(start, writer, status);
 }
 
 void
-VTimeZone::writeSimple(UDate time, UnicodeString& result, UErrorCode& status) /*const*/ {
+VTimeZone::writeSimple(UDate time, UnicodeString& result, UErrorCode& status) const {
     result.remove();
     VTZWriter writer(result);
     writeSimple(time, writer, status);
@@ -1219,30 +1225,30 @@ VTimeZone::hasSameRules(const TimeZone& other) const {
 }
 
 UBool
-VTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) /*const*/ {
+VTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const {
     return tz->getNextTransition(base, inclusive, result);
 }
 
 UBool
-VTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) /*const*/ {
+VTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const {
     return tz->getPreviousTransition(base, inclusive, result);
 }
 
 int32_t
-VTimeZone::countTransitionRules(UErrorCode& status) /*const*/ {
+VTimeZone::countTransitionRules(UErrorCode& status) const {
     return tz->countTransitionRules(status);
 }
 
 void
 VTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial,
                             const TimeZoneRule* trsrules[], int32_t& trscount,
-                            UErrorCode& status) /*const*/ {
+                            UErrorCode& status) const {
     tz->getTimeZoneRules(initial, trsrules, trscount, status);
 }
 
 void
 VTimeZone::load(VTZReader& reader, UErrorCode& status) {
-    vtzlines = new UVector(uhash_deleteUnicodeString, uhash_compareUnicodeString, DEFAULT_VTIMEZONE_LINES, status);
+    vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, DEFAULT_VTIMEZONE_LINES, status);
     if (U_FAILURE(status)) {
         return;
     }
@@ -1255,7 +1261,7 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) {
         UChar ch = reader.read();
         if (ch == 0xFFFF) {
             // end of file
-            if (start && line.startsWith(ICAL_END_VTIMEZONE)) {
+            if (start && line.startsWith(ICAL_END_VTIMEZONE, -1)) {
                 vtzlines->addElement(new UnicodeString(line), status);
                 if (U_FAILURE(status)) {
                     goto cleanupVtzlines;
@@ -1290,7 +1296,7 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) {
                 // LF
                 eol = TRUE;
                 if (start) {
-                    if (line.startsWith(ICAL_END_VTIMEZONE)) {
+                    if (line.startsWith(ICAL_END_VTIMEZONE, -1)) {
                         vtzlines->addElement(new UnicodeString(line), status);
                         if (U_FAILURE(status)) {
                             goto cleanupVtzlines;
@@ -1299,7 +1305,7 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) {
                         break;
                     }
                 } else {
-                    if (line.startsWith(ICAL_BEGIN_VTIMEZONE)) {
+                    if (line.startsWith(ICAL_BEGIN_VTIMEZONE, -1)) {
                         vtzlines->addElement(new UnicodeString(line), status);
                         if (U_FAILURE(status)) {
                             goto cleanupVtzlines;
@@ -1378,7 +1384,7 @@ VTimeZone::parse(UErrorCode& status) {
      // Set the deleter to remove TimeZoneRule vectors to avoid memory leaks due to unowned TimeZoneRules.
     rules->setDeleter(deleteTimeZoneRule);
     
-    dates = new UVector(uhash_deleteUnicodeString, uhash_compareUnicodeString, status);
+    dates = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status);
     if (U_FAILURE(status)) {
         goto cleanupParse;
     }
@@ -1398,27 +1404,27 @@ VTimeZone::parse(UErrorCode& status) {
 
         switch (state) {
         case INI:
-            if (name.compare(ICAL_BEGIN) == 0
-                && value.compare(ICAL_VTIMEZONE) == 0) {
+            if (name.compare(ICAL_BEGIN, -1) == 0
+                && value.compare(ICAL_VTIMEZONE, -1) == 0) {
                 state = VTZ;
             }
             break;
 
         case VTZ:
-            if (name.compare(ICAL_TZID) == 0) {
+            if (name.compare(ICAL_TZID, -1) == 0) {
                 tzid = value;
-            } else if (name.compare(ICAL_TZURL) == 0) {
+            } else if (name.compare(ICAL_TZURL, -1) == 0) {
                 tzurl = value;
-            } else if (name.compare(ICAL_LASTMOD) == 0) {
+            } else if (name.compare(ICAL_LASTMOD, -1) == 0) {
                 // Always in 'Z' format, so the offset argument for the parse method
                 // can be any value.
                 lastmod = parseDateTimeString(value, 0, status);
                 if (U_FAILURE(status)) {
                     goto cleanupParse;
                 }
-            } else if (name.compare(ICAL_BEGIN) == 0) {
-                UBool isDST = (value.compare(ICAL_DAYLIGHT) == 0);
-                if (value.compare(ICAL_STANDARD) == 0 || isDST) {
+            } else if (name.compare(ICAL_BEGIN, -1) == 0) {
+                UBool isDST = (value.compare(ICAL_DAYLIGHT, -1) == 0);
+                if (value.compare(ICAL_STANDARD, -1) == 0 || isDST) {
                     // tzid must be ready at this point
                     if (tzid.length() == 0) {
                         goto cleanupParse;
@@ -1438,20 +1444,20 @@ VTimeZone::parse(UErrorCode& status) {
                     // must not be there.
                     goto cleanupParse;
                 }
-            } else if (name.compare(ICAL_END) == 0) {
+            } else if (name.compare(ICAL_END, -1) == 0) {
                 break;
             }
             break;
         case TZI:
-            if (name.compare(ICAL_DTSTART) == 0) {
+            if (name.compare(ICAL_DTSTART, -1) == 0) {
                 dtstart = value;
-            } else if (name.compare(ICAL_TZNAME) == 0) {
+            } else if (name.compare(ICAL_TZNAME, -1) == 0) {
                 zonename = value;
-            } else if (name.compare(ICAL_TZOFFSETFROM) == 0) {
+            } else if (name.compare(ICAL_TZOFFSETFROM, -1) == 0) {
                 from = value;
-            } else if (name.compare(ICAL_TZOFFSETTO) == 0) {
+            } else if (name.compare(ICAL_TZOFFSETTO, -1) == 0) {
                 to = value;
-            } else if (name.compare(ICAL_RDATE) == 0) {
+            } else if (name.compare(ICAL_RDATE, -1) == 0) {
                 // RDATE mixed with RRULE is not supported
                 if (isRRULE) {
                     goto cleanupParse;
@@ -1475,7 +1481,7 @@ VTimeZone::parse(UErrorCode& status) {
                     }
                     dstart = dend + 1;
                 }
-            } else if (name.compare(ICAL_RRULE) == 0) {
+            } else if (name.compare(ICAL_RRULE, -1) == 0) {
                 // RRULE mixed with RDATE is not supported
                 if (!isRRULE && dates->size() != 0) {
                     goto cleanupParse;
@@ -1485,7 +1491,7 @@ VTimeZone::parse(UErrorCode& status) {
                 if (U_FAILURE(status)) {
                     goto cleanupParse;
                 }
-            } else if (name.compare(ICAL_END) == 0) {
+            } else if (name.compare(ICAL_END, -1) == 0) {
                 // Mandatory properties
                 if (dtstart.length() == 0 || from.length() == 0 || to.length() == 0) {
                     goto cleanupParse;
@@ -1720,13 +1726,13 @@ VTimeZone::write(VTZWriter& writer, UErrorCode& status) const {
     if (vtzlines != NULL) {
         for (int32_t i = 0; i < vtzlines->size(); i++) {
             UnicodeString *line = (UnicodeString*)vtzlines->elementAt(i);
-            if (line->startsWith(ICAL_TZURL)
+            if (line->startsWith(ICAL_TZURL, -1)
                 && line->charAt(u_strlen(ICAL_TZURL)) == COLON) {
                 writer.write(ICAL_TZURL);
                 writer.write(COLON);
                 writer.write(tzurl);
                 writer.write(ICAL_NEWLINE);
-            } else if (line->startsWith(ICAL_LASTMOD)
+            } else if (line->startsWith(ICAL_LASTMOD, -1)
                 && line->charAt(u_strlen(ICAL_LASTMOD)) == COLON) {
                 UnicodeString utcString;
                 writer.write(ICAL_LASTMOD);
@@ -1741,7 +1747,7 @@ VTimeZone::write(VTZWriter& writer, UErrorCode& status) const {
     } else {
         UVector *customProps = NULL;
         if (olsonzid.length() > 0 && icutzver.length() > 0) {
-            customProps = new UVector(uhash_deleteUnicodeString, uhash_compareUnicodeString, status);
+            customProps = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status);
             if (U_FAILURE(status)) {
                 return;
             }
@@ -1763,13 +1769,13 @@ VTimeZone::write(VTZWriter& writer, UErrorCode& status) const {
 }
 
 void
-VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) /*const*/ {
+VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) const {
     if (U_FAILURE(status)) {
         return;
     }
     InitialTimeZoneRule *initial = NULL;
     UVector *transitionRules = NULL;
-    UVector customProps(uhash_deleteUnicodeString, uhash_compareUnicodeString, status);
+    UVector customProps(uprv_deleteUObject, uhash_compareUnicodeString, status);
     UnicodeString tzid;
 
     // Extract rules applicable to dates after the start time
@@ -1802,7 +1808,7 @@ VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) /*const*/ {
         icutzprop->append(olsonzid);
         icutzprop->append((UChar)0x005B/*'['*/);
         icutzprop->append(icutzver);
-        icutzprop->append(ICU_TZINFO_PARTIAL);
+        icutzprop->append(ICU_TZINFO_PARTIAL, -1);
         appendMillis(start, *icutzprop);
         icutzprop->append((UChar)0x005D/*']'*/);
         customProps.addElement(icutzprop, status);
@@ -1828,12 +1834,12 @@ cleanupWritePartial:
 }
 
 void
-VTimeZone::writeSimple(UDate time, VTZWriter& writer, UErrorCode& status) /*const*/ {
+VTimeZone::writeSimple(UDate time, VTZWriter& writer, UErrorCode& status) const {
     if (U_FAILURE(status)) {
         return;
     }
 
-    UVector customProps(uhash_deleteUnicodeString, uhash_compareUnicodeString, status);
+    UVector customProps(uprv_deleteUObject, uhash_compareUnicodeString, status);
     UnicodeString tzid;
 
     // Extract simple rules
@@ -1857,7 +1863,7 @@ VTimeZone::writeSimple(UDate time, VTZWriter& writer, UErrorCode& status) /*cons
             icutzprop->append(olsonzid);
             icutzprop->append((UChar)0x005B/*'['*/);
             icutzprop->append(icutzver);
-            icutzprop->append(ICU_TZINFO_SIMPLE);
+            icutzprop->append(ICU_TZINFO_SIMPLE, -1);
             appendMillis(time, *icutzprop);
             icutzprop->append((UChar)0x005D/*']'*/);
             customProps.addElement(icutzprop, status);
@@ -2104,8 +2110,13 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz,
                         if (U_FAILURE(status)) {
                             goto cleanupWriteZone;
                         }
-                        writeFinalRule(w, TRUE, finalDstRule,
-                                dstFromOffset - dstFromDSTSavings, dstFromDSTSavings, dstStartTime, status);
+                        UDate nextStart;
+                        UBool nextStartAvail = finalDstRule->getNextStart(dstUntilTime, dstFromOffset - dstFromDSTSavings, dstFromDSTSavings, false, nextStart);
+                        U_ASSERT(nextStartAvail);
+                        if (nextStartAvail) {
+                            writeFinalRule(w, TRUE, finalDstRule,
+                                    dstFromOffset - dstFromDSTSavings, dstFromDSTSavings, nextStart, status);
+                        }
                     }
                 }
                 if (U_FAILURE(status)) {
@@ -2133,7 +2144,7 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz,
                     // Use a single rule if possible
                     if (isEquivalentDateRule(stdMonth, stdWeekInMonth, stdDayOfWeek, finalStdRule->getRule())) {
                         writeZonePropsByDOW(w, FALSE, stdName, stdFromOffset, stdToOffset,
-                                stdMonth, stdWeekInMonth, stdDayOfWeek, stdStartTime, MAX_MILLIS, status);                            
+                                stdMonth, stdWeekInMonth, stdDayOfWeek, stdStartTime, MAX_MILLIS, status);
                     } else {
                         // Not equivalent rule - write out two different rules
                         writeZonePropsByDOW(w, FALSE, stdName, stdFromOffset, stdToOffset,
@@ -2141,8 +2152,13 @@ VTimeZone::writeZone(VTZWriter& w, BasicTimeZone& basictz,
                         if (U_FAILURE(status)) {
                             goto cleanupWriteZone;
                         }
-                        writeFinalRule(w, FALSE, finalStdRule,
-                                stdFromOffset - stdFromDSTSavings, stdFromDSTSavings, stdStartTime, status);
+                        UDate nextStart;
+                        UBool nextStartAvail = finalStdRule->getNextStart(stdUntilTime, stdFromOffset - stdFromDSTSavings, stdFromDSTSavings, false, nextStart);
+                        U_ASSERT(nextStartAvail);
+                        if (nextStartAvail) {
+                            writeFinalRule(w, FALSE, finalStdRule,
+                                    stdFromOffset - stdFromDSTSavings, stdFromDSTSavings, nextStart, status);
+                        }
                     }
                 }
                 if (U_FAILURE(status)) {