]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/tzfmt.cpp
ICU-64260.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / tzfmt.cpp
index 7f26d196b7ee2e7dd303426b2c4a59e068b97aaa..b252d2056d461077dc148d69b013ef964e20a63f 100644 (file)
@@ -18,6 +18,7 @@
 #include "unicode/uchar.h"
 #include "unicode/udat.h"
 #include "unicode/ustring.h"
+#include "unicode/utf16.h"
 #include "tzgnames.h"
 #include "cmemory.h"
 #include "cstring.h"
@@ -30,6 +31,7 @@
 #include "uvector.h"
 #include "zonemeta.h"
 #include "tznames_impl.h"   // TextTrieMap
+#include "patternprops.h"
 
 U_NAMESPACE_BEGIN
 
@@ -145,7 +147,10 @@ static icu::UInitOnce gZoneIdTrieInitOnce = U_INITONCE_INITIALIZER;
 static TextTrieMap *gShortZoneIdTrie = NULL;
 static icu::UInitOnce gShortZoneIdTrieInitOnce = U_INITONCE_INITIALIZER;
 
-static UMutex gLock = U_MUTEX_INITIALIZER;
+static UMutex *gLock() {
+    static UMutex *m = STATIC_NEW(UMutex);
+    return m;
+}
 
 U_CDECL_BEGIN
 /**
@@ -265,7 +270,7 @@ GMTOffsetField::isValid(FieldType type, int32_t width) {
     case SECOND:
         return (width == 2);
     default:
-        U_ASSERT(FALSE);
+        UPRV_UNREACHABLE;
     }
     return (width > 0);
 }
@@ -320,7 +325,7 @@ TimeZoneFormat::TimeZoneFormat(const Locale& locale, UErrorCode& status)
     }
 
     const char* region = fLocale.getCountry();
-    int32_t regionLen = uprv_strlen(region);
+    int32_t regionLen = static_cast<int32_t>(uprv_strlen(region));
     if (regionLen == 0) {
         char loc[ULOC_FULLNAME_CAPACITY];
         uloc_addLikelySubtags(fLocale.getName(), loc, sizeof(loc), &status);
@@ -587,8 +592,7 @@ TimeZoneFormat::setGMTOffsetPattern(UTimeZoneFormatGMTOffsetPatternType type, co
         required = FIELDS_HMS;
         break;
     default:
-        U_ASSERT(FALSE);
-        break;
+        UPRV_UNREACHABLE;
     }
 
     UVector* patternItems = parseOffsetPattern(pattern, required, status);
@@ -788,7 +792,7 @@ TimeZoneFormat::format(const Formattable& obj, UnicodeString& appendTo,
         if (tz != NULL) {
             int32_t rawOffset, dstOffset;
             tz->getOffset(date, FALSE, rawOffset, dstOffset, status);
-            UChar buf[32];
+            UChar buf[ZONE_NAME_U16_MAX];
             UnicodeString result(buf, 0, UPRV_LENGTHOF(buf));
             formatOffsetLocalizedGMT(rawOffset + dstOffset, result, status);
             if (U_SUCCESS(status)) {
@@ -1026,7 +1030,7 @@ TimeZoneFormat::parse(UTimeZoneFormatStyle style, const UnicodeString& text, Par
                 break;
 
             default:
-                U_ASSERT(FALSE);
+                UPRV_UNREACHABLE;
             }
 
             int32_t len = 0;
@@ -1381,12 +1385,12 @@ TimeZoneFormat::getTimeZoneGenericNames(UErrorCode& status) const {
         return NULL;
     }
 
-    umtx_lock(&gLock);
+    umtx_lock(gLock());
     if (fTimeZoneGenericNames == NULL) {
         TimeZoneFormat *nonConstThis = const_cast<TimeZoneFormat *>(this);
         nonConstThis->fTimeZoneGenericNames = TimeZoneGenericNames::createInstance(fLocale, status);
     }
-    umtx_unlock(&gLock);
+    umtx_unlock(gLock());
 
     return fTimeZoneGenericNames;
 }
@@ -1397,7 +1401,7 @@ TimeZoneFormat::getTZDBTimeZoneNames(UErrorCode& status) const {
         return NULL;
     }
 
-    umtx_lock(&gLock);
+    umtx_lock(gLock());
     if (fTZDBTimeZoneNames == NULL) {
         TZDBTimeZoneNames *tzdbNames = new TZDBTimeZoneNames(fLocale);
         if (tzdbNames == NULL) {
@@ -1407,14 +1411,14 @@ TimeZoneFormat::getTZDBTimeZoneNames(UErrorCode& status) const {
             nonConstThis->fTZDBTimeZoneNames = tzdbNames;
         }
     }
-    umtx_unlock(&gLock);
+    umtx_unlock(gLock());
 
     return fTZDBTimeZoneNames;
 }
 
 UnicodeString&
 TimeZoneFormat::formatExemplarLocation(const TimeZone& tz, UnicodeString& name) const {
-    UChar locationBuf[64];
+    UChar locationBuf[ZONE_NAME_U16_MAX];
     UnicodeString location(locationBuf, 0, UPRV_LENGTHOF(locationBuf));
     const UChar* canonicalID = ZoneMeta::getCanonicalCLDRID(tz);
 
@@ -1812,7 +1816,9 @@ TimeZoneFormat::parseOffsetFields(const UnicodeString& text, int32_t start, UBoo
         // but it should be parsed as 00:10:20.
         int32_t tmpLen = 0;
         int32_t tmpSign = 1;
-        int32_t tmpH, tmpM, tmpS;
+        int32_t tmpH = 0;
+        int32_t tmpM = 0;
+        int32_t tmpS = 0;
 
         for (int32_t patidx = 0; PARSE_GMT_OFFSET_TYPES[patidx] >= 0; patidx++) {
             int32_t gmtPatType = PARSE_GMT_OFFSET_TYPES[patidx];
@@ -1860,6 +1866,27 @@ TimeZoneFormat::parseOffsetFieldsWithPattern(const UnicodeString& text, int32_t
         if (fieldType == GMTOffsetField::TEXT) {
             const UChar* patStr = field->getPatternText();
             len = u_strlen(patStr);
+            if (i == 0) {
+                // When TimeZoneFormat parse() is called from SimpleDateFormat,
+                // leading space characters might be truncated. If the first pattern text
+                // starts with such character (e.g. Bidi control), then we need to
+                // skip the leading space charcters.
+                if (idx < text.length() && !PatternProps::isWhiteSpace(text.char32At(idx))) {
+                    while (len > 0) {
+                        UChar32 ch;
+                        int32_t chLen;
+                        U16_GET(patStr, 0, 0, len, ch)
+                        if (PatternProps::isWhiteSpace(ch)) {
+                            chLen = U16_LENGTH(ch);
+                            len -= chLen;
+                            patStr += chLen;
+                        }
+                        else {
+                            break;
+                        }
+                    }
+                }
+            }
             if (text.caseCompare(idx, len, patStr, 0) != 0) {
                 failed = TRUE;
                 break;
@@ -2428,7 +2455,7 @@ TimeZoneFormat::parseOffsetPattern(const UnicodeString& pattern, OffsetFields re
                 isPrevQuote = TRUE;
                 if (itemType != GMTOffsetField::TEXT) {
                     if (GMTOffsetField::isValid(itemType, itemLength)) {
-                        GMTOffsetField* fld = GMTOffsetField::createTimeField(itemType, (uint8_t)itemLength, status);
+                        GMTOffsetField* fld = GMTOffsetField::createTimeField(itemType, static_cast<uint8_t>(itemLength), status);
                         result->addElement(fld, status);
                         if (U_FAILURE(status)) {
                             break;
@@ -2463,7 +2490,7 @@ TimeZoneFormat::parseOffsetPattern(const UnicodeString& pattern, OffsetFields re
                             }
                         } else {
                             if (GMTOffsetField::isValid(itemType, itemLength)) {
-                                GMTOffsetField* fld = GMTOffsetField::createTimeField(itemType, itemLength, status);
+                                GMTOffsetField* fld = GMTOffsetField::createTimeField(itemType, static_cast<uint8_t>(itemLength), status);
                                 result->addElement(fld, status);
                                 if (U_FAILURE(status)) {
                                     break;
@@ -2481,7 +2508,7 @@ TimeZoneFormat::parseOffsetPattern(const UnicodeString& pattern, OffsetFields re
                     // a string literal
                     if (itemType != GMTOffsetField::TEXT) {
                         if (GMTOffsetField::isValid(itemType, itemLength)) {
-                            GMTOffsetField* fld = GMTOffsetField::createTimeField(itemType, itemLength, status);
+                            GMTOffsetField* fld = GMTOffsetField::createTimeField(itemType, static_cast<uint8_t>(itemLength), status);
                             result->addElement(fld, status);
                             if (U_FAILURE(status)) {
                                 break;
@@ -2506,7 +2533,7 @@ TimeZoneFormat::parseOffsetPattern(const UnicodeString& pattern, OffsetFields re
             }
         } else {
             if (GMTOffsetField::isValid(itemType, itemLength)) {
-                GMTOffsetField* fld = GMTOffsetField::createTimeField(itemType, itemLength, status);
+                GMTOffsetField* fld = GMTOffsetField::createTimeField(itemType, static_cast<uint8_t>(itemLength), status);
                 result->addElement(fld, status);
             } else {
                 status = U_ILLEGAL_ARGUMENT_ERROR;
@@ -2623,12 +2650,12 @@ TimeZoneFormat::checkAbuttingHoursAndMinutes() {
         UVector *items = fGMTOffsetPatternItems[type];
         for (int32_t i = 0; i < items->size(); i++) {
             const GMTOffsetField* item = (GMTOffsetField*)items->elementAt(i);
-            GMTOffsetField::FieldType type = item->getType();
-            if (type != GMTOffsetField::TEXT) {
+            GMTOffsetField::FieldType fieldType = item->getType();
+            if (fieldType != GMTOffsetField::TEXT) {
                 if (afterH) {
                     fAbuttingOffsetHoursAndMinutes = TRUE;
                     break;
-                } else if (type == GMTOffsetField::HOUR) {
+                } else if (fieldType == GMTOffsetField::HOUR) {
                     afterH = TRUE;
                 }
             } else if (afterH) {
@@ -2752,7 +2779,7 @@ static void U_CALLCONV initZoneIdTrie(UErrorCode &status) {
     }
     StringEnumeration *tzenum = TimeZone::createEnumeration();
     const UnicodeString *id;
-    while ((id = tzenum->snext(status))) {
+    while ((id = tzenum->snext(status)) != NULL) {
         const UChar* uid = ZoneMeta::findTimeZoneID(*id);
         if (uid) {
             gZoneIdTrie->put(uid, const_cast<UChar *>(uid), status);
@@ -2799,7 +2826,7 @@ static void U_CALLCONV initShortZoneIdTrie(UErrorCode &status) {
             status = U_MEMORY_ALLOCATION_ERROR;
         } else {
             const UnicodeString *id;
-            while ((id = tzenum->snext(status))) {
+            while ((id = tzenum->snext(status)) != NULL) {
                 const UChar* uID = ZoneMeta::findTimeZoneID(*id);
                 const UChar* shortID = ZoneMeta::getShortID(*id);
                 if (shortID && uID) {