Move the content of LocalizedCalendarICU.cpp and LocalizedDateICU.cpp to ICULocale...
authortkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Apr 2012 00:47:22 +0000 (00:47 +0000)
committertkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Apr 2012 00:47:22 +0000 (00:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=84568

Reviewed by Hajime Morita.

Move it to ICULocal.cpp because we want to share UDateFormat
object in LocalizedDate functions and LocalizedCalendar functions,
and it becomes easier to cache the UDateFormat object, and making
unit tests for these functions easier.

No new tests because of no bahevior changes.

* platform/text/ICULocale.cpp:
(WebCore::ICULocale::ICULocale): Initialize new members.
(WebCore::ICULocale::~ICULocale): Delete m_shortDateFormat.
(WebCore::ICULocale::initializeShortDateFormat):
Moved from creteShortDateFormatter of LocalizedDateICU.cpp.
(WebCore::ICULocale::parseLocalizedDate):
Moved from LocalizedDate.cpp, use m_shortDateFormat.
(WebCore::ICULocale::formatLocalizedDate): ditto.
(WebCore::ICULocale::createLabelVector):
Moved from LocalizedCalendarICU.cpp, use m_shortDateFormat.
(WebCore::createFallbackMonthLabels): Moved from LocalizedCalendarICU.cpp.
(WebCore::createFallbackWeekDayShortLabels): ditto.
(WebCore::ICULocale::initializeCalendar):
lazy initialization of m_monthLabels, m_weekDayShortLabels, and m_firstDayOfWeek.
(WebCore::ICULocale::monthLabels):
(WebCore::ICULocale::weekDayShortLabels):
(WebCore::ICULocale::firstDayOfWeek):
* platform/text/ICULocale.h:
(ICULocale): Add declarations.
* platform/text/LocalizedCalendarICU.cpp:
(WebCore::monthLabels): Use ICULocale::currentLocale().
(WebCore::weekDayShortLabels): ditto.
(WebCore::firstDayOfWeek): ditto.
* platform/text/LocalizedDateICU.cpp:
(WebCore::parseLocalizedDate): ditto.
(WebCore::formatLocalizedDate): ditto.

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

Source/WebCore/ChangeLog
Source/WebCore/platform/text/ICULocale.cpp
Source/WebCore/platform/text/ICULocale.h
Source/WebCore/platform/text/LocalizedCalendarICU.cpp
Source/WebCore/platform/text/LocalizedDateICU.cpp

index c703b25..75e2617 100644 (file)
@@ -1,3 +1,44 @@
+2012-04-23  Kent Tamura  <tkent@chromium.org>
+
+        Move the content of LocalizedCalendarICU.cpp and LocalizedDateICU.cpp to ICULocale.cpp.
+        https://bugs.webkit.org/show_bug.cgi?id=84568
+
+        Reviewed by Hajime Morita.
+
+        Move it to ICULocal.cpp because we want to share UDateFormat
+        object in LocalizedDate functions and LocalizedCalendar functions,
+        and it becomes easier to cache the UDateFormat object, and making
+        unit tests for these functions easier.
+
+        No new tests because of no bahevior changes.
+
+        * platform/text/ICULocale.cpp:
+        (WebCore::ICULocale::ICULocale): Initialize new members.
+        (WebCore::ICULocale::~ICULocale): Delete m_shortDateFormat.
+        (WebCore::ICULocale::initializeShortDateFormat):
+        Moved from creteShortDateFormatter of LocalizedDateICU.cpp.
+        (WebCore::ICULocale::parseLocalizedDate):
+        Moved from LocalizedDate.cpp, use m_shortDateFormat.
+        (WebCore::ICULocale::formatLocalizedDate): ditto.
+        (WebCore::ICULocale::createLabelVector):
+        Moved from LocalizedCalendarICU.cpp, use m_shortDateFormat.
+        (WebCore::createFallbackMonthLabels): Moved from LocalizedCalendarICU.cpp.
+        (WebCore::createFallbackWeekDayShortLabels): ditto.
+        (WebCore::ICULocale::initializeCalendar):
+        lazy initialization of m_monthLabels, m_weekDayShortLabels, and m_firstDayOfWeek.
+        (WebCore::ICULocale::monthLabels):
+        (WebCore::ICULocale::weekDayShortLabels):
+        (WebCore::ICULocale::firstDayOfWeek):
+        * platform/text/ICULocale.h:
+        (ICULocale): Add declarations.
+        * platform/text/LocalizedCalendarICU.cpp:
+        (WebCore::monthLabels): Use ICULocale::currentLocale().
+        (WebCore::weekDayShortLabels): ditto.
+        (WebCore::firstDayOfWeek): ditto.
+        * platform/text/LocalizedDateICU.cpp:
+        (WebCore::parseLocalizedDate): ditto.
+        (WebCore::formatLocalizedDate): ditto.
+
 2012-04-23  Raymond Toy  <rtoy@google.com>
 
         Move AudioDestinationChromium FIFO class to its own class.
index 8c1e2a6..68fc5b8 100644 (file)
 #include "config.h"
 #include "ICULocale.h"
 
+#include <limits>
 #include <wtf/PassOwnPtr.h>
 #include <wtf/text/StringBuilder.h>
 
 using namespace icu;
+using namespace std;
 
 namespace WebCore {
 
 ICULocale::ICULocale(const char* locale)
     : m_locale(locale)
     , m_numberFormat(0)
+    , m_shortDateFormat(0)
     , m_didCreateDecimalFormat(false)
+    , m_didCreateShortDateFormat(false)
+#if ENABLE(CALENDAR_PICKER)
+    , m_firstDayOfWeek(0)
+#endif
 {
 }
 
 ICULocale::~ICULocale()
 {
     unum_close(m_numberFormat);
+    udat_close(m_shortDateFormat);
 }
 
 PassOwnPtr<ICULocale> ICULocale::create(const char* localeString)
@@ -258,5 +266,148 @@ String ICULocale::convertFromLocalizedNumber(const String& localized)
     return builder.toString();
 }
 
+bool ICULocale::initializeShortDateFormat()
+{
+    if (m_didCreateShortDateFormat)
+        return m_shortDateFormat;
+    const UChar gmtTimezone[3] = {'G', 'M', 'T'};
+    UErrorCode status = U_ZERO_ERROR;
+    m_shortDateFormat = udat_open(UDAT_NONE, UDAT_SHORT, m_locale.data(), gmtTimezone, WTF_ARRAY_LENGTH(gmtTimezone), 0, -1, &status);
+    m_didCreateShortDateFormat = true;
+    return m_shortDateFormat;
+}
+
+double ICULocale::parseLocalizedDate(const String& input)
+{
+    if (!initializeShortDateFormat())
+        return numeric_limits<double>::quiet_NaN();
+    if (input.length() > static_cast<unsigned>(numeric_limits<int32_t>::max()))
+        return numeric_limits<double>::quiet_NaN();
+    int32_t inputLength = static_cast<int32_t>(input.length());
+    UErrorCode status = U_ZERO_ERROR;
+    int32_t parsePosition = 0;
+    UDate date = udat_parse(m_shortDateFormat, input.characters(), inputLength, &parsePosition, &status);
+    if (parsePosition != inputLength || U_FAILURE(status))
+        return numeric_limits<double>::quiet_NaN();
+    // UDate, which is an alias of double, is compatible with our expectation.
+    return date;
+}
+
+String ICULocale::formatLocalizedDate(const DateComponents& dateComponents)
+{
+    if (!initializeShortDateFormat())
+        return String();
+    double input = dateComponents.millisecondsSinceEpoch();
+    UErrorCode status = U_ZERO_ERROR;
+    int32_t length = udat_format(m_shortDateFormat, input, 0, 0, 0, &status);
+    if (status != U_BUFFER_OVERFLOW_ERROR)
+        return String();
+    Vector<UChar> buffer(length);
+    status = U_ZERO_ERROR;
+    udat_format(m_shortDateFormat, input, buffer.data(), length, 0, &status);
+    if (U_FAILURE(status))
+        return String();
+    return String::adopt(buffer);
+}
+
+#if ENABLE(CALENDAR_PICKER)
+PassOwnPtr<Vector<String> > ICULocale::createLabelVector(UDateFormatSymbolType type, int32_t startIndex, int32_t size)
+{
+    if (!m_shortDateFormat)
+        return PassOwnPtr<Vector<String> >();
+    if (udat_countSymbols(m_shortDateFormat, type) != startIndex + size)
+        return PassOwnPtr<Vector<String> >();
+
+    OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>());
+    labels->reserveCapacity(size);
+    for (int32_t i = 0; i < size; ++i) {
+        UErrorCode status = U_ZERO_ERROR;
+        int32_t length = udat_getSymbols(m_shortDateFormat, type, startIndex + i, 0, 0, &status);
+        if (status != U_BUFFER_OVERFLOW_ERROR)
+            return PassOwnPtr<Vector<String> >();
+        Vector<UChar> buffer(length);
+        status = U_ZERO_ERROR;
+        udat_getSymbols(m_shortDateFormat, type, startIndex + i, buffer.data(), length, &status);
+        if (U_FAILURE(status))
+            return PassOwnPtr<Vector<String> >();
+        labels->append(String::adopt(buffer));
+    }
+    return labels.release();
+}
+
+static PassOwnPtr<Vector<String> > createFallbackMonthLabels()
+{
+    OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>());
+    labels->reserveCapacity(12);
+    labels->append("January");
+    labels->append("February");
+    labels->append("March");
+    labels->append("April");
+    labels->append("May");
+    labels->append("June");
+    labels->append("July");
+    labels->append("August");
+    labels->append("September");
+    labels->append("October");
+    labels->append("November");
+    labels->append("December");
+    return labels.release();
+}
+
+static PassOwnPtr<Vector<String> > createFallbackWeekDayShortLabels()
+{
+    OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>());
+    labels->reserveCapacity(7);
+    labels->append("Sun");
+    labels->append("Mon");
+    labels->append("Tue");
+    labels->append("Wed");
+    labels->append("Thu");
+    labels->append("Fri");
+    labels->append("Sat");
+    return labels.release();
+}
+
+void ICULocale::initializeCalendar()
+{
+    if (m_monthLabels && m_weekDayShortLabels)
+        return;
+
+    if (!initializeShortDateFormat()) {
+        m_firstDayOfWeek = 0;
+        m_monthLabels = createFallbackMonthLabels();
+        m_weekDayShortLabels = createFallbackWeekDayShortLabels();
+        return;
+    }
+    m_firstDayOfWeek = ucal_getAttribute(udat_getCalendar(m_shortDateFormat), UCAL_FIRST_DAY_OF_WEEK) - UCAL_SUNDAY;
+
+    m_monthLabels = createLabelVector(UDAT_MONTHS, UCAL_JANUARY, 12);
+    if (!m_monthLabels)
+        m_monthLabels = createFallbackMonthLabels();
+
+    m_weekDayShortLabels = createLabelVector(UDAT_SHORT_WEEKDAYS, UCAL_SUNDAY, 7);
+    if (!m_weekDayShortLabels)
+        m_weekDayShortLabels = createFallbackWeekDayShortLabels();
+}
+
+const Vector<String>& ICULocale::monthLabels()
+{
+    initializeCalendar();
+    return *m_monthLabels;
+}
+
+const Vector<String>& ICULocale::weekDayShortLabels()
+{
+    initializeCalendar();
+    return *m_weekDayShortLabels;
+}
+
+unsigned ICULocale::firstDayOfWeek()
+{
+    initializeCalendar();
+    return m_firstDayOfWeek;
+}
+#endif
+
 } // namespace WebCore
 
index 0a24280..ec2ca5e 100644 (file)
@@ -31,6 +31,8 @@
 #ifndef ICULocale_h
 #define ICULocale_h
 
+#include "DateComponents.h"
+#include <unicode/udat.h>
 #include <unicode/unum.h>
 #include <wtf/Forward.h>
 #include <wtf/OwnPtr.h>
 
 namespace WebCore {
 
-// We should use this class only for LocalizedNumberICU.cpp and LocalizedNumberICUTest.cpp.
+// We should use this class only for LocalizedNumberICU.cpp, LocalizedDateICU.cpp,
+// LocalizedCalendarICU.cpp, and LocalizedNumberICUTest.cpp.
 class ICULocale {
 public:
     static PassOwnPtr<ICULocale> create(const char* localeString);
     static ICULocale* currentLocale();
     ~ICULocale();
+
+    // For LocalizedNumber
     String convertToLocalizedNumber(const String&);
     String convertFromLocalizedNumber(const String&);
 
+    // For LocalizedDate
+    double parseLocalizedDate(const String&);
+    String formatLocalizedDate(const DateComponents&);
+
+#if ENABLE(CALENDAR_PICKER)
+    // For LocalizedCalendar
+    const Vector<String>& monthLabels();
+    const Vector<String>& weekDayShortLabels();
+    unsigned firstDayOfWeek();
+#endif
+
 private:
     static PassOwnPtr<ICULocale> createForCurrentLocale();
     explicit ICULocale(const char*);
@@ -58,8 +74,16 @@ private:
     bool detectSignAndGetDigitRange(const String& input, bool& isNegative, unsigned& startIndex, unsigned& endIndex);
     unsigned matchedDecimalSymbolIndex(const String& input, unsigned& position);
 
+    bool initializeShortDateFormat();
+
+#if ENABLE(CALENDAR_PICKER)
+    PassOwnPtr<Vector<String> > createLabelVector(UDateFormatSymbolType, int32_t startIndex, int32_t size);
+    void initializeCalendar();
+#endif
+
     CString m_locale;
     UNumberFormat* m_numberFormat;
+    UDateFormat* m_shortDateFormat;
     enum {
         // 0-9 for digits.
         DecimalSeparatorIndex = 10,
@@ -72,6 +96,13 @@ private:
     String m_negativePrefix;
     String m_negativeSuffix;
     bool m_didCreateDecimalFormat;
+    bool m_didCreateShortDateFormat;
+
+#if ENABLE(CALENDAR_PICKER)
+    OwnPtr<Vector<String> > m_monthLabels;
+    OwnPtr<Vector<String> > m_weekDayShortLabels;
+    unsigned m_firstDayOfWeek;
+#endif
 };
 
 }
index c3cba30..f781849 100644 (file)
 #include "LocalizedCalendar.h"
 
 #if ENABLE(CALENDAR_PICKER)
-#include "Language.h"
-#include <unicode/ucal.h>
-#include <unicode/udat.h>
-#include <wtf/PassOwnPtr.h>
-#include <wtf/text/CString.h>
+#include "ICULocale.h"
 
 namespace WebCore {
 
-class ScopedDateFormat {
-public:
-    ScopedDateFormat()
-    {
-        UErrorCode status = U_ZERO_ERROR;
-        m_dateFormat = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, defaultLanguage().utf8().data(), 0, -1, 0, -1, &status);
-    }
-
-    ~ScopedDateFormat()
-    {
-        if (m_dateFormat)
-            udat_close(m_dateFormat);
-    }
-
-    UDateFormat* get() const { return m_dateFormat; }
-
-private:
-    UDateFormat* m_dateFormat;
-};
-
-static PassOwnPtr<Vector<String> > createFallbackMonthLabels()
-{
-    OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>());
-    labels->reserveCapacity(12);
-    labels->append("January");
-    labels->append("February");
-    labels->append("March");
-    labels->append("April");
-    labels->append("May");
-    labels->append("June");
-    labels->append("July");
-    labels->append("August");
-    labels->append("September");
-    labels->append("October");
-    labels->append("November");
-    labels->append("December");
-    return labels.release();
-}
-
-static PassOwnPtr<Vector<String> > createLabelVector(UDateFormatSymbolType type, int32_t startIndex, int32_t size)
-{
-    ScopedDateFormat dateFormat;
-    if (!dateFormat.get())
-        return PassOwnPtr<Vector<String> >();
-    if (udat_countSymbols(dateFormat.get(), type) != startIndex + size)
-        return PassOwnPtr<Vector<String> >();
-
-    OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>());
-    labels->reserveCapacity(size);
-    for (int32_t i = 0; i < size; ++i) {
-        UErrorCode status = U_ZERO_ERROR;
-        int32_t length = udat_getSymbols(dateFormat.get(), type, startIndex + i, 0, 0, &status);
-        if (status != U_BUFFER_OVERFLOW_ERROR)
-            return PassOwnPtr<Vector<String> >();
-        Vector<UChar> buffer(length);
-        status = U_ZERO_ERROR;
-        udat_getSymbols(dateFormat.get(), type, startIndex + i, buffer.data(), length, &status);
-        if (U_FAILURE(status))
-            return PassOwnPtr<Vector<String> >();
-        labels->append(String::adopt(buffer));
-    }
-    return labels.release();
-}
-
-static PassOwnPtr<Vector<String> > createMonthLabels()
-{
-    OwnPtr<Vector<String> > labels = createLabelVector(UDAT_MONTHS, UCAL_JANUARY, 12);
-    return labels ? labels.release() : createFallbackMonthLabels();
-}
-
 const Vector<String>& monthLabels()
 {
-    static const Vector<String>* labels = createMonthLabels().leakPtr();
-    return *labels;
-}
-
-static PassOwnPtr<Vector<String> > createFallbackWeekDayShortLabels()
-{
-    OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>());
-    labels->reserveCapacity(7);
-    labels->append("Sun");
-    labels->append("Mon");
-    labels->append("Tue");
-    labels->append("Wed");
-    labels->append("Thu");
-    labels->append("Fri");
-    labels->append("Sat");
-    return labels.release();
-}
-
-static PassOwnPtr<Vector<String> > createWeekDayShortLabels()
-{
-    OwnPtr<Vector<String> > labels = createLabelVector(UDAT_SHORT_WEEKDAYS, UCAL_SUNDAY, 7);
-    return labels ? labels.release() : createFallbackWeekDayShortLabels();
+    return ICULocale::currentLocale()->monthLabels();
 }
 
 const Vector<String>& weekDayShortLabels()
 {
-    static const Vector<String>* labels = createWeekDayShortLabels().leakPtr();
-    return *labels;
-}
-
-static unsigned getFirstDayOfWeek()
-{
-    ScopedDateFormat dateFormat;
-    if (!dateFormat.get())
-        return 0;
-    unsigned firstDay = ucal_getAttribute(udat_getCalendar(dateFormat.get()), UCAL_FIRST_DAY_OF_WEEK) - UCAL_SUNDAY;
-    return firstDay;
+    return ICULocale::currentLocale()->weekDayShortLabels();
 }
 
 unsigned firstDayOfWeek()
 {
-    static unsigned firstDay = getFirstDayOfWeek();
-    return firstDay;
+    return ICULocale::currentLocale()->firstDayOfWeek();
 }
 
 }
index 56999e4..e312d5c 100644 (file)
 #include "config.h"
 #include "LocalizedDate.h"
 
-#include "Language.h"
+#include "ICULocale.h"
 #include <limits>
-#include <unicode/udat.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
-#include <wtf/text/CString.h>
 
-using namespace icu;
 using namespace std;
 
 namespace WebCore {
 
-static inline UDateFormat* createShortDateFormatter()
-{
-    const UChar gmtTimezone[3] = {'G', 'M', 'T'};
-    UErrorCode status = U_ZERO_ERROR;
-    return udat_open(UDAT_NONE, UDAT_SHORT, defaultLanguage().utf8().data(), gmtTimezone, WTF_ARRAY_LENGTH(gmtTimezone), 0, -1, &status);
-}
-
 double parseLocalizedDate(const String& input, DateComponents::Type type)
 {
     switch (type) {
-    case DateComponents::Date: {
-        if (input.length() > static_cast<unsigned>(numeric_limits<int32_t>::max()))
-            break;
-        int32_t inputLength = static_cast<int32_t>(input.length());
-        UDateFormat* dateFormat = createShortDateFormatter();
-        if (!dateFormat)
-            break;
-        UErrorCode status = U_ZERO_ERROR;
-        int32_t parsePosition = 0;
-        UDate date = udat_parse(dateFormat, input.characters(), inputLength, &parsePosition, &status);
-        udat_close(dateFormat);
-        if (parsePosition != inputLength || U_FAILURE(status))
-            break;
-        // UDate, which is an alias of double, is compatible with our expectation.
-        return date;
-    }
+    case DateComponents::Date:
+        return ICULocale::currentLocale()->parseLocalizedDate(input);
     case DateComponents::DateTime:
     case DateComponents::DateTimeLocal:
     case DateComponents::Month:
@@ -83,25 +57,8 @@ double parseLocalizedDate(const String& input, DateComponents::Type type)
 String formatLocalizedDate(const DateComponents& dateComponents)
 {
     switch (dateComponents.type()) {
-    case DateComponents::Date: {
-        UDateFormat* dateFormat = createShortDateFormatter();
-        if (!dateFormat)
-            break;
-        double input = dateComponents.millisecondsSinceEpoch();
-        UErrorCode status = U_ZERO_ERROR;
-        int32_t length = udat_format(dateFormat, input, 0, 0, 0, &status);
-        if (status != U_BUFFER_OVERFLOW_ERROR) {
-            udat_close(dateFormat);
-            break;
-        }
-        Vector<UChar> buffer(length);
-        status = U_ZERO_ERROR;
-        udat_format(dateFormat, input, buffer.data(), length, 0, &status);
-        udat_close(dateFormat);
-        if (U_FAILURE(status))
-            break;
-        return String::adopt(buffer);
-    }
+    case DateComponents::Date:
+        return ICULocale::currentLocale()->formatLocalizedDate(dateComponents);
     case DateComponents::DateTime:
     case DateComponents::DateTimeLocal:
     case DateComponents::Month: