18inline constexpr bool IsTZLeadingChar(
base::uc32 c) {
25 return IsTZLeadingChar(c) || c ==
'-';
29inline constexpr bool IsDecimalSeparator(
base::uc32 c) {
30 return c ==
'.' || c ==
',';
34inline constexpr bool IsDateTimeSeparator(
base::uc32 c) {
39inline constexpr bool IsAsciiSign(
base::uc32 c) {
return c ==
'-' || c ==
'+'; }
43 return c == 0x2212 || IsAsciiSign(c);
47inline constexpr bool IsTimeZoneUTCOffsetSign(
base::uc32 c) {
52 return c == 0x2212 ?
'-' : c;
58template <
typename Char>
59bool HasTwoDigits(base::Vector<Char> str, int32_t s, int32_t* out) {
62 *out = ToInt(str[s]) * 10 + ToInt(str[s + 1]);
70template <
typename Char>
71int32_t ScanTwoDigitsExpectValue(base::Vector<Char> str, int32_t s,
72 int32_t expected, int32_t* out) {
73 return HasTwoDigits<Char>(str, s, out) && (*out == expected) ? 2 : 0;
78template <
typename Char>
79int32_t ScanTwoDigitsExpectRange(base::Vector<Char> str, int32_t s, int32_t min,
80 int32_t max, int32_t* out) {
81 return HasTwoDigits<Char>(str, s, out) &&
base::IsInRange(*out, min, max) ? 2
87template <
typename Char>
88int32_t ScanTwoDigitsExpectZeroOrRange(base::Vector<Char> str, int32_t s,
89 int32_t min, int32_t max, int32_t* out) {
90 return HasTwoDigits<Char>(str, s, out) &&
124template <
typename Char>
125int32_t ScanHour(base::Vector<Char> str, int32_t s, int32_t* out) {
126 return ScanTwoDigitsExpectRange<Char>(str, s, 0, 23, out);
136template <
typename Char>
137int32_t ScanUnpaddedHour(base::Vector<Char> str, int32_t s) {
139 int32_t len = ScanTwoDigitsExpectRange<Char>(str, s, 10, 23, &dummy);
140 if (len > 0)
return len;
147template <
typename Char>
148int32_t ScanMinuteSecond(base::Vector<Char> str, int32_t s, int32_t* out) {
149 return ScanTwoDigitsExpectRange<Char>(str, s, 0, 59, out);
155#define SCAN_FORWARD(B, T, R) \
156 template <typename Char> \
157 int32_t Scan##B(base::Vector<Char> str, int32_t s, R* r) { \
158 return Scan##T(str, s, r); \
167#define SCAN_EITHER_FORWARD(B, T1, T2, R) \
168 template <typename Char> \
169 int32_t Scan##B(base::Vector<Char> str, int32_t s, R* r) { \
171 if ((len = Scan##T1(str, s, r)) > 0) return len; \
172 return Scan##T2(str, s, r); \
184template <
typename Char>
185int32_t ScanTimeSecond(base::Vector<Char> str, int32_t s, int32_t* out) {
186 return ScanTwoDigitsExpectRange<Char>(str, s, 0, 60, out);
189constexpr int kPowerOfTen[] = {1, 10, 100, 1000, 10000,
190 100000, 1000000, 10000000, 100000000};
193template <
typename Char>
194int32_t ScanFractionalPart(base::Vector<Char> str, int32_t s, int32_t* out) {
196 if ((str.length() < (cur + 1)) || !
IsDecimalDigit(str[cur]))
return 0;
197 *out = ToInt(str[cur++]);
198 while ((cur < str.length()) && ((cur - s) < 9) &&
IsDecimalDigit(str[cur])) {
199 *out = 10 * (*out) + ToInt(str[cur++]);
201 *out *= kPowerOfTen[9 - (cur -
s)];
206SCAN_FORWARD(TimeFractionalPart, FractionalPart, int32_t)
210template <
typename Char>
211int32_t ScanFraction(base::Vector<Char> str, int32_t s, int32_t* out) {
212 if ((str.length() < (s + 2)) || (!IsDecimalSeparator(str[s])))
return 0;
214 if ((len = ScanFractionalPart(str, s + 1, out)) == 0)
return 0;
220template <
typename Char>
221int32_t ScanTimeFraction(base::Vector<Char> str, int32_t s, int32_t* out) {
222 if ((str.length() < (s + 2)) || (!IsDecimalSeparator(str[s])))
return 0;
224 if ((len = ScanTimeFractionalPart(str, s + 1, out)) == 0)
return 0;
228template <
typename Char>
229int32_t ScanTimeFraction(base::Vector<Char> str, int32_t s,
230 ParsedISO8601Result*
r) {
231 return ScanTimeFraction(str, s, &(
r->time_nanosecond));
240template <
typename Char>
241int32_t ScanTimeSpec(base::Vector<Char> str, int32_t s,
242 ParsedISO8601Result*
r) {
243 int32_t time_hour, time_minute, time_second;
246 if ((len = ScanTimeHour(str, cur, &time_hour)) == 0)
return 0;
248 if ((cur + 1) > str.length()) {
250 r->time_hour = time_hour;
253 if (str[cur] ==
':') {
255 if ((len = ScanTimeMinute(str, cur, &time_minute)) == 0)
return 0;
257 if ((cur + 1) > str.length() || (str[cur] !=
':')) {
259 r->time_hour = time_hour;
260 r->time_minute = time_minute;
264 if ((len = ScanTimeSecond(str, cur, &time_second)) == 0)
return 0;
266 if ((len = ScanTimeMinute(str, cur, &time_minute)) == 0) {
268 r->time_hour = time_hour;
272 if ((len = ScanTimeSecond(str, cur, &time_second)) == 0) {
274 r->time_hour = time_hour;
275 r->time_minute = time_minute;
280 len = ScanTimeFraction(str, cur,
r);
281 r->time_hour = time_hour;
282 r->time_minute = time_minute;
283 r->time_second = time_second;
290template <
typename Char>
291int32_t ScanTimeSpecSeparator(base::Vector<Char> str, int32_t s,
292 ParsedISO8601Result*
r) {
293 if (!(((s + 1) < str.length()) && IsDateTimeSeparator(str[s])))
return 0;
294 int32_t len = ScanTimeSpec(str, s + 1,
r);
295 return (len == 0) ? 0 : len + 1;
299template <
typename Char>
300int32_t ScanDateExtendedYear(base::Vector<Char> str, int32_t s, int32_t* out) {
301 if (str.length() < (s + 7))
return 0;
306 int32_t sign = (CanonicalSign(str[s]) ==
'-') ? -1 : 1;
307 *out =
sign * (ToInt(str[s + 1]) * 100000 + ToInt(str[s + 2]) * 10000 +
308 ToInt(str[s + 3]) * 1000 + ToInt(str[s + 4]) * 100 +
309 ToInt(str[s + 5]) * 10 + ToInt(str[s + 6]));
313 if (
sign == -1 && *out == 0)
return 0;
320template <
typename Char>
321int32_t ScanDateFourDigitYear(base::Vector<Char> str, int32_t s, int32_t* out) {
322 if (str.length() < (s + 4))
return 0;
325 *out = ToInt(str[s]) * 1000 + ToInt(str[s + 1]) * 100 +
326 ToInt(str[s + 2]) * 10 + ToInt(str[s + 3]);
343template <
typename Char>
344int32_t ScanDateMonth(base::Vector<Char> str, int32_t s, int32_t* out) {
345 return ScanTwoDigitsExpectRange<Char>(str, s, 1, 12, out);
354template <
typename Char>
355int32_t ScanDateDay(base::Vector<Char> str, int32_t s, int32_t* out) {
356 return ScanTwoDigitsExpectRange<Char>(str, s, 1, 31, out);
362template <
typename Char>
363int32_t ScanDate(base::Vector<Char> str, int32_t s, ParsedISO8601Result*
r) {
364 int32_t date_year, date_month, date_day;
367 if ((len = ScanDateYear(str, cur, &date_year)) == 0)
return 0;
368 if (((cur += len) + 1) > str.length())
return 0;
369 if (str[cur] ==
'-') {
371 if ((len = ScanDateMonth(str, cur, &date_month)) == 0)
return 0;
373 if (((cur + 1) > str.length()) || (str[cur++] !=
'-'))
return 0;
375 if ((len = ScanDateMonth(str, cur, &date_month)) == 0)
return 0;
378 if ((len = ScanDateDay(str, cur, &date_day)) == 0)
return 0;
379 r->date_year = date_year;
380 r->date_month = date_month;
381 r->date_day = date_day;
382 return cur + len -
s;
387template <
typename Char>
388int32_t ScanDateMonthWithThirtyOneDays(base::Vector<Char> str, int32_t s) {
390 if (!HasTwoDigits(str, s, &value))
return false;
391 return value == 1 || value == 3 || value == 5 || value == 7 || value == 8 ||
392 value == 10 || value == 12;
399SCAN_FORWARD(TimeZoneUTCOffsetMinute, MinuteSecond, int32_t)
402SCAN_FORWARD(TimeZoneUTCOffsetSecond, MinuteSecond, int32_t)
406SCAN_FORWARD(TimeZoneUTCOffsetFractionalPart, FractionalPart, int32_t)
410template <
typename Char>
411int32_t ScanTimeZoneUTCOffsetFraction(base::Vector<Char> str, int32_t s,
413 if ((str.length() < (s + 2)) || (!IsDecimalSeparator(str[s])))
return 0;
415 if ((len = ScanTimeZoneUTCOffsetFractionalPart(str, s + 1, out)) > 0) {
430template <
typename Char>
431int32_t ScanTimeZoneNumericUTCOffset(base::Vector<Char> str, int32_t s,
432 ParsedISO8601Result*
r) {
435 if ((str.length() < (cur + 1)) || (!IsTimeZoneUTCOffsetSign(str[cur]))) {
438 int32_t sign = (CanonicalSign(str[cur++]) ==
'-') ? -1 : 1;
439 if ((len = ScanTimeZoneUTCOffsetHour(str, cur, &
hour)) == 0)
return 0;
441 if ((cur + 1) > str.length()) {
445 r->offset_string_start =
s;
446 r->offset_string_length = cur -
s;
449 if (str[cur] ==
':') {
451 if ((len = ScanTimeZoneUTCOffsetMinute(str, cur, &
minute)) == 0)
return 0;
453 if ((cur + 1) > str.length() || str[cur] !=
':') {
458 r->offset_string_start =
s;
459 r->offset_string_length = cur -
s;
463 if ((len = ScanTimeZoneUTCOffsetSecond(str, cur, &
second)) == 0)
return 0;
465 if ((len = ScanTimeZoneUTCOffsetMinute(str, cur, &
minute)) == 0) {
469 r->offset_string_start =
s;
470 r->offset_string_length = cur -
s;
474 if ((len = ScanTimeZoneUTCOffsetSecond(str, cur, &
second)) == 0) {
479 r->offset_string_start =
s;
480 r->offset_string_length = cur -
s;
485 len = ScanTimeZoneUTCOffsetFraction(str, cur, &
nanosecond);
491 r->offset_string_start =
s;
492 r->offset_string_length = cur + len -
s;
500template <
typename Char>
501int32_t ScanTimeZoneUTCOffset(base::Vector<Char> str, int32_t s,
502 ParsedISO8601Result*
r) {
503 if (str.length() < (s + 1))
return 0;
506 r->utc_designator =
true;
510 return ScanTimeZoneNumericUTCOffset(str, s,
r);
515template <
typename Char>
516int32_t ScanTimeZoneIANANameComponent(base::Vector<Char> str, int32_t s) {
518 if (str.length() < (cur + 1) || !IsTZLeadingChar(str[cur++]))
return 0;
519 while (((cur) < str.length()) && ((cur - s) < 14) && IsTZChar(str[cur])) {
522 if ((cur - s) == 1 && str[s] ==
'.')
return 0;
523 if ((cur - s) == 2 && str[s] ==
'.' && str[s + 1] ==
'.')
return 0;
536template <
typename Char>
537int32_t ScanTimeZoneIANALegacyName(base::Vector<Char> str, int32_t s) {
541 if (str.length() < cur + len)
return 0;
547 if (str.length() < cur + len)
return 0;
556 if (str.length() < cur + len)
return 0;
567 if (str.length() < cur + len)
return 0;
575template <
typename Char>
576int32_t ScanEtcGMTASCIISignUnpaddedHour(base::Vector<Char> str, int32_t s) {
577 if ((s + 9) > str.length())
return 0;
582 Char
sign = str[cur++];
583 if (!IsAsciiSign(
sign))
return 0;
584 len = ScanUnpaddedHour(str, cur);
585 if (len == 0)
return 0;
600template <
typename Char>
601int32_t ScanTimeZoneIANAName(base::Vector<Char> str, int32_t s) {
603 if ((len = ScanEtcGMTASCIISignUnpaddedHour(str, s)) > 0 ||
604 (len = ScanTimeZoneIANALegacyName(str, s)) > 0) {
608 if ((len = ScanTimeZoneIANANameComponent(str, cur)) == 0)
return 0;
610 while ((str.length() > (cur + 1)) && (str[cur] ==
'/')) {
612 if ((len = ScanTimeZoneIANANameComponent(str, cur)) == 0) {
628template <
typename Char>
629int32_t ScanTimeZoneUTCOffsetName(base::Vector<Char> str, int32_t s) {
632 if ((str.length() < (s + 3)) || !IsSign(str[cur++]))
return 0;
634 if ((len = ScanHour(str, cur, &
hour)) == 0)
return 0;
636 if ((cur + 1) > str.length()) {
640 if (str[cur] ==
':') {
643 if ((len = ScanMinuteSecond(str, cur, &
minute)) == 0)
return 0;
645 if ((cur + 1) > str.length() || (str[cur] !=
':')) {
651 if ((len = ScanMinuteSecond(str, cur, &
second)) == 0)
return 0;
653 len = ScanFraction(str, cur, &fraction);
654 return cur + len -
s;
656 if ((len = ScanMinuteSecond(str, cur, &
minute)) == 0) {
661 if ((len = ScanMinuteSecond(str, cur, &
second)) == 0) {
666 len = ScanFraction(str, cur, &fraction);
679template <
typename Char>
680int32_t ScanEtcGMTAsciiSignHour(base::Vector<Char> str, int32_t s) {
681 if ((s + 10) > str.length())
return 0;
683 if ((str[cur++] !=
'E') || (str[cur++] !=
't') || (str[cur++] !=
'c') ||
684 (str[cur++] !=
'/') || (str[cur++] !=
'G') || (str[cur++] !=
'M') ||
685 (str[cur++] !=
'T')) {
688 Char
sign = str[cur++];
689 if (!IsAsciiSign(
sign))
return 0;
692 if (len == 0)
return 0;
697template <
typename Char>
698int32_t ScanTimeZoneIdentifier(base::Vector<Char> str, int32_t s,
699 ParsedISO8601Result*
r);
702template <
typename Char>
703int32_t ScanTimeZoneBracketedAnnotation(base::Vector<Char> str, int32_t s,
704 ParsedISO8601Result*
r) {
705 if ((str.length() < (s + 3)) || (str[s] !=
'['))
return 0;
707 int32_t len = ScanTimeZoneIdentifier(str, cur,
r);
709 if (len == 0 || str.length() < (cur + 1) || (str[cur] !=
']')) {
712 r->tzi_name_start = 0;
713 r->tzi_name_length = 0;
722template <
typename Char>
723int32_t ScanTimeZoneOffsetRequired(base::Vector<Char> str, int32_t s,
724 ParsedISO8601Result*
r) {
726 cur += ScanTimeZoneUTCOffset(str, cur,
r);
727 if (cur == s)
return 0;
728 cur += ScanTimeZoneBracketedAnnotation(str, cur,
r);
734template <
typename Char>
735int32_t ScanTimeZoneNameRequired(base::Vector<Char> str, int32_t s,
736 ParsedISO8601Result*
r) {
738 cur += ScanTimeZoneUTCOffset(str, cur,
r);
739 int32_t len = ScanTimeZoneBracketedAnnotation(str, cur,
r);
740 if (len == 0)
return 0;
748template <
typename Char>
749int32_t ScanTimeZone(base::Vector<Char> str, int32_t s,
750 ParsedISO8601Result*
r) {
754 if ((len = ScanTimeZoneUTCOffset(str, cur,
r)) > 0) {
757 len = ScanTimeZoneBracketedAnnotation(str, cur,
r);
762 return ScanTimeZoneBracketedAnnotation(str, cur,
r);
771template <
typename Char>
772int32_t ScanValidMonthDay(base::Vector<Char> str, int32_t s) {
776 if ((len = ScanDateMonth(str, cur, &date_month)) > 0) {
778 if (str.length() >= (cur + 1)) {
779 if (str[cur] ==
'-') cur++;
781 if ((len = ScanTwoDigitsExpectRange(str, cur, 1, 30, &day_of_month)) >
788 if (date_month != 2 || day_of_month != 30) {
797 if ((len = ScanDateMonthWithThirtyOneDays(str, cur)) > 0) {
799 if (str.length() >= (cur + 1)) {
800 if (str[cur] ==
'-') cur++;
802 if ((len = ScanTwoDigitsExpectValue(str, cur, 31, &dummy)) > 0) {
811template <
typename Char>
812int32_t ScanDateSpecYearMonth(base::Vector<Char> str, int32_t s,
813 ParsedISO8601Result*
r);
817template <
typename Char>
818int32_t ScanTimeSpecWithOptionalTimeZoneNotAmbiguous(base::Vector<Char> str,
820 ParsedISO8601Result*
r) {
823 if ((len = ScanTimeSpec(str, cur,
r)) == 0)
return 0;
826 len = ScanTimeZone(str, cur,
r);
830 if (ScanValidMonthDay(str, s) == len)
return 0;
832 ParsedISO8601Result
tmp;
833 if (ScanDateSpecYearMonth(str, s, &tmp) == len)
return 0;
839template <
typename Char>
840int32_t ScanCalendarNameComponent(base::Vector<Char> str, int32_t s) {
843 if ((cur - s) < 3 || (cur - s) > 8)
return 0;
854template <
typename Char>
855int32_t ScanCalendarName(base::Vector<Char> str, int32_t s,
856 ParsedISO8601Result*
r) {
859 if ((len = ScanCalendarNameComponent(str, cur)) == 0)
return 0;
861 while ((str.length() > (cur + 1)) && (str[cur++] ==
'-')) {
862 if ((len = ScanCalendarNameComponent(str, cur)) == 0)
return 0;
866 r->calendar_name_start =
s;
867 r->calendar_name_length = cur -
s;
872template <
typename Char>
873int32_t ScanCalendar(base::Vector<Char> str, int32_t s,
874 ParsedISO8601Result*
r) {
875 if (str.length() < (s + 7))
return 0;
878 if ((str[cur++] !=
'[') || (str[cur++] !=
'u') || (str[cur++] !=
'-') ||
879 (str[cur++] !=
'c') || (str[cur++] !=
'a') || (str[cur++] !=
'=')) {
882 int32_t len = ScanCalendarName(str, cur,
r);
883 if (len == 0)
return 0;
884 if ((str.length() < (cur + len + 1)) || (str[cur + len] !=
']')) {
887 r->calendar_name_start = 0;
888 r->calendar_name_length = 0;
896template <
typename Char>
897int32_t ScanCalendarTime_L1(base::Vector<Char> str, int32_t s,
898 ParsedISO8601Result*
r) {
900 if (str.length() < (s + 1))
return 0;
903 int32_t len = ScanTimeSpec(str, cur,
r);
904 if (len == 0)
return 0;
907 cur += ScanTimeZone(str, cur,
r);
909 cur += ScanCalendar(str, cur,
r);
915template <
typename Char>
916int32_t ScanCalendarTime_L2(base::Vector<Char> str, int32_t s,
917 ParsedISO8601Result*
r) {
919 int32_t len = ScanTimeSpecWithOptionalTimeZoneNotAmbiguous(str, cur,
r);
920 if (len == 0)
return 0;
923 cur += ScanCalendar(str, cur,
r);
928template <
typename Char>
929int32_t ScanDateTime(base::Vector<Char> str, int32_t s,
930 ParsedISO8601Result*
r) {
932 int32_t len = ScanDate(str, cur,
r);
933 if (len == 0)
return 0;
935 cur += ScanTimeSpecSeparator(str, cur,
r);
936 cur += ScanTimeZone(str, cur,
r);
941template <
typename Char>
942int32_t ScanDateSpecYearMonth(base::Vector<Char> str, int32_t s,
943 ParsedISO8601Result*
r) {
946 int32_t len = ScanDateYear(str, cur, &date_year);
947 if (len == 0)
return 0;
949 if (str.length() < (cur + 1))
return 0;
950 if (str[cur] ==
'-') cur++;
951 len = ScanDateMonth(str, cur, &date_month);
952 if (len == 0)
return 0;
953 r->date_year = date_year;
954 r->date_month = date_month;
961template <
typename Char>
962int32_t ScanDateSpecMonthDay(base::Vector<Char> str, int32_t s,
963 ParsedISO8601Result*
r) {
964 if (str.length() < (s + 4))
return 0;
966 if (str[cur] ==
'-') {
968 if (str[++cur] !=
'-')
return 0;
973 int32_t len = ScanDateMonth(str, cur, &date_month);
974 if (len == 0)
return 0;
976 if (str.length() < (cur + 1))
return 0;
978 if (str[cur] ==
'-') cur++;
979 len = ScanDateDay(str, cur, &date_day);
980 if (len == 0)
return 0;
981 r->date_month = date_month;
982 r->date_day = date_day;
990template <
typename Char>
991int32_t ScanTimeZoneIdentifier(base::Vector<Char> str, int32_t s,
992 ParsedISO8601Result*
r) {
995 if ((len = ScanTimeZoneIANAName(str, cur)) > 0 ||
996 (len = ScanTimeZoneUTCOffsetName(str, cur)) > 0) {
998 r->tzi_name_start =
s;
999 r->tzi_name_length = len;
1006template <
typename Char>
1007int32_t ScanCalendarDateTime(base::Vector<Char> str, int32_t s,
1008 ParsedISO8601Result*
r) {
1009 int32_t len = ScanDateTime(str, s,
r);
1010 if (len == 0)
return 0;
1011 return len + ScanCalendar(str, len,
r);
1015template <
typename Char>
1016int32_t ScanCalendarDateTimeTimeRequired(base::Vector<Char> str, int32_t s,
1017 ParsedISO8601Result*
r) {
1019 int32_t len = ScanDate(str, cur,
r);
1020 if (len == 0)
return 0;
1022 len = ScanTimeSpecSeparator(str, cur,
r);
1023 if (len == 0)
return 0;
1026 cur += ScanTimeZone(str, cur,
r);
1028 cur += ScanCalendar(str, cur,
r);
1034template <
typename Char>
1035int32_t ScanTemporalZonedDateTimeString(base::Vector<Char> str, int32_t s,
1036 ParsedISO8601Result*
r) {
1039 int32_t len = ScanDate(str, cur,
r);
1040 if (len == 0)
return 0;
1044 cur += ScanTimeSpecSeparator(str, cur,
r);
1047 len = ScanTimeZoneNameRequired(str, cur,
r);
1048 if (len == 0)
return 0;
1052 cur += ScanCalendar(str, cur,
r);
1056SCAN_FORWARD(TemporalDateTimeString, CalendarDateTime, ParsedISO8601Result)
1063 ParsedISO8601Result)
1067template <
typename Char>
1068int32_t ScanTemporalInstantString(base::Vector<Char> str, int32_t s,
1069 ParsedISO8601Result*
r) {
1072 int32_t len = ScanDate(str, cur,
r);
1073 if (len == 0)
return 0;
1077 cur += ScanTimeSpecSeparator(str, cur,
r);
1080 len = ScanTimeZoneOffsetRequired(str, cur,
r);
1081 if (len == 0)
return 0;
1084 cur += ScanCalendar(str, cur,
r);
1089#define SATISIFY(T, R) \
1090 template <typename Char> \
1091 bool Satisfy##T(base::Vector<Char> str, R* r) { \
1093 int32_t len = Scan##T(str, 0, &ret); \
1094 if ((len > 0) && (len == str.length())) { \
1101#define IF_SATISFY_RETURN(T) \
1103 if (Satisfy##T(str, r)) return true; \
1106#define SATISIFY_EITHER(T1, T2, T3, R) \
1107 template <typename Char> \
1108 bool Satisfy##T1(base::Vector<Char> str, R* r) { \
1109 IF_SATISFY_RETURN(T2) \
1110 IF_SATISFY_RETURN(T3) \
1114SATISIFY(TemporalDateTimeString, ParsedISO8601Result)
1115SATISIFY(DateTime, ParsedISO8601Result)
1116SATISIFY(DateSpecYearMonth, ParsedISO8601Result)
1117SATISIFY(DateSpecMonthDay, ParsedISO8601Result)
1118SATISIFY(CalendarDateTime, ParsedISO8601Result)
1119SATISIFY(CalendarTime_L1, ParsedISO8601Result)
1120SATISIFY(CalendarTime_L2, ParsedISO8601Result)
1122template <
typename Char>
1123bool SatisfyCalendarTime(base::Vector<Char> str, ParsedISO8601Result*
r) {
1128SATISIFY(CalendarDateTimeTimeRequired, ParsedISO8601Result)
1129SATISIFY_EITHER(TemporalTimeString, CalendarTime, CalendarDateTimeTimeRequired,
1130 ParsedISO8601Result)
1131SATISIFY_EITHER(TemporalYearMonthString, DateSpecYearMonth, CalendarDateTime,
1132 ParsedISO8601Result)
1133SATISIFY_EITHER(TemporalMonthDayString, DateSpecMonthDay, CalendarDateTime,
1134 ParsedISO8601Result)
1135SATISIFY(TimeZoneNumericUTCOffset, ParsedISO8601Result)
1136SATISIFY(TimeZoneIdentifier, ParsedISO8601Result)
1137SATISIFY(TemporalInstantString, ParsedISO8601Result)
1138SATISIFY(TemporalZonedDateTimeString, ParsedISO8601Result)
1140SATISIFY(CalendarName, ParsedISO8601Result)
1146template <
typename Char>
1147int32_t ScanDigits(base::Vector<Char> str, int32_t s,
double* out) {
1149 *out = ToInt(str[s]);
1151 while (s + len + 1 <= str.length() &&
IsDecimalDigit(str[s + len])) {
1152 *out = 10 * (*out) + ToInt(str[s + len]);
1173SCAN_FORWARD(DurationHoursFraction, TimeFraction, int32_t)
1176SCAN_FORWARD(DurationMinutesFraction, TimeFraction, int32_t)
1179SCAN_FORWARD(DurationSecondsFraction, TimeFraction, int32_t)
1181#define DURATION_WHOLE_FRACTION_DESIGNATOR(Name, name, d) \
1182 template <typename Char> \
1183 int32_t ScanDurationWhole##Name##FractionDesignator( \
1184 base::Vector<Char> str, int32_t s, ParsedISO8601Duration* r) { \
1186 double whole = ParsedISO8601Duration::kEmpty; \
1187 cur += ScanDurationWhole##Name(str, cur, &whole); \
1188 if (cur == s) return 0; \
1189 int32_t fraction = ParsedISO8601Duration::kEmpty; \
1190 int32_t len = ScanDuration##Name##Fraction(str, cur, &fraction); \
1192 if (str.length() < (cur + 1) || AsciiAlphaToLower(str[cur++]) != (d)) \
1194 r->whole_##name = whole; \
1195 r->name##_fraction = fraction; \
1205SCAN_FORWARD(DurationSecondsPart, DurationWholeSecondsFractionDesignator,
1206 ParsedISO8601Duration)
1211template <typename Char>
1212int32_t ScanDurationMinutesPart(base::Vector<Char> str, int32_t s,
1213 ParsedISO8601Duration*
r) {
1215 int32_t len = ScanDurationWholeMinutesFractionDesignator(str, s,
r);
1216 if (len == 0)
return 0;
1218 cur += ScanDurationSecondsPart(str, cur,
r);
1228template <
typename Char>
1229int32_t ScanDurationHoursPart(base::Vector<Char> str, int32_t s,
1230 ParsedISO8601Duration*
r) {
1232 int32_t len = ScanDurationWholeHoursFractionDesignator(str, s,
r);
1233 if (len == 0)
return 0;
1235 len = ScanDurationMinutesPart(str, cur,
r);
1239 cur += ScanDurationSecondsPart(str, cur,
r);
1248template <
typename Char>
1249int32_t ScanDurationTime(base::Vector<Char> str, int32_t s,
1250 ParsedISO8601Duration*
r) {
1252 if (str.length() < (s + 1))
return 0;
1254 if ((cur += ScanDurationHoursPart(str, cur,
r)) - s > 1)
return cur -
s;
1255 if ((cur += ScanDurationMinutesPart(str, cur,
r)) - s > 1)
return cur -
s;
1256 if ((cur += ScanDurationSecondsPart(str, cur,
r)) - s > 1)
return cur -
s;
1260#define DURATION_AND_DESIGNATOR(Name, name, d) \
1261 template <typename Char> \
1262 int32_t ScanDuration##Name##Designator(base::Vector<Char> str, int32_t s, \
1263 ParsedISO8601Duration* r) { \
1266 if ((cur += ScanDuration##Name(str, cur, &name)) == s) return 0; \
1267 if (str.length() < (cur + 1) || AsciiAlphaToLower(str[cur++]) != (d)) { \
1280SCAN_FORWARD(DurationDaysPart, DurationDaysDesignator, ParsedISO8601Duration)
1283template <typename Char>
1284int32_t ScanDurationWeeksPart(base::Vector<Char> str, int32_t s,
1285 ParsedISO8601Duration*
r) {
1287 if ((cur += ScanDurationWeeksDesignator(str, cur,
r)) == s)
return 0;
1288 cur += ScanDurationDaysPart(str, cur,
r);
1295template <
typename Char>
1296int32_t ScanDurationMonthsPart(base::Vector<Char> str, int32_t s,
1297 ParsedISO8601Duration*
r) {
1299 int32_t len = ScanDurationMonthsDesignator(str, cur,
r);
1300 if (len == 0)
return 0;
1302 if ((len = ScanDurationWeeksPart(str, cur,
r)) > 0) {
1305 cur += ScanDurationDaysPart(str, cur,
r);
1314template <
typename Char>
1315int32_t ScanDurationYearsPart(base::Vector<Char> str, int32_t s,
1316 ParsedISO8601Duration*
r) {
1318 int32_t len = ScanDurationYearsDesignator(str, cur,
r);
1319 if (len == 0)
return 0;
1321 if ((len = ScanDurationMonthsPart(str, cur,
r)) > 0) {
1323 }
else if ((len = ScanDurationWeeksPart(str, cur,
r)) > 0) {
1326 len = ScanDurationDaysPart(str, cur,
r);
1337template <
typename Char>
1338int32_t ScanDurationDate(base::Vector<Char> str, int32_t s,
1339 ParsedISO8601Duration*
r) {
1342 if ((cur += ScanDurationYearsPart(str, cur,
r)) > s)
break;
1343 if ((cur += ScanDurationMonthsPart(str, cur,
r)) > s)
break;
1344 if ((cur += ScanDurationWeeksPart(str, cur,
r)) > s)
break;
1345 if ((cur += ScanDurationDaysPart(str, cur,
r)) > s)
break;
1348 cur += ScanDurationTime(str, cur,
r);
1355template <
typename Char>
1356int32_t ScanDuration(base::Vector<Char> str, int32_t s,
1357 ParsedISO8601Duration*
r) {
1358 if (str.length() < (s + 2))
return 0;
1361 (IsSign(str[cur]) && CanonicalSign(str[cur++]) ==
'-') ? -1 : 1;
1363 int32_t len = ScanDurationDate(str, cur,
r);
1364 if (len == 0) len = ScanDurationTime(str, cur,
r);
1365 if (len == 0)
return 0;
1370SCAN_FORWARD(TemporalDurationString, Duration, ParsedISO8601Duration)
1372SATISIFY(TemporalDurationString, ParsedISO8601Duration)
1376#define IMPL_PARSE_METHOD(R, NAME) \
1377 std::optional<R> TemporalParser::Parse##NAME( \
1378 Isolate* isolate, DirectHandle<String> iso_string) { \
1381 iso_string = String::Flatten(isolate, iso_string); \
1383 DisallowGarbageCollection no_gc; \
1384 String::FlatContent str_content = iso_string->GetFlatContent(no_gc); \
1385 if (str_content.IsOneByte()) { \
1386 valid = Satisfy##NAME(str_content.ToOneByteVector(), &parsed); \
1388 valid = Satisfy##NAME(str_content.ToUC16Vector(), &parsed); \
1391 if (valid) return parsed; \
1392 return std::nullopt; \
constexpr bool IsInRange(T value, U lower_limit, U higher_limit)
bool CompareCharsEqual(const lchar *lhs, const rchar *rhs, size_t chars)
constexpr bool IsDecimalDigit(base::uc32 c)
constexpr int AsciiAlphaToLower(base::uc32 c)
constexpr bool IsAlphaNumeric(base::uc32 c)
#define IF_SATISFY_RETURN(T)
#define SCAN_EITHER_FORWARD(B, T1, T2, R)
#define IMPL_PARSE_METHOD(R, NAME)
#define SCAN_FORWARD(B, T, R)
#define SATISIFY_EITHER(T1, T2, T3, R)
#define DURATION_WHOLE_FRACTION_DESIGNATOR(Name, name, d)
#define DURATION_AND_DESIGNATOR(Name, name, d)