[Chromium-win] Refactor date/time format conversion code in LocaleWin
authortkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Nov 2012 03:33:38 +0000 (03:33 +0000)
committertkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Nov 2012 03:33:38 +0000 (03:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=101329

Reviewed by Kentaro Hara.

convertWindowsDateFormatToLDML and convertWindowsTimeFormatToLDML did
similar jobs with different code. We can merge them into one function.

As for the date format conversion, we have tokenized a format string and
stored token objects into a vector. We skip token object generation and
generate a LDML-compliant pattern string during parsing.

No new tests. This should make no behavior changes and
WebKit/chromium/tests/LocaleWinTest.cpp has test cases.

* platform/text/win/LocaleWin.cpp:
(WebCore): Remove DateFormatToken, isFooSymbol, ensureShortDateTokens,
convertWindowsDateFormatToLDML, mapCharacterToDateTimeFieldType, and
convertWindowsTimeFormatToLDML.
(WebCore::commitLiteralToken): Store the result to the specified StringBuilder.
(WebCore::convertWindowsDateTimeFormat):
Renamed from parseDateFormat, and supports time format symbols.
(WebCore::LocaleWin::dateFormat): Use convertWindowsDateTimeFormat.
(WebCore::LocaleWin::monthFormat): Ditto.
(WebCore::LocaleWin::timeFormat): Ditto.
(WebCore::LocaleWin::shortTimeFormat): Ditto.
* platform/text/win/LocaleWin.h:
(LocaleWin): Remove ensureShortDateTokens and m_shortDateTokens.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@133712 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/text/win/LocaleWin.cpp
Source/WebCore/platform/text/win/LocaleWin.h

index 13e2285..e55c044 100644 (file)
@@ -1,3 +1,34 @@
+2012-11-06  Kent Tamura  <tkent@chromium.org>
+
+        [Chromium-win] Refactor date/time format conversion code in LocaleWin
+        https://bugs.webkit.org/show_bug.cgi?id=101329
+
+        Reviewed by Kentaro Hara.
+
+        convertWindowsDateFormatToLDML and convertWindowsTimeFormatToLDML did
+        similar jobs with different code. We can merge them into one function.
+
+        As for the date format conversion, we have tokenized a format string and
+        stored token objects into a vector. We skip token object generation and
+        generate a LDML-compliant pattern string during parsing.
+
+        No new tests. This should make no behavior changes and
+        WebKit/chromium/tests/LocaleWinTest.cpp has test cases.
+
+        * platform/text/win/LocaleWin.cpp:
+        (WebCore): Remove DateFormatToken, isFooSymbol, ensureShortDateTokens,
+        convertWindowsDateFormatToLDML, mapCharacterToDateTimeFieldType, and
+        convertWindowsTimeFormatToLDML.
+        (WebCore::commitLiteralToken): Store the result to the specified StringBuilder.
+        (WebCore::convertWindowsDateTimeFormat):
+        Renamed from parseDateFormat, and supports time format symbols.
+        (WebCore::LocaleWin::dateFormat): Use convertWindowsDateTimeFormat.
+        (WebCore::LocaleWin::monthFormat): Ditto.
+        (WebCore::LocaleWin::timeFormat): Ditto.
+        (WebCore::LocaleWin::shortTimeFormat): Ditto.
+        * platform/text/win/LocaleWin.h:
+        (LocaleWin): Remove ensureShortDateTokens and m_shortDateTokens.
+
 2012-11-06  Elliott Sprehn  <esprehn@chromium.org>
 
         Make Document::renderer faster by using the cached ptr for RenderView
index f78b383..924b7d3 100644 (file)
@@ -160,42 +160,6 @@ void LocaleWin::ensureShortMonthLabels()
 
 // -------------------------------- Tokenized date format
 
-struct DateFormatToken {
-    enum Type {
-        Literal,
-        Day1,
-        Day2,
-        Month1,
-        Month2,
-        Month3,
-        Month4,
-        Year1,
-        Year2,
-        Year4,
-    };
-    Type type;
-    String data; // This is valid only if type==Literal.
-
-    DateFormatToken(Type type)
-        : type(type)
-    { }
-
-    DateFormatToken(const String& data)
-        : type(Literal)
-        , data(data)
-    { }
-
-    DateFormatToken(const DateFormatToken& token)
-        : type(token.type)
-        , data(token.data)
-    { }
-};
-
-static inline bool isEraSymbol(UChar letter) { return letter == 'g'; }
-static inline bool isYearSymbol(UChar letter) { return letter == 'y'; }
-static inline bool isMonthSymbol(UChar letter) { return letter == 'M'; }
-static inline bool isDaySymbol(UChar letter) { return letter == 'd'; }
-
 static unsigned countContinuousLetters(const String& format, unsigned index)
 {
     unsigned count = 1;
@@ -208,18 +172,34 @@ static unsigned countContinuousLetters(const String& format, unsigned index)
     return count;
 }
 
-static void commitLiteralToken(StringBuilder& literalBuffer, Vector<DateFormatToken>& tokens)
+static void commitLiteralToken(StringBuilder& literalBuffer, StringBuilder& converted)
 {
     if (literalBuffer.length() <= 0)
         return;
-    tokens.append(DateFormatToken(literalBuffer.toString()));
+    DateTimeFormat::quoteAndAppendLiteral(literalBuffer.toString(), converted);
     literalBuffer.clear();
 }
 
-// See http://msdn.microsoft.com/en-us/library/dd317787(v=vs.85).aspx
-static Vector<DateFormatToken> parseDateFormat(const String format)
-{
-    Vector<DateFormatToken> tokens;
+// This function converts Windows date/time pattern format [1][2] into LDML date
+// format pattern [3].
+//
+// i.e.
+//   We set h, H, m, s, d, dd, M, or y as is. They have same meaning in both of
+//   Windows and LDML.
+//   We need to convert the following patterns:
+//     t -> a
+//     tt -> a
+//     ddd -> EEE
+//     dddd -> EEEE
+//     g -> G
+//     gg -> ignore
+//
+// [1] http://msdn.microsoft.com/en-us/library/dd317787(v=vs.85).aspx
+// [2] http://msdn.microsoft.com/en-us/library/dd318148(v=vs.85).aspx
+// [3] LDML http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns
+static String convertWindowsDateTimeFormat(const String& format)
+{
+    StringBuilder converted;
     StringBuilder literalBuffer;
     bool inQuote = false;
     bool lastQuoteCanBeLiteral = false;
@@ -246,51 +226,36 @@ static Vector<DateFormatToken> parseDateFormat(const String format)
                 lastQuoteCanBeLiteral = false;
             } else
                 lastQuoteCanBeLiteral = true;
-        } else if (isYearSymbol(ch)) {
-            commitLiteralToken(literalBuffer, tokens);
-            unsigned count = countContinuousLetters(format, i);
-            i += count - 1;
-            if (count == 1)
-                tokens.append(DateFormatToken(DateFormatToken::Year1));
-            else if (count == 2)
-                tokens.append(DateFormatToken(DateFormatToken::Year2));
-            else
-                tokens.append(DateFormatToken(DateFormatToken::Year4));
-        } else if (isMonthSymbol(ch)) {
-            commitLiteralToken(literalBuffer, tokens);
-            unsigned count = countContinuousLetters(format, i);
-            i += count - 1;
-            if (count == 1)
-                tokens.append(DateFormatToken(DateFormatToken::Month1));
-            else if (count == 2)
-                tokens.append(DateFormatToken(DateFormatToken::Month2));
-            else if (count == 3)
-                tokens.append(DateFormatToken(DateFormatToken::Month3));
-            else
-                tokens.append(DateFormatToken(DateFormatToken::Month4));
-        } else if (isDaySymbol(ch)) {
-            commitLiteralToken(literalBuffer, tokens);
+        } else if (isASCIIAlpha(ch)) {
+            commitLiteralToken(literalBuffer, converted);
+            unsigned symbolStart = i;
             unsigned count = countContinuousLetters(format, i);
             i += count - 1;
-            if (count == 1)
-                tokens.append(DateFormatToken(DateFormatToken::Day1));
+            if (ch == 'h' || ch == 'H' || ch == 'm' || ch == 's' || ch == 'M' || ch == 'y')
+                converted.append(format, symbolStart, count);
+            else if (ch == 'd') {
+                if (count <= 2)
+                    converted.append(format, symbolStart, count);
+                else if (count == 3)
+                    converted.append("EEE");
+                else
+                    converted.append("EEEE");
+            } else if (ch == 'g') {
+                if (count == 1)
+                    converted.append('G');
+                else {
+                    // gg means imperial era in Windows.
+                    // Just ignore it.
+                }
+            } else if (ch == 't')
+                converted.append('a');
             else
-                tokens.append(DateFormatToken(DateFormatToken::Day2));
-        } else if (isEraSymbol(ch)) {
-            // Just ignore era.
-            // HTML5 date supports only A.D.
+                literalBuffer.append(format, symbolStart, count);
         } else
             literalBuffer.append(ch);
     }
-    commitLiteralToken(literalBuffer, tokens);
-    return tokens;
-}
-
-void LocaleWin::ensureShortDateTokens()
-{
-    if (!m_shortDateTokens.isEmpty())
-        return;
-    m_shortDateTokens = parseDateFormat(getLocaleInfoString(LOCALE_SSHORTDATE));
+    commitLiteralToken(literalBuffer, converted);
+    return converted.toString();
 }
 
 void LocaleWin::ensureMonthLabels()
@@ -380,128 +345,29 @@ bool LocaleWin::isRTL()
 #endif
 
 #if ENABLE(DATE_AND_TIME_INPUT_TYPES)
-static String convertWindowsDateFormatToLDML(const Vector<DateFormatToken>& tokens)
-{
-    StringBuilder buffer;
-    for (unsigned i = 0; i < tokens.size(); ++i) {
-        switch (tokens[i].type) {
-        case DateFormatToken::Literal:
-            DateTimeFormat::quoteAndAppendLiteral(tokens[i].data, buffer);
-            break;
-
-        case DateFormatToken::Day2:
-            buffer.append(static_cast<char>(DateTimeFormat::FieldTypeDayOfMonth));
-            // Fallthrough.
-        case DateFormatToken::Day1:
-            buffer.append(static_cast<char>(DateTimeFormat::FieldTypeDayOfMonth));
-            break;
-
-        case DateFormatToken::Month4:
-            buffer.append(static_cast<char>(DateTimeFormat::FieldTypeMonth));
-            // Fallthrough.
-        case DateFormatToken::Month3:
-            buffer.append(static_cast<char>(DateTimeFormat::FieldTypeMonth));
-            // Fallthrough.
-        case DateFormatToken::Month2:
-            buffer.append(static_cast<char>(DateTimeFormat::FieldTypeMonth));
-            // Fallthrough.
-        case DateFormatToken::Month1:
-            buffer.append(static_cast<char>(DateTimeFormat::FieldTypeMonth));
-            break;
-
-        case DateFormatToken::Year4:
-            buffer.append(static_cast<char>(DateTimeFormat::FieldTypeYear));
-            buffer.append(static_cast<char>(DateTimeFormat::FieldTypeYear));
-            // Fallthrough.
-        case DateFormatToken::Year2:
-            buffer.append(static_cast<char>(DateTimeFormat::FieldTypeYear));
-            // Fallthrough.
-        case DateFormatToken::Year1:
-            buffer.append(static_cast<char>(DateTimeFormat::FieldTypeYear));
-            break;
-        }
-    }
-    return buffer.toString();
-}
-
-static DateTimeFormat::FieldType mapCharacterToDateTimeFieldType(UChar ch)
-{
-    switch (ch) {
-    case 'h':
-        return DateTimeFormat::FieldTypeHour12;
-
-    case 'H':
-        return DateTimeFormat::FieldTypeHour23;
-
-    case 'm':
-        return DateTimeFormat::FieldTypeMinute;
-
-    case 's':
-        return DateTimeFormat::FieldTypeSecond;
-
-    case 't':
-        return DateTimeFormat::FieldTypePeriod;
-
-    default:
-        return DateTimeFormat::FieldTypeLiteral;
-    }
-}
-
-// This class used for converting Windows time pattern format[1] into LDML[2]
-// time format string.
-// [1] http://msdn.microsoft.com/en-us/library/windows/desktop/dd318148(v=vs.85).aspx
-// [2] LDML http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns
-static String convertWindowsTimeFormatToLDML(const String& windowsTimeFormat)
-{
-    StringBuilder builder;
-    int counter = 0;
-    DateTimeFormat::FieldType lastFieldType = DateTimeFormat::FieldTypeLiteral;
-    for (unsigned index = 0; index < windowsTimeFormat.length(); ++index) {
-        UChar const ch = windowsTimeFormat[index];
-        DateTimeFormat::FieldType fieldType = mapCharacterToDateTimeFieldType(ch);
-        if (fieldType == DateTimeFormat::FieldTypeLiteral)
-            builder.append(ch);
-        else if (fieldType == lastFieldType) {
-            ++counter;
-            if (counter == 2 && lastFieldType != DateTimeFormat::FieldTypePeriod)
-                builder.append(static_cast<UChar>(lastFieldType));
-        } else {
-            if (lastFieldType != DateTimeFormat::FieldTypeLiteral)
-                builder.append(static_cast<UChar>(lastFieldType));
-            builder.append(static_cast<UChar>(fieldType));
-            counter = 1;
-        }
-        lastFieldType = fieldType;
-    }
-    return builder.toString();
-}
-
 String LocaleWin::dateFormat()
 {
-    if (!m_dateFormat.isNull())
-        return m_dateFormat;
-    ensureShortDateTokens();
-    m_dateFormat = convertWindowsDateFormatToLDML(m_shortDateTokens);
+    if (m_dateFormat.isNull())
+        m_dateFormat = convertWindowsDateTimeFormat(getLocaleInfoString(LOCALE_SSHORTDATE));
     return m_dateFormat;
 }
 
 String LocaleWin::dateFormat(const String& windowsFormat)
 {
-    return convertWindowsDateFormatToLDML(parseDateFormat(windowsFormat));
+    return convertWindowsDateTimeFormat(windowsFormat);
 }
 
 String LocaleWin::monthFormat()
 {
-    if (!m_monthFormat.isNull())
-        return m_monthFormat;
-    m_monthFormat = convertWindowsDateFormatToLDML(parseDateFormat(getLocaleInfoString(LOCALE_SYEARMONTH)));
+    if (m_monthFormat.isNull())
+        m_monthFormat = convertWindowsDateTimeFormat(getLocaleInfoString(LOCALE_SYEARMONTH));
     return m_monthFormat;
 }
 
 String LocaleWin::timeFormat()
 {
     if (m_timeFormatWithSeconds.isNull())
-        m_timeFormatWithSeconds = convertWindowsTimeFormatToLDML(getLocaleInfoString(LOCALE_STIMEFORMAT));
+        m_timeFormatWithSeconds = convertWindowsDateTimeFormat(getLocaleInfoString(LOCALE_STIMEFORMAT));
     return m_timeFormatWithSeconds;
 }
 
@@ -520,7 +386,7 @@ String LocaleWin::shortTimeFormat()
         if (pos != notFound)
             format.remove(pos, builder.length());
     }
-    m_timeFormatWithoutSeconds = convertWindowsTimeFormatToLDML(format);
+    m_timeFormatWithoutSeconds = convertWindowsDateTimeFormat(format);
     return m_timeFormatWithoutSeconds;
 }
 
index 08112ff..ce64d23 100644 (file)
@@ -71,7 +71,6 @@ private:
     void getLocaleInfo(LCTYPE, DWORD&);
     void ensureShortMonthLabels();
     void ensureMonthLabels();
-    void ensureShortDateTokens();
 #if ENABLE(CALENDAR_PICKER)
     void ensureWeekDayShortLabels();
 #endif
@@ -79,7 +78,6 @@ private:
     virtual void initializeLocaleData() OVERRIDE;
 
     LCID m_lcid;
-    Vector<DateFormatToken> m_shortDateTokens;
 #if ENABLE(DATE_AND_TIME_INPUT_TYPES)
     Vector<String> m_shortMonthLabels;
     Vector<String> m_monthLabels;