Title: [263900] trunk/Source/WebCore
Revision
263900
Author
[email protected]
Date
2020-07-03 09:45:29 -0700 (Fri, 03 Jul 2020)

Log Message

Convert DateComponents parsing code to use Optional based return values rather than out-parameters
https://bugs.webkit.org/show_bug.cgi?id=213440

Reviewed by Darin Adler.

Rework DateComponents and Date/Time related InputTypes to use Optional based programming
for parsing results. Also take the opportunity to remove unicode upconversion from
DateComponent parsing and instead separate UChar and LChar variants via templates.

* html/BaseDateAndTimeInputType.cpp:
* html/BaseDateAndTimeInputType.h:
* html/DateInputType.cpp:
* html/DateInputType.h:
* html/DateTimeInputType.cpp:
* html/DateTimeInputType.h:
* html/DateTimeLocalInputType.cpp:
* html/DateTimeLocalInputType.h:
* html/HTMLInputElement.cpp:
* html/HTMLInputElement.h:
* html/InputType.cpp:
* html/InputType.h:
* html/MonthInputType.cpp:
* html/MonthInputType.h:
* html/TimeInputType.cpp:
* html/TimeInputType.h:
* html/WeekInputType.cpp:
* html/WeekInputType.h:
    - Removes parseToDateComponentsInternal. No need it and parseToDateComponents.
    - Makes parseToDateComponents pure virtual. The old code had a default implementations
      down in InputType, but it had no callers.
    - Remove iOS vs. non-iOS difference for dateType(). It is now available on InputType
      on all platforms.
    - Make setMillisecondToDateComponents and parseToDateComponents return an Optional.

* platform/DateComponents.cpp:
* platform/DateComponents.h:
    - Replace member function based interfaces for parsing/setting explicit time offsets
      with new factory functions that return Optional<DateComponents>.
    - These factories are implemented using the existing member functions, which are
      now private.
    - Make max/min constants constexpr.
    - Make parse* member functions templates to allow factory parse functions to
      call them without upconverting.
    - Replace header guard with #pragma once.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (263899 => 263900)


--- trunk/Source/WebCore/ChangeLog	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/ChangeLog	2020-07-03 16:45:29 UTC (rev 263900)
@@ -1,5 +1,52 @@
 2020-07-03  Sam Weinig  <[email protected]>
 
+        Convert DateComponents parsing code to use Optional based return values rather than out-parameters
+        https://bugs.webkit.org/show_bug.cgi?id=213440
+
+        Reviewed by Darin Adler.
+
+        Rework DateComponents and Date/Time related InputTypes to use Optional based programming
+        for parsing results. Also take the opportunity to remove unicode upconversion from 
+        DateComponent parsing and instead separate UChar and LChar variants via templates. 
+
+        * html/BaseDateAndTimeInputType.cpp:
+        * html/BaseDateAndTimeInputType.h:
+        * html/DateInputType.cpp:
+        * html/DateInputType.h:
+        * html/DateTimeInputType.cpp:
+        * html/DateTimeInputType.h:
+        * html/DateTimeLocalInputType.cpp:
+        * html/DateTimeLocalInputType.h:
+        * html/HTMLInputElement.cpp:
+        * html/HTMLInputElement.h:
+        * html/InputType.cpp:
+        * html/InputType.h:
+        * html/MonthInputType.cpp:
+        * html/MonthInputType.h:
+        * html/TimeInputType.cpp:
+        * html/TimeInputType.h:
+        * html/WeekInputType.cpp:
+        * html/WeekInputType.h:
+            - Removes parseToDateComponentsInternal. No need it and parseToDateComponents.
+            - Makes parseToDateComponents pure virtual. The old code had a default implementations
+              down in InputType, but it had no callers.
+            - Remove iOS vs. non-iOS difference for dateType(). It is now available on InputType
+              on all platforms. 
+            - Make setMillisecondToDateComponents and parseToDateComponents return an Optional.
+        
+        * platform/DateComponents.cpp:
+        * platform/DateComponents.h:
+            - Replace member function based interfaces for parsing/setting explicit time offsets
+              with new factory functions that return Optional<DateComponents>.
+            - These factories are implemented using the existing member functions, which are
+              now private.
+            - Make max/min constants constexpr.
+            - Make parse* member functions templates to allow factory parse functions to
+              call them without upconverting.
+            - Replace header guard with #pragma once.
+
+2020-07-03  Sam Weinig  <[email protected]>
+
         Cleanup ApplicationCacheManifestParser.h/cpp
         https://bugs.webkit.org/show_bug.cgi?id=213844
 

Modified: trunk/Source/WebCore/html/BaseDateAndTimeInputType.cpp (263899 => 263900)


--- trunk/Source/WebCore/html/BaseDateAndTimeInputType.cpp	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/BaseDateAndTimeInputType.cpp	2020-07-03 16:45:29 UTC (rev 263900)
@@ -78,7 +78,7 @@
 
 bool BaseDateAndTimeInputType::typeMismatchFor(const String& value) const
 {
-    return !value.isEmpty() && !parseToDateComponents(value, 0);
+    return !value.isEmpty() && !parseToDateComponents(value);
 }
 
 bool BaseDateAndTimeInputType::typeMismatch() const
@@ -110,32 +110,22 @@
 
 Decimal BaseDateAndTimeInputType::parseToNumber(const String& source, const Decimal& defaultValue) const
 {
-    DateComponents date;
-    if (!parseToDateComponents(source, &date))
+    auto date = parseToDateComponents(source);
+    if (!date)
         return defaultValue;
-    double msec = date.millisecondsSinceEpoch();
+    double msec = date->millisecondsSinceEpoch();
     ASSERT(std::isfinite(msec));
     return Decimal::fromDouble(msec);
 }
 
-bool BaseDateAndTimeInputType::parseToDateComponents(const String& source, DateComponents* out) const
-{
-    if (source.isEmpty())
-        return false;
-    DateComponents ignoredResult;
-    if (!out)
-        out = &ignoredResult;
-    return parseToDateComponentsInternal(StringView(source).upconvertedCharacters(), source.length(), out);
-}
-
 String BaseDateAndTimeInputType::serialize(const Decimal& value) const
 {
     if (!value.isFinite())
-        return String();
-    DateComponents date;
-    if (!setMillisecondToDateComponents(value.toDouble(), &date))
-        return String();
-    return serializeWithComponents(date);
+        return { };
+    auto date = setMillisecondToDateComponents(value.toDouble());
+    if (!date)
+        return { };
+    return serializeWithComponents(*date);
 }
 
 String BaseDateAndTimeInputType::serializeWithComponents(const DateComponents& date) const
@@ -158,12 +148,12 @@
 
 String BaseDateAndTimeInputType::localizeValue(const String& proposedValue) const
 {
-    DateComponents date;
-    if (!parseToDateComponents(proposedValue, &date))
+    auto date = parseToDateComponents(proposedValue);
+    if (!date)
         return proposedValue;
 
     ASSERT(element());
-    String localized = element()->locale().formatDateTime(date);
+    String localized = element()->locale().formatDateTime(*date);
     return localized.isEmpty() ? proposedValue : localized;
 }
 

Modified: trunk/Source/WebCore/html/BaseDateAndTimeInputType.h (263899 => 263900)


--- trunk/Source/WebCore/html/BaseDateAndTimeInputType.h	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/BaseDateAndTimeInputType.h	2020-07-03 16:45:29 UTC (rev 263900)
@@ -44,11 +44,9 @@
     BaseDateAndTimeInputType(HTMLInputElement& element) : InputType(element) { }
 
     Decimal parseToNumber(const String&, const Decimal&) const override;
-    bool parseToDateComponents(const String&, DateComponents*) const override;
     String sanitizeValue(const String&) const override;
     String serialize(const Decimal&) const override;
     String serializeWithComponents(const DateComponents&) const;
-    virtual bool setMillisecondToDateComponents(double, DateComponents*) const = 0;
     String visibleValue() const override;
     void attributeChanged(const QualifiedName&) override;
 #if PLATFORM(IOS_FAMILY)
@@ -56,10 +54,9 @@
 #endif
 
 private:
-    virtual bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const = 0;
-#if !PLATFORM(IOS_FAMILY)
-    virtual DateComponents::Type dateType() const = 0;
-#endif
+    virtual Optional<DateComponents> parseToDateComponents(const StringView&) const = 0;
+    virtual Optional<DateComponents> setMillisecondToDateComponents(double) const = 0;
+
     double valueAsDate() const override;
     ExceptionOr<void> setValueAsDate(double) const override;
     double valueAsDouble() const override;

Modified: trunk/Source/WebCore/html/DateInputType.cpp (263899 => 263900)


--- trunk/Source/WebCore/html/DateInputType.cpp	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/DateInputType.cpp	2020-07-03 16:45:29 UTC (rev 263900)
@@ -70,17 +70,14 @@
     return StepRange(stepBase, RangeLimitations::Valid, minimum, maximum, step, dateStepDescription);
 }
 
-bool DateInputType::parseToDateComponentsInternal(const UChar* characters, unsigned length, DateComponents* out) const
+Optional<DateComponents> DateInputType::parseToDateComponents(const StringView& source) const
 {
-    ASSERT(out);
-    unsigned end;
-    return out->parseDate(characters, length, 0, end) && end == length;
+    return DateComponents::fromParsingDate(source);
 }
 
-bool DateInputType::setMillisecondToDateComponents(double value, DateComponents* date) const
+Optional<DateComponents> DateInputType::setMillisecondToDateComponents(double value) const
 {
-    ASSERT(date);
-    return date->setMillisecondsSinceEpochForDate(value);
+    return DateComponents::fromMillisecondsSinceEpochForDate(value);
 }
 
 bool DateInputType::isDateField() const

Modified: trunk/Source/WebCore/html/DateInputType.h (263899 => 263900)


--- trunk/Source/WebCore/html/DateInputType.h	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/DateInputType.h	2020-07-03 16:45:29 UTC (rev 263900)
@@ -44,8 +44,8 @@
     const AtomString& formControlType() const override;
     DateComponents::Type dateType() const override;
     StepRange createStepRange(AnyStepHandling) const override;
-    bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const override;
-    bool setMillisecondToDateComponents(double, DateComponents*) const override;
+    Optional<DateComponents> parseToDateComponents(const StringView&) const override;
+    Optional<DateComponents> setMillisecondToDateComponents(double) const override;
     bool isDateField() const override;
 };
 

Modified: trunk/Source/WebCore/html/DateTimeInputType.cpp (263899 => 263900)


--- trunk/Source/WebCore/html/DateTimeInputType.cpp	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/DateTimeInputType.cpp	2020-07-03 16:45:29 UTC (rev 263900)
@@ -69,17 +69,14 @@
     return StepRange(stepBase, RangeLimitations::Valid, minimum, maximum, step, dateTimeStepDescription);
 }
 
-bool DateTimeInputType::parseToDateComponentsInternal(const UChar* characters, unsigned length, DateComponents* out) const
+Optional<DateComponents> DateTimeInputType::parseToDateComponents(const StringView& source) const
 {
-    ASSERT(out);
-    unsigned end;
-    return out->parseDateTime(characters, length, 0, end) && end == length;
+    return DateComponents::fromParsingDateTime(source);
 }
 
-bool DateTimeInputType::setMillisecondToDateComponents(double value, DateComponents* date) const
+Optional<DateComponents> DateTimeInputType::setMillisecondToDateComponents(double value) const
 {
-    ASSERT(date);
-    return date->setMillisecondsSinceEpochForDateTime(value);
+    return DateComponents::fromMillisecondsSinceEpochForDateTime(value);
 }
 
 bool DateTimeInputType::isDateTimeField() const
@@ -89,10 +86,10 @@
 
 String DateTimeInputType::sanitizeValue(const String& proposedValue) const
 {
-    DateComponents date;
-    if (!parseToDateComponents(proposedValue, &date))
-        return String();
-    return date.toString();
+    auto date = parseToDateComponents(proposedValue);
+    if (!date)
+        return { };
+    return date->toString();
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/html/DateTimeInputType.h (263899 => 263900)


--- trunk/Source/WebCore/html/DateTimeInputType.h	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/DateTimeInputType.h	2020-07-03 16:45:29 UTC (rev 263900)
@@ -46,8 +46,8 @@
     DateComponents::Type dateType() const override;
     StepRange createStepRange(AnyStepHandling) const override;
     Decimal defaultValueForStepUp() const override;
-    bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const override;
-    bool setMillisecondToDateComponents(double, DateComponents*) const override;
+    Optional<DateComponents> parseToDateComponents(const StringView&) const override;
+    Optional<DateComponents> setMillisecondToDateComponents(double) const override;
     bool isDateTimeField() const override;
     String sanitizeValue(const String&) const override;
 };

Modified: trunk/Source/WebCore/html/DateTimeLocalInputType.cpp (263899 => 263900)


--- trunk/Source/WebCore/html/DateTimeLocalInputType.cpp	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/DateTimeLocalInputType.cpp	2020-07-03 16:45:29 UTC (rev 263900)
@@ -78,17 +78,14 @@
     return StepRange(stepBase, RangeLimitations::Valid, minimum, maximum, step, dateTimeLocalStepDescription);
 }
 
-bool DateTimeLocalInputType::parseToDateComponentsInternal(const UChar* characters, unsigned length, DateComponents* out) const
+Optional<DateComponents> DateTimeLocalInputType::parseToDateComponents(const StringView& source) const
 {
-    ASSERT(out);
-    unsigned end;
-    return out->parseDateTimeLocal(characters, length, 0, end) && end == length;
+    return DateComponents::fromParsingDateTimeLocal(source);
 }
 
-bool DateTimeLocalInputType::setMillisecondToDateComponents(double value, DateComponents* date) const
+Optional<DateComponents> DateTimeLocalInputType::setMillisecondToDateComponents(double value) const
 {
-    ASSERT(date);
-    return date->setMillisecondsSinceEpochForDateTimeLocal(value);
+    return DateComponents::fromMillisecondsSinceEpochForDateTimeLocal(value);
 }
 
 bool DateTimeLocalInputType::isDateTimeLocalField() const

Modified: trunk/Source/WebCore/html/DateTimeLocalInputType.h (263899 => 263900)


--- trunk/Source/WebCore/html/DateTimeLocalInputType.h	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/DateTimeLocalInputType.h	2020-07-03 16:45:29 UTC (rev 263900)
@@ -46,8 +46,8 @@
     double valueAsDate() const final;
     ExceptionOr<void> setValueAsDate(double) const final;
     StepRange createStepRange(AnyStepHandling) const final;
-    bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const final;
-    bool setMillisecondToDateComponents(double, DateComponents*) const final;
+    Optional<DateComponents> parseToDateComponents(const StringView&) const final;
+    Optional<DateComponents> setMillisecondToDateComponents(double) const final;
     bool isDateTimeLocalField() const final;
 };
 

Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (263899 => 263900)


--- trunk/Source/WebCore/html/HTMLInputElement.cpp	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp	2020-07-03 16:45:29 UTC (rev 263900)
@@ -1674,12 +1674,10 @@
     return m_inputType->isSteppable();
 }
 
-#if PLATFORM(IOS_FAMILY)
 DateComponents::Type HTMLInputElement::dateType() const
 {
     return m_inputType->dateType();
 }
-#endif
 
 bool HTMLInputElement::isTextButton() const
 {

Modified: trunk/Source/WebCore/html/HTMLInputElement.h (263899 => 263900)


--- trunk/Source/WebCore/html/HTMLInputElement.h	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/HTMLInputElement.h	2020-07-03 16:45:29 UTC (rev 263900)
@@ -24,6 +24,7 @@
 
 #pragma once
 
+#include "DateComponents.h"
 #include "FileChooser.h"
 #include "HTMLTextFormControlElement.h"
 #include "StepRange.h"
@@ -30,10 +31,6 @@
 #include <memory>
 #include <wtf/WeakPtr.h>
 
-#if PLATFORM(IOS_FAMILY)
-#include "DateComponents.h"
-#endif
-
 namespace WebCore {
 
 class DragData;
@@ -131,9 +128,7 @@
     WEBCORE_EXPORT bool isTimeField() const;
     WEBCORE_EXPORT bool isWeekField() const;
 
-#if PLATFORM(IOS_FAMILY)
     DateComponents::Type dateType() const;
-#endif
 
     HTMLElement* containerElement() const;
     

Modified: trunk/Source/WebCore/html/InputType.cpp (263899 => 263900)


--- trunk/Source/WebCore/html/InputType.cpp	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/InputType.cpp	2020-07-03 16:45:29 UTC (rev 263900)
@@ -522,12 +522,6 @@
     return parseToNumber(string, Decimal::nan());
 }
 
-bool InputType::parseToDateComponents(const String&, DateComponents*) const
-{
-    ASSERT_NOT_REACHED();
-    return false;
-}
-
 String InputType::serialize(const Decimal&) const
 {
     ASSERT_NOT_REACHED();
@@ -534,12 +528,10 @@
     return String();
 }
 
-#if PLATFORM(IOS_FAMILY)
 DateComponents::Type InputType::dateType() const
 {
     return DateComponents::Invalid;
 }
-#endif
 
 void InputType::dispatchSimulatedClickIfActive(KeyboardEvent& event) const
 {

Modified: trunk/Source/WebCore/html/InputType.h (263899 => 263900)


--- trunk/Source/WebCore/html/InputType.h	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/InputType.h	2020-07-03 16:45:29 UTC (rev 263900)
@@ -282,12 +282,6 @@
     // return NaN or Infinity only if defaultValue is NaN or Infinity.
     virtual Decimal parseToNumber(const String&, const Decimal& defaultValue) const;
 
-    // Parses the specified string for this InputType, and returns true if it
-    // is successfully parsed. An instance pointed by the DateComponents*
-    // parameter will have parsed values and be modified even if the parsing
-    // fails. The DateComponents* parameter may be null.
-    virtual bool parseToDateComponents(const String&, DateComponents*) const;
-
     // Create a string representation of the specified Decimal value for the
     // input type. If NaN or Infinity is specified, this returns an empty
     // string. This should not be called for types without valueAsNumber.
@@ -309,9 +303,8 @@
     virtual bool receiveDroppedFiles(const DragData&);
 #endif
 
-#if PLATFORM(IOS_FAMILY)
     virtual DateComponents::Type dateType() const;
-#endif
+
     virtual String displayString() const;
 
 protected:

Modified: trunk/Source/WebCore/html/MonthInputType.cpp (263899 => 263900)


--- trunk/Source/WebCore/html/MonthInputType.cpp	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/MonthInputType.cpp	2020-07-03 16:45:29 UTC (rev 263900)
@@ -61,10 +61,10 @@
 double MonthInputType::valueAsDate() const
 {
     ASSERT(element());
-    DateComponents date;
-    if (!parseToDateComponents(element()->value(), &date))
+    auto date = parseToDateComponents(element()->value());
+    if (!date)
         return DateComponents::invalidMilliseconds();
-    double msec = date.millisecondsSinceEpoch();
+    double msec = date->millisecondsSinceEpoch();
     ASSERT(std::isfinite(msec));
     return msec;
 }
@@ -71,10 +71,10 @@
 
 String MonthInputType::serializeWithMilliseconds(double value) const
 {
-    DateComponents date;
-    if (!date.setMillisecondsSinceEpochForMonth(value))
-        return String();
-    return serializeWithComponents(date);
+    auto date = DateComponents::fromMillisecondsSinceEpochForMonth(value);
+    if (!date)
+        return { };
+    return serializeWithComponents(*date);
 }
 
 Decimal MonthInputType::defaultValueForStepUp() const
@@ -83,9 +83,11 @@
     int offset = calculateLocalTimeOffset(current).offset / msPerMinute;
     current += offset * msPerMinute;
 
-    DateComponents date;
-    date.setMillisecondsSinceEpochForMonth(current);
-    double months = date.monthsSinceEpoch();
+    auto date = DateComponents::fromMillisecondsSinceEpochForMonth(current);
+    if (!date)
+        return  { };
+
+    double months = date->monthsSinceEpoch();
     ASSERT(std::isfinite(months));
     return Decimal::fromDouble(months);
 }
@@ -102,25 +104,22 @@
 
 Decimal MonthInputType::parseToNumber(const String& src, const Decimal& defaultValue) const
 {
-    DateComponents date;
-    if (!parseToDateComponents(src, &date))
+    auto date = parseToDateComponents(src);
+    if (!date)
         return defaultValue;
-    double months = date.monthsSinceEpoch();
+    double months = date->monthsSinceEpoch();
     ASSERT(std::isfinite(months));
     return Decimal::fromDouble(months);
 }
 
-bool MonthInputType::parseToDateComponentsInternal(const UChar* characters, unsigned length, DateComponents* out) const
+Optional<DateComponents> MonthInputType::parseToDateComponents(const StringView& source) const
 {
-    ASSERT(out);
-    unsigned end;
-    return out->parseMonth(characters, length, 0, end) && end == length;
+    return DateComponents::fromParsingMonth(source);
 }
 
-bool MonthInputType::setMillisecondToDateComponents(double value, DateComponents* date) const
+Optional<DateComponents> MonthInputType::setMillisecondToDateComponents(double value) const
 {
-    ASSERT(date);
-    return date->setMonthsSinceEpoch(value);
+    return DateComponents::fromMonthsSinceEpoch(value);
 }
 
 bool MonthInputType::isMonthField() const

Modified: trunk/Source/WebCore/html/MonthInputType.h (263899 => 263900)


--- trunk/Source/WebCore/html/MonthInputType.h	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/MonthInputType.h	2020-07-03 16:45:29 UTC (rev 263900)
@@ -48,8 +48,8 @@
     Decimal parseToNumber(const String&, const Decimal&) const override;
     Decimal defaultValueForStepUp() const override;
     StepRange createStepRange(AnyStepHandling) const override;
-    bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const override;
-    bool setMillisecondToDateComponents(double, DateComponents*) const override;
+    Optional<DateComponents> parseToDateComponents(const StringView&) const override;
+    Optional<DateComponents> setMillisecondToDateComponents(double) const override;
     bool isMonthField() const override;
 };
 

Modified: trunk/Source/WebCore/html/TimeInputType.cpp (263899 => 263900)


--- trunk/Source/WebCore/html/TimeInputType.cpp	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/TimeInputType.cpp	2020-07-03 16:45:29 UTC (rev 263900)
@@ -68,9 +68,11 @@
     int offset = calculateLocalTimeOffset(current).offset / msPerMinute;
     current += offset * msPerMinute;
 
-    DateComponents date;
-    date.setMillisecondsSinceMidnight(current);
-    double milliseconds = date.millisecondsSinceEpoch();
+    auto date = DateComponents::fromMillisecondsSinceMidnight(current);
+    if (!date)
+        return  { };
+
+    double milliseconds = date->millisecondsSinceEpoch();
     ASSERT(std::isfinite(milliseconds));
     return Decimal::fromDouble(milliseconds);
 }
@@ -85,17 +87,14 @@
     return StepRange(stepBase, RangeLimitations::Valid, minimum, maximum, step, timeStepDescription);
 }
 
-bool TimeInputType::parseToDateComponentsInternal(const UChar* characters, unsigned length, DateComponents* out) const
+Optional<DateComponents> TimeInputType::parseToDateComponents(const StringView& source) const
 {
-    ASSERT(out);
-    unsigned end;
-    return out->parseTime(characters, length, 0, end) && end == length;
+    return DateComponents::fromParsingTime(source);
 }
 
-bool TimeInputType::setMillisecondToDateComponents(double value, DateComponents* date) const
+Optional<DateComponents> TimeInputType::setMillisecondToDateComponents(double value) const
 {
-    ASSERT(date);
-    return date->setMillisecondsSinceMidnight(value);
+    return DateComponents::fromMillisecondsSinceMidnight(value);
 }
 
 bool TimeInputType::isTimeField() const

Modified: trunk/Source/WebCore/html/TimeInputType.h (263899 => 263900)


--- trunk/Source/WebCore/html/TimeInputType.h	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/TimeInputType.h	2020-07-03 16:45:29 UTC (rev 263900)
@@ -45,8 +45,8 @@
     DateComponents::Type dateType() const override;
     Decimal defaultValueForStepUp() const override;
     StepRange createStepRange(AnyStepHandling) const override;
-    bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const override;
-    bool setMillisecondToDateComponents(double, DateComponents*) const override;
+    Optional<DateComponents> parseToDateComponents(const StringView&) const override;
+    Optional<DateComponents> setMillisecondToDateComponents(double) const override;
     bool isTimeField() const override;
 };
 

Modified: trunk/Source/WebCore/html/WeekInputType.cpp (263899 => 263900)


--- trunk/Source/WebCore/html/WeekInputType.cpp	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/WeekInputType.cpp	2020-07-03 16:45:29 UTC (rev 263900)
@@ -65,17 +65,14 @@
     return StepRange(stepBase, RangeLimitations::Valid, minimum, maximum, step, weekStepDescription);
 }
 
-bool WeekInputType::parseToDateComponentsInternal(const UChar* characters, unsigned length, DateComponents* out) const
+Optional<DateComponents> WeekInputType::parseToDateComponents(const StringView& source) const
 {
-    ASSERT(out);
-    unsigned end;
-    return out->parseWeek(characters, length, 0, end) && end == length;
+    return DateComponents::fromParsingWeek(source);
 }
 
-bool WeekInputType::setMillisecondToDateComponents(double value, DateComponents* date) const
+Optional<DateComponents> WeekInputType::setMillisecondToDateComponents(double value) const
 {
-    ASSERT(date);
-    return date->setMillisecondsSinceEpochForWeek(value);
+    return DateComponents::fromMillisecondsSinceEpochForWeek(value);
 }
 
 bool WeekInputType::isWeekField() const

Modified: trunk/Source/WebCore/html/WeekInputType.h (263899 => 263900)


--- trunk/Source/WebCore/html/WeekInputType.h	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/html/WeekInputType.h	2020-07-03 16:45:29 UTC (rev 263900)
@@ -44,8 +44,8 @@
     const AtomString& formControlType() const override;
     DateComponents::Type dateType() const override;
     StepRange createStepRange(AnyStepHandling) const override;
-    bool parseToDateComponentsInternal(const UChar*, unsigned length, DateComponents*) const override;
-    bool setMillisecondToDateComponents(double, DateComponents*) const override;
+    Optional<DateComponents> parseToDateComponents(const StringView&) const override;
+    Optional<DateComponents> setMillisecondToDateComponents(double) const override;
     bool isWeekField() const override;
 };
 

Modified: trunk/Source/WebCore/platform/DateComponents.cpp (263899 => 263900)


--- trunk/Source/WebCore/platform/DateComponents.cpp	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/platform/DateComponents.cpp	2020-07-03 16:45:29 UTC (rev 263900)
@@ -96,7 +96,7 @@
     return day == Thursday || (day == Wednesday && isLeapYear(m_year)) ? maximumWeekNumber : maximumWeekNumber - 1;
 }
 
-static unsigned countDigits(const UChar* src, unsigned length, unsigned start)
+template<typename CharacterType> static unsigned countDigits(const CharacterType* src, unsigned length, unsigned start)
 {
     unsigned index = start;
     for (; index < length; ++index) {
@@ -107,13 +107,13 @@
 }
 
 // Very strict integer parser. Do not allow leading or trailing whitespace unlike charactersToIntStrict().
-static bool toInt(const UChar* src, unsigned length, unsigned parseStart, unsigned parseLength, int& out)
+template<typename CharacterType> static bool toInt(const CharacterType* src, unsigned length, unsigned parseStart, unsigned parseLength, int& out)
 {
     if (parseStart + parseLength > length || parseLength <= 0)
         return false;
     int value = 0;
-    const UChar* current = src + parseStart;
-    const UChar* end = current + parseLength;
+    auto current = src + parseStart;
+    auto end = current + parseLength;
 
     // We don't need to handle negative numbers for ISO 8601.
     for (; current < end; ++current) {
@@ -128,7 +128,7 @@
     return true;
 }
 
-bool DateComponents::parseYear(const UChar* src, unsigned length, unsigned start, unsigned& end)
+template<typename CharacterType> bool DateComponents::parseYear(const CharacterType* src, unsigned length, unsigned start, unsigned& end)
 {
     unsigned digitsLength = countDigits(src, length, start);
     // Needs at least 4 digits according to the standard.
@@ -180,6 +180,67 @@
     return !hour && !minute && !second && !millisecond;
 }
 
+template<typename F> static Optional<DateComponents> createFromString(StringView source, F&& parseFunction)
+{
+    if (source.isEmpty())
+        return WTF::nullopt;
+
+    DateComponents result;
+    unsigned end;
+    if (source.is8Bit()) {
+        if (!parseFunction(result, source.characters8(), source.length(), end))
+            return WTF::nullopt;
+    } else {
+        if (!parseFunction(result, source.characters16(), source.length(), end))
+            return WTF::nullopt;
+    }
+    if (end != source.length())
+        return WTF::nullopt;
+    return result;
+}
+
+Optional<DateComponents> DateComponents::fromParsingMonth(StringView source)
+{
+    return createFromString(source, [] (auto& date, const auto* src, auto length, auto& end) {
+        return date.parseMonth(src, length, 0, end);
+    });
+}
+
+Optional<DateComponents> DateComponents::fromParsingDate(StringView source)
+{
+    return createFromString(source, [] (auto& date, const auto* src, auto length, auto& end) {
+        return date.parseDate(src, length, 0, end);
+    });
+}
+
+Optional<DateComponents> DateComponents::fromParsingWeek(StringView source)
+{
+    return createFromString(source, [] (auto& date, const auto* src, auto length, auto& end) {
+        return date.parseWeek(src, length, 0, end);
+    });
+}
+
+Optional<DateComponents> DateComponents::fromParsingTime(StringView source)
+{
+    return createFromString(source, [] (auto& date, const auto* src, auto length, auto& end) {
+        return date.parseTime(src, length, 0, end);
+    });
+}
+
+Optional<DateComponents> DateComponents::fromParsingDateTimeLocal(StringView source)
+{
+    return createFromString(source, [] (auto& date, const auto* src, auto length, auto& end) {
+        return date.parseDateTimeLocal(src, length, 0, end);
+    });
+}
+
+Optional<DateComponents> DateComponents::fromParsingDateTime(StringView source)
+{
+    return createFromString(source, [] (auto& date, const auto* src, auto length, auto& end) {
+        return date.parseDateTime(src, length, 0, end);
+    });
+}
+
 bool DateComponents::addDay(int dayDiff)
 {
     ASSERT(m_monthDay);
@@ -283,7 +344,7 @@
 }
 
 // Parses a timezone part, and adjust year, month, monthDay, hour, minute, second, millisecond.
-bool DateComponents::parseTimeZone(const UChar* src, unsigned length, unsigned start, unsigned& end)
+template<typename CharacterType> bool DateComponents::parseTimeZone(const CharacterType* src, unsigned length, unsigned start, unsigned& end)
 {
     if (start >= length)
         return false;
@@ -328,7 +389,7 @@
     return true;
 }
 
-bool DateComponents::parseMonth(const UChar* src, unsigned length, unsigned start, unsigned& end)
+template<typename CharacterType> bool DateComponents::parseMonth(const CharacterType* src, unsigned length, unsigned start, unsigned& end)
 {
     ASSERT(src);
     unsigned index;
@@ -350,7 +411,7 @@
     return true;
 }
 
-bool DateComponents::parseDate(const UChar* src, unsigned length, unsigned start, unsigned& end)
+template<typename CharacterType> bool DateComponents::parseDate(const CharacterType* src, unsigned length, unsigned start, unsigned& end)
 {
     ASSERT(src);
     unsigned index;
@@ -374,7 +435,7 @@
     return true;
 }
 
-bool DateComponents::parseWeek(const UChar* src, unsigned length, unsigned start, unsigned& end)
+template<typename CharacterType> bool DateComponents::parseWeek(const CharacterType* src, unsigned length, unsigned start, unsigned& end)
 {
     ASSERT(src);
     unsigned index;
@@ -402,7 +463,7 @@
     return true;
 }
 
-bool DateComponents::parseTime(const UChar* src, unsigned length, unsigned start, unsigned& end)
+template<typename CharacterType> bool DateComponents::parseTime(const CharacterType* src, unsigned length, unsigned start, unsigned& end)
 {
     ASSERT(src);
     int hour;
@@ -457,7 +518,7 @@
     return true;
 }
 
-bool DateComponents::parseDateTimeLocal(const UChar* src, unsigned length, unsigned start, unsigned& end)
+template<typename CharacterType> bool DateComponents::parseDateTimeLocal(const CharacterType* src, unsigned length, unsigned start, unsigned& end)
 {
     ASSERT(src);
     unsigned index;
@@ -476,7 +537,7 @@
     return true;
 }
 
-bool DateComponents::parseDateTime(const UChar* src, unsigned length, unsigned start, unsigned& end)
+template<typename CharacterType> bool DateComponents::parseDateTime(const CharacterType* src, unsigned length, unsigned start, unsigned& end)
 {
     ASSERT(src);
     unsigned index;
@@ -503,6 +564,63 @@
     return remainder < 0 ? remainder + divider : remainder;
 }
 
+template<typename F> static Optional<DateComponents> createFromTimeOffset(double timeOffset, F&& function)
+{
+    DateComponents result;
+    if (!function(result, timeOffset))
+        return WTF::nullopt;
+    return result;
+}
+
+Optional<DateComponents> DateComponents::fromMillisecondsSinceEpochForDate(double ms)
+{
+    return createFromTimeOffset(ms, [] (auto& date, auto ms) {
+        return date.setMillisecondsSinceEpochForDate(ms);
+    });
+}
+
+Optional<DateComponents> DateComponents::fromMillisecondsSinceEpochForDateTime(double ms)
+{
+    return createFromTimeOffset(ms, [] (auto& date, auto ms) {
+        return date.setMillisecondsSinceEpochForDateTime(ms);
+    });
+}
+
+Optional<DateComponents> DateComponents::fromMillisecondsSinceEpochForDateTimeLocal(double ms)
+{
+    return createFromTimeOffset(ms, [] (auto& date, auto ms) {
+        return date.setMillisecondsSinceEpochForDateTimeLocal(ms);
+    });
+}
+
+Optional<DateComponents> DateComponents::fromMillisecondsSinceEpochForMonth(double ms)
+{
+    return createFromTimeOffset(ms, [] (auto& date, auto ms) {
+        return date.setMillisecondsSinceEpochForMonth(ms);
+    });
+}
+
+Optional<DateComponents> DateComponents::fromMillisecondsSinceEpochForWeek(double ms)
+{
+    return createFromTimeOffset(ms, [] (auto& date, auto ms) {
+        return date.setMillisecondsSinceEpochForWeek(ms);
+    });
+}
+
+Optional<DateComponents> DateComponents::fromMillisecondsSinceMidnight(double ms)
+{
+    return createFromTimeOffset(ms, [] (auto& date, auto ms) {
+        return date.setMillisecondsSinceMidnight(ms);
+    });
+}
+
+Optional<DateComponents> DateComponents::fromMonthsSinceEpoch(double months)
+{
+    return createFromTimeOffset(months, [] (auto& date, auto months) {
+        return date.setMonthsSinceEpoch(months);
+    });
+}
+
 void DateComponents::setMillisecondsSinceMidnightInternal(double msInDay)
 {
     ASSERT(msInDay >= 0 && msInDay < msPerDay);

Modified: trunk/Source/WebCore/platform/DateComponents.h (263899 => 263900)


--- trunk/Source/WebCore/platform/DateComponents.h	2020-07-03 15:09:38 UTC (rev 263899)
+++ trunk/Source/WebCore/platform/DateComponents.h	2020-07-03 16:45:29 UTC (rev 263900)
@@ -28,8 +28,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef DateComponents_h
-#define DateComponents_h
+#pragma once
 
 #include <limits>
 #include <unicode/utypes.h>
@@ -86,101 +85,109 @@
 
     // Returns an ISO 8601 representation for this instance.
     // The format argument is valid for DateTime, DateTimeLocal, and Time types.
-    String toString(SecondFormat format = None) const;
+    String toString(SecondFormat = None) const;
 
-    // parse*() and setMillisecondsSince*() functions are initializers for an
-    // DateComponents instance. If these functions return false, the instance
-    // might be invalid.
-
-    // The following six functions parse the input 'src' whose length is
-    // 'length', and updates some fields of this instance. The parsing starts at
-    // src[start] and examines characters before src[length].
-    // 'src' must be non-null. The 'src' string doesn't need to be
-    // null-terminated.
-    // The functions return true if the parsing succeeds, and set 'end' to the
-    // next index after the last consumed. Extra leading characters cause parse
-    // failures, and the trailing extra characters don't cause parse failures.
-
     // Sets year and month.
-    bool parseMonth(const UChar* src, unsigned length, unsigned start, unsigned& end);
+    static Optional<DateComponents> fromParsingMonth(StringView);
     // Sets year, month and monthDay.
-    bool parseDate(const UChar* src, unsigned length, unsigned start, unsigned& end);
+    static Optional<DateComponents> fromParsingDate(StringView);
     // Sets year and week.
-    bool parseWeek(const UChar* src, unsigned length, unsigned start, unsigned& end);
+    static Optional<DateComponents> fromParsingWeek(StringView);
     // Sets hour, minute, second and millisecond.
-    bool parseTime(const UChar* src, unsigned length, unsigned start, unsigned& end);
+    static Optional<DateComponents> fromParsingTime(StringView);
     // Sets year, month, monthDay, hour, minute, second and millisecond.
-    bool parseDateTimeLocal(const UChar* src, unsigned length, unsigned start, unsigned& end);
+    static Optional<DateComponents> fromParsingDateTimeLocal(StringView);
     // Sets year, month, monthDay, hour, minute, second and millisecond, and adjusts timezone.
-    bool parseDateTime(const UChar* src, unsigned length, unsigned start, unsigned& end);
+    static Optional<DateComponents> fromParsingDateTime(StringView);
 
-    // The following setMillisecondsSinceEpochFor*() functions take
-    // the number of milliseconds since 1970-01-01 00:00:00.000 UTC as
-    // the argument, and update all fields for the corresponding
-    // DateComponents type. The functions return true if it succeeds, and
-    // false if they fail.
 
     // For Date type. Updates m_year, m_month and m_monthDay.
-    bool setMillisecondsSinceEpochForDate(double ms);
+    static Optional<DateComponents> fromMillisecondsSinceEpochForDate(double ms);
     // For DateTime type. Updates m_year, m_month, m_monthDay, m_hour, m_minute, m_second and m_millisecond.
-    bool setMillisecondsSinceEpochForDateTime(double ms);
+    static Optional<DateComponents> fromMillisecondsSinceEpochForDateTime(double ms);
     // For DateTimeLocal type. Updates m_year, m_month, m_monthDay, m_hour, m_minute, m_second and m_millisecond.
-    bool setMillisecondsSinceEpochForDateTimeLocal(double ms);
+    static Optional<DateComponents> fromMillisecondsSinceEpochForDateTimeLocal(double ms);
     // For Month type. Updates m_year and m_month.
-    bool setMillisecondsSinceEpochForMonth(double ms);
+    static Optional<DateComponents> fromMillisecondsSinceEpochForMonth(double ms);
     // For Week type. Updates m_year and m_week.
-    bool setMillisecondsSinceEpochForWeek(double ms);
+    static Optional<DateComponents> fromMillisecondsSinceEpochForWeek(double ms);
 
     // For Time type. Updates m_hour, m_minute, m_second and m_millisecond.
-    bool setMillisecondsSinceMidnight(double ms);
+    static Optional<DateComponents> fromMillisecondsSinceMidnight(double ms);
 
     // Another initializer for Month type. Updates m_year and m_month.
-    bool setMonthsSinceEpoch(double months);
+    static Optional<DateComponents> fromMonthsSinceEpoch(double months);
 
     // Returns the number of milliseconds from 1970-01-01 00:00:00 UTC.
     // For a DateComponents initialized with parseDateTimeLocal(),
     // millisecondsSinceEpoch() returns a value for UTC timezone.
     double millisecondsSinceEpoch() const;
+
     // Returns the number of months from 1970-01.
     // Do not call this for types other than Month.
     double monthsSinceEpoch() const;
+
     static inline double invalidMilliseconds() { return std::numeric_limits<double>::quiet_NaN(); }
 
     // Minimum and maxmimum limits for setMillisecondsSince*(),
     // setMonthsSinceEpoch(), millisecondsSinceEpoch(), and monthsSinceEpoch().
-    static inline double minimumDate() { return -62135596800000.0; } // 0001-01-01T00:00Z
-    static inline double minimumDateTime() { return -62135596800000.0; } // ditto.
-    static inline double minimumMonth() { return (1 - 1970) * 12.0 + 1 - 1; } // 0001-01
-    static inline double minimumTime() { return 0; } // 00:00:00.000
-    static inline double minimumWeek() { return -62135596800000.0; } // 0001-01-01, the first Monday of 0001.
-    static inline double maximumDate() { return 8640000000000000.0; } // 275760-09-13T00:00Z
-    static inline double maximumDateTime() { return 8640000000000000.0; } // ditto.
-    static inline double maximumMonth() { return (275760 - 1970) * 12.0 + 9 - 1; } // 275760-09
-    static inline double maximumTime() { return 86399999; } // 23:59:59.999
-    static inline double maximumWeek() { return 8639999568000000.0; } // 275760-09-08, the Monday of the week including 275760-09-13.
+    static constexpr inline double minimumDate() { return -62135596800000.0; } // 0001-01-01T00:00Z
+    static constexpr inline double minimumDateTime() { return -62135596800000.0; } // ditto.
+    static constexpr inline double minimumMonth() { return (1 - 1970) * 12.0 + 1 - 1; } // 0001-01
+    static constexpr inline double minimumTime() { return 0; } // 00:00:00.000
+    static constexpr inline double minimumWeek() { return -62135596800000.0; } // 0001-01-01, the first Monday of 0001.
+    static constexpr inline double maximumDate() { return 8640000000000000.0; } // 275760-09-13T00:00Z
+    static constexpr inline double maximumDateTime() { return 8640000000000000.0; } // ditto.
+    static constexpr inline double maximumMonth() { return (275760 - 1970) * 12.0 + 9 - 1; } // 275760-09
+    static constexpr inline double maximumTime() { return 86399999; } // 23:59:59.999
+    static constexpr inline double maximumWeek() { return 8639999568000000.0; } // 275760-09-08, the Monday of the week including 275760-09-13.
 
     // HTML5 uses ISO-8601 format with year >= 1. Gregorian calendar started in
     // 1582. However, we need to support 0001-01-01 in Gregorian calendar rule.
     static inline int minimumYear() { return 1; }
+
     // Date in ECMAScript can't represent dates later than 275760-09-13T00:00Z.
     // So, we have the same upper limit in HTML5 date/time types.
     static inline int maximumYear() { return 275760; }
+
     static const int minimumWeekNumber;
     static const int maximumWeekNumber;
 
 private:
+    template<typename CharacterType> bool parseMonth(const CharacterType* src, unsigned length, unsigned start, unsigned& end);
+    template<typename CharacterType> bool parseDate(const CharacterType* src, unsigned length, unsigned start, unsigned& end);
+    template<typename CharacterType> bool parseWeek(const CharacterType* src, unsigned length, unsigned start, unsigned& end);
+    template<typename CharacterType> bool parseTime(const CharacterType* src, unsigned length, unsigned start, unsigned& end);
+    template<typename CharacterType> bool parseDateTimeLocal(const CharacterType* src, unsigned length, unsigned start, unsigned& end);
+    template<typename CharacterType> bool parseDateTime(const CharacterType* src, unsigned length, unsigned start, unsigned& end);
+    template<typename CharacterType> bool parseYear(const CharacterType* src, unsigned length, unsigned start, unsigned& end);
+    template<typename CharacterType> bool parseTimeZone(const CharacterType* src, unsigned length, unsigned start, unsigned& end);
+
+    // The following setMillisecondsSinceEpochFor*() functions take
+    // the number of milliseconds since 1970-01-01 00:00:00.000 UTC as
+    // the argument, and update all fields for the corresponding
+    // DateComponents type. The functions return true if it succeeds, and
+    // false if they fail.
+    bool setMillisecondsSinceEpochForDate(double);
+    bool setMillisecondsSinceEpochForDateTime(double);
+    bool setMillisecondsSinceEpochForDateTimeLocal(double);
+    bool setMillisecondsSinceEpochForMonth(double);
+    bool setMillisecondsSinceEpochForWeek(double);
+    bool setMillisecondsSinceMidnight(double);
+    bool setMonthsSinceEpoch(double);
+    bool setMillisecondsSinceEpochForDateInternal(double);
+    void setMillisecondsSinceMidnightInternal(double);
+
     // Returns the maximum week number in this DateComponents's year.
     // The result is either of 52 and 53.
     int maxWeekNumberInYear() const;
-    bool parseYear(const UChar* src, unsigned length, unsigned start, unsigned& end);
+
     bool addDay(int);
     bool addMinute(int);
-    bool parseTimeZone(const UChar* src, unsigned length, unsigned start, unsigned& end);
+
     // Helper for millisecondsSinceEpoch().
     double millisecondsSinceEpochForTime() const;
-    // Helpers for setMillisecondsSinceEpochFor*().
-    bool setMillisecondsSinceEpochForDateInternal(double ms);
-    void setMillisecondsSinceMidnightInternal(double ms);
+
     // Helper for toString().
     String toStringForTime(SecondFormat) const;
 
@@ -207,7 +214,4 @@
     Type m_type;
 };
 
-
 } // namespace WebCore
-
-#endif // DateComponents_h
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to