Bug Summary

File:out/../deps/v8/src/temporal/temporal-parser.cc
Warning:line 178, column 8
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name temporal-parser.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D V8_GYP_BUILD -D V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP=64 -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D V8_TARGET_ARCH_X64 -D V8_HAVE_TARGET_OS -D V8_TARGET_OS_LINUX -D V8_EMBEDDER_STRING="-node.8" -D ENABLE_DISASSEMBLER -D V8_PROMISE_INTERNAL_FIELD_COUNT=1 -D V8_SHORT_BUILTIN_CALLS -D OBJECT_PRINT -D V8_INTL_SUPPORT -D V8_ATOMIC_OBJECT_FIELD_WRITES -D V8_ENABLE_LAZY_SOURCE_POSITIONS -D V8_USE_SIPHASH -D V8_SHARED_RO_HEAP -D V8_WIN64_UNWINDING_INFO -D V8_ENABLE_REGEXP_INTERPRETER_THREADED_DISPATCH -D V8_SNAPSHOT_COMPRESSION -D V8_ENABLE_WEBASSEMBLY -D V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS -D V8_ALLOCATION_FOLDING -D V8_ALLOCATION_SITE_TRACKING -D V8_SCRIPTORMODULE_LEGACY_LIFETIME -D V8_ADVANCED_BIGINT_ALGORITHMS -D ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC -D UCONFIG_NO_SERVICE=1 -D U_ENABLE_DYLOAD=0 -D U_STATIC_IMPLEMENTATION=1 -D U_HAVE_STD_STRING=1 -D UCONFIG_NO_BREAK_ITERATION=0 -I ../deps/v8 -I ../deps/v8/include -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/inspector-generated-output-root -I ../deps/v8/third_party/inspector_protocol -I /home/maurizio/node-v18.6.0/out/Release/obj/gen -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/generate-bytecode-output-root -I ../deps/icu-small/source/i18n -I ../deps/icu-small/source/common -I ../deps/v8/third_party/zlib -I ../deps/v8/third_party/zlib/google -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-return-type -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c++ ../deps/v8/src/temporal/temporal-parser.cc
1// Copyright 2021 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/temporal/temporal-parser.h"
6
7#include "src/base/bounds.h"
8#include "src/objects/string-inl.h"
9#include "src/strings/char-predicates-inl.h"
10
11namespace v8 {
12namespace internal {
13
14namespace {
15
16// Temporal #prod-NonzeroDigit
17inline constexpr bool IsNonZeroDecimalDigit(base::uc32 c) {
18 return base::IsInRange(c, '1', '9');
19}
20
21// Temporal #prod-TZLeadingChar
22inline constexpr bool IsTZLeadingChar(base::uc32 c) {
23 return base::IsInRange(AsciiAlphaToLower(c), 'a', 'z') || c == '.' ||
24 c == '_';
25}
26
27// Temporal #prod-TZChar
28inline constexpr bool IsTZChar(base::uc32 c) {
29 return IsTZLeadingChar(c) || c == '-';
30}
31
32// Temporal #prod-DecimalSeparator
33inline constexpr bool IsDecimalSeparator(base::uc32 c) {
34 return c == '.' || c == ',';
35}
36
37// Temporal #prod-DateTimeSeparator
38inline constexpr bool IsDateTimeSeparator(base::uc32 c) {
39 return c == ' ' || AsciiAlphaToLower(c) == 't';
40}
41
42// Temporal #prod-ASCIISign
43inline constexpr bool IsAsciiSign(base::uc32 c) { return c == '-' || c == '+'; }
44
45// Temporal #prod-Sign
46inline constexpr bool IsSign(base::uc32 c) {
47 return c == 0x2212 || IsAsciiSign(c);
48}
49
50inline constexpr base::uc32 CanonicalSign(base::uc32 c) {
51 return c == 0x2212 ? '-' : c;
52}
53
54inline constexpr int32_t ToInt(base::uc32 c) { return c - '0'; }
55
56/**
57 * The TemporalParser use two types of internal routine:
58 * - Scan routines: Follow the function signature below:
59 * template <typename Char> int32_t Scan$ProductionName(
60 * base::Vector<Char> str, int32_t s, R* out)
61 *
62 * These routine scan the next item from position s in str and store the
63 * parsed result into out if the expected string is successfully scanned.
64 * It return the length of matched text from s or 0 to indicate no
65 * expected item matched.
66 *
67 * - Satisfy routines: Follow the function sigature below:
68 * template <typename Char>
69 * bool Satisfy$ProductionName(base::Vector<Char> str, R* r);
70 * It scan from the beginning of the str by calling Scan routines to put
71 * parsed result into r and return true if the entire str satisfy the
72 * production. It internally use Scan routines.
73 *
74 * TODO(ftang) investigate refactoring to class before shipping
75 * Reference to RegExpParserImpl by encapsulating the cursor position and
76 * only manipulating the current character and position with Next(),
77 * Advance(), current(), etc
78 */
79
80// For Hour Production
81// Hour:
82// [0 1] Digit
83// 2 [0 1 2 3]
84template <typename Char>
85bool IsHour(base::Vector<Char> str, int32_t s) {
86 return (str.length() >= (s + 2)) &&
87 ((base::IsInRange(str[s], '0', '1') && IsDecimalDigit(str[s + 1])) ||
88 ((str[s] == '2') && base::IsInRange(str[s + 1], '0', '3')));
89}
90
91template <typename Char>
92int32_t ScanHour(base::Vector<Char> str, int32_t s, int32_t* out) {
93 if (!IsHour(str, s)) return 0;
94 *out = ToInt(str[s]) * 10 + ToInt(str[s + 1]);
95 return 2;
96}
97
98// MinuteSecond:
99// [0 1 2 3 4 5] Digit
100template <typename Char>
101bool IsMinuteSecond(base::Vector<Char> str, int32_t s) {
102 return (str.length() >= (s + 2)) &&
103 (base::IsInRange(str[s], '0', '5') && IsDecimalDigit(str[s + 1]));
104}
105
106template <typename Char>
107int32_t ScanMinuteSecond(base::Vector<Char> str, int32_t s, int32_t* out) {
108 if (!IsMinuteSecond(str, s)) return 0;
109 *out = ToInt(str[s]) * 10 + ToInt(str[s + 1]);
110 return 2;
111}
112
113// For the forward production in the grammar such as
114// ProductionB:
115// ProductionT
116#define SCAN_FORWARD(B, T, R)template <typename Char> int32_t ScanB(base::Vector<
Char> str, int32_t s, R* r) { return ScanT(str, s, r); }
\
117 template <typename Char> \
118 int32_t Scan##B(base::Vector<Char> str, int32_t s, R* r) { \
119 return Scan##T(str, s, r); \
120 }
121
122// Same as above but store the result into a particular field in R
123
124// For the forward production in the grammar such as
125// ProductionB:
126// ProductionT1
127// ProductionT2
128#define SCAN_EITHER_FORWARD(B, T1, T2, R)template <typename Char> int32_t ScanB(base::Vector<
Char> str, int32_t s, R* r) { int32_t len; if ((len = ScanT1
(str, s, r)) > 0) return len; return ScanT2(str, s, r); }
\
129 template <typename Char> \
130 int32_t Scan##B(base::Vector<Char> str, int32_t s, R* r) { \
131 int32_t len; \
132 if ((len = Scan##T1(str, s, r)) > 0) return len; \
133 return Scan##T2(str, s, r); \
134 }
135
136// TimeHour: Hour
137SCAN_FORWARD(TimeHour, Hour, int32_t)template <typename Char> int32_t ScanTimeHour(base::Vector
<Char> str, int32_t s, int32_t* r) { return ScanHour(str
, s, r); }
138
139// TimeMinute: MinuteSecond
140SCAN_FORWARD(TimeMinute, MinuteSecond, int32_t)template <typename Char> int32_t ScanTimeMinute(base::Vector
<Char> str, int32_t s, int32_t* r) { return ScanMinuteSecond
(str, s, r); }
141
142// TimeSecond:
143// MinuteSecond
144// 60
145template <typename Char>
146int32_t ScanTimeSecond(base::Vector<Char> str, int32_t s, int32_t* out) {
147 int32_t len = ScanMinuteSecond(str, s, out);
148 // MinuteSecond
149 if (len > 0) return len;
150 if ((str.length() < (s + 2)) || (str[s] != '6') || (str[s + 1] != '0')) {
151 return 0;
152 }
153 // 60
154 *out = 60;
155 return 2;
156}
157
158constexpr int kPowerOfTen[] = {1, 10, 100, 1000, 10000,
159 100000, 1000000, 10000000, 100000000};
160
161// FractionalPart : Digit{1,9}
162template <typename Char>
163int32_t ScanFractionalPart(base::Vector<Char> str, int32_t s, int32_t* out) {
164 int32_t cur = s;
165 if ((str.length() < (cur + 1)) || !IsDecimalDigit(str[cur])) return 0;
12
Assuming the condition is true
13
Returning without writing to '*out'
166 *out = ToInt(str[cur++]);
167 while ((cur < str.length()) && ((cur - s) < 9) && IsDecimalDigit(str[cur])) {
168 *out = 10 * (*out) + ToInt(str[cur++]);
169 }
170 *out *= kPowerOfTen[9 - (cur - s)];
171 return cur - s;
172}
173
174template <typename Char>
175int32_t ScanFractionalPart(base::Vector<Char> str, int32_t s, int64_t* out) {
176 int32_t out32;
10
'out32' declared without an initial value
177 int32_t len = ScanFractionalPart(str, s, &out32);
11
Calling 'ScanFractionalPart<const unsigned short>'
14
Returning from 'ScanFractionalPart<const unsigned short>'
178 *out = out32;
15
Assigned value is garbage or undefined
179 return len;
180}
181
182// TimeFraction: FractionalPart
183SCAN_FORWARD(TimeFractionalPart, FractionalPart, int32_t)template <typename Char> int32_t ScanTimeFractionalPart
(base::Vector<Char> str, int32_t s, int32_t* r) { return
ScanFractionalPart(str, s, r); }
184
185// Fraction: DecimalSeparator FractionalPart
186// DecimalSeparator: one of , .
187template <typename Char>
188int32_t ScanFraction(base::Vector<Char> str, int32_t s, int32_t* out) {
189 if ((str.length() < (s + 2)) || (!IsDecimalSeparator(str[s]))) return 0;
190 int32_t len;
191 if ((len = ScanFractionalPart(str, s + 1, out)) == 0) return 0;
192 return len + 1;
193}
194
195// TimeFraction: DecimalSeparator TimeFractionalPart
196// DecimalSeparator: one of , .
197template <typename Char>
198int32_t ScanTimeFraction(base::Vector<Char> str, int32_t s, int32_t* out) {
199 if ((str.length() < (s + 2)) || (!IsDecimalSeparator(str[s]))) return 0;
200 int32_t len;
201 if ((len = ScanTimeFractionalPart(str, s + 1, out)) == 0) return 0;
202 return len + 1;
203}
204
205template <typename Char>
206int32_t ScanTimeFraction(base::Vector<Char> str, int32_t s,
207 ParsedISO8601Result* r) {
208 return ScanTimeFraction(str, s, &(r->time_nanosecond));
209}
210
211// TimeSpec:
212// TimeHour
213// TimeHour : TimeMinute
214// TimeHour : TimeMinute : TimeSecond [TimeFraction]
215// TimeHour TimeMinute
216// TimeHour TimeMinute TimeSecond [TimeFraction]
217template <typename Char>
218int32_t ScanTimeSpec(base::Vector<Char> str, int32_t s,
219 ParsedISO8601Result* r) {
220 int32_t time_hour, time_minute, time_second;
221 int32_t len;
222 int32_t cur = s;
223 if ((len = ScanTimeHour(str, cur, &time_hour)) == 0) return 0;
224 cur += len;
225 if ((cur + 1) > str.length()) {
226 // TimeHour
227 r->time_hour = time_hour;
228 return cur - s;
229 }
230 if (str[cur] == ':') {
231 cur++;
232 if ((len = ScanTimeMinute(str, cur, &time_minute)) == 0) return 0;
233 cur += len;
234 if ((cur + 1) > str.length() || (str[cur] != ':')) {
235 // TimeHour : TimeMinute
236 r->time_hour = time_hour;
237 r->time_minute = time_minute;
238 return cur - s;
239 }
240 cur++;
241 if ((len = ScanTimeSecond(str, cur, &time_second)) == 0) return 0;
242 } else {
243 if ((len = ScanTimeMinute(str, cur, &time_minute)) == 0) {
244 // TimeHour
245 r->time_hour = time_hour;
246 return cur - s;
247 }
248 cur += len;
249 if ((len = ScanTimeSecond(str, cur, &time_second)) == 0) {
250 // TimeHour TimeMinute
251 r->time_hour = time_hour;
252 r->time_minute = time_minute;
253 return cur - s;
254 }
255 }
256 cur += len;
257 len = ScanTimeFraction(str, cur, r);
258 r->time_hour = time_hour;
259 r->time_minute = time_minute;
260 r->time_second = time_second;
261 return cur + len - s;
262}
263
264// TimeSpecSeparator: DateTimeSeparator TimeSpec
265// DateTimeSeparator: SPACE, 't', or 'T'
266template <typename Char>
267int32_t ScanTimeSpecSeparator(base::Vector<Char> str, int32_t s,
268 ParsedISO8601Result* r) {
269 if (!(((s + 1) < str.length()) && IsDateTimeSeparator(str[s]))) return 0;
270 int32_t len = ScanTimeSpec(str, s + 1, r);
271 return (len == 0) ? 0 : len + 1;
272}
273
274// DateExtendedYear: Sign Digit Digit Digit Digit Digit Digit
275template <typename Char>
276int32_t ScanDateExtendedYear(base::Vector<Char> str, int32_t s, int32_t* out) {
277 if (str.length() < (s + 7)) return 0;
278 if (IsSign(str[s]) && IsDecimalDigit(str[s + 1]) &&
279 IsDecimalDigit(str[s + 2]) && IsDecimalDigit(str[s + 3]) &&
280 IsDecimalDigit(str[s + 4]) && IsDecimalDigit(str[s + 5]) &&
281 IsDecimalDigit(str[s + 6])) {
282 int32_t sign = (CanonicalSign(str[s]) == '-') ? -1 : 1;
283 *out = sign * (ToInt(str[s + 1]) * 100000 + ToInt(str[s + 2]) * 10000 +
284 ToInt(str[s + 3]) * 1000 + ToInt(str[s + 4]) * 100 +
285 ToInt(str[s + 5]) * 10 + ToInt(str[s + 6]));
286 return 7;
287 }
288 return 0;
289}
290
291// DateFourDigitYear: Digit Digit Digit Digit
292template <typename Char>
293int32_t ScanDateFourDigitYear(base::Vector<Char> str, int32_t s, int32_t* out) {
294 if (str.length() < (s + 4)) return 0;
295 if (IsDecimalDigit(str[s]) && IsDecimalDigit(str[s + 1]) &&
296 IsDecimalDigit(str[s + 2]) && IsDecimalDigit(str[s + 3])) {
297 *out = ToInt(str[s]) * 1000 + ToInt(str[s + 1]) * 100 +
298 ToInt(str[s + 2]) * 10 + ToInt(str[s + 3]);
299 return 4;
300 }
301 return 0;
302}
303
304// DateYear:
305// DateFourDigitYear
306// DateExtendedYear
307// The lookahead is at most 1 char.
308SCAN_EITHER_FORWARD(DateYear, DateFourDigitYear, DateExtendedYear, int32_t)template <typename Char> int32_t ScanDateYear(base::Vector
<Char> str, int32_t s, int32_t* r) { int32_t len; if ((
len = ScanDateFourDigitYear(str, s, r)) > 0) return len; return
ScanDateExtendedYear(str, s, r); }
309
310// DateMonth:
311// 0 NonzeroDigit
312// 10
313// 11
314// 12
315template <typename Char>
316int32_t ScanDateMonth(base::Vector<Char> str, int32_t s, int32_t* out) {
317 if (str.length() < (s + 2)) return 0;
318 if (((str[s] == '0') && IsNonZeroDecimalDigit(str[s + 1])) ||
319 ((str[s] == '1') && base::IsInRange(str[s + 1], '0', '2'))) {
320 *out = ToInt(str[s]) * 10 + ToInt(str[s + 1]);
321 return 2;
322 }
323 return 0;
324}
325
326// DateDay:
327// 0 NonzeroDigit
328// 1 Digit
329// 2 Digit
330// 30
331// 31
332template <typename Char>
333int32_t ScanDateDay(base::Vector<Char> str, int32_t s, int32_t* out) {
334 if (str.length() < (s + 2)) return 0;
335 if (((str[s] == '0') && IsNonZeroDecimalDigit(str[s + 1])) ||
336 (base::IsInRange(str[s], '1', '2') && IsDecimalDigit(str[s + 1])) ||
337 ((str[s] == '3') && base::IsInRange(str[s + 1], '0', '1'))) {
338 *out = ToInt(str[s]) * 10 + ToInt(str[s + 1]);
339 return 2;
340 }
341 return 0;
342}
343
344// Date:
345// DateYear - DateMonth - DateDay
346// DateYear DateMonth DateDay
347template <typename Char>
348int32_t ScanDate(base::Vector<Char> str, int32_t s, ParsedISO8601Result* r) {
349 int32_t date_year, date_month, date_day;
350 int32_t cur = s;
351 int32_t len;
352 if ((len = ScanDateYear(str, cur, &date_year)) == 0) return 0;
353 if (((cur += len) + 1) > str.length()) return 0;
354 if (str[cur] == '-') {
355 cur++;
356 if ((len = ScanDateMonth(str, cur, &date_month)) == 0) return 0;
357 cur += len;
358 if (((cur + 1) > str.length()) || (str[cur++] != '-')) return 0;
359 } else {
360 if ((len = ScanDateMonth(str, cur, &date_month)) == 0) return 0;
361 cur += len;
362 }
363 if ((len = ScanDateDay(str, cur, &date_day)) == 0) return 0;
364 r->date_year = date_year;
365 r->date_month = date_month;
366 r->date_day = date_day;
367 return cur + len - s;
368}
369
370// TimeZoneUTCOffsetHour: Hour
371SCAN_FORWARD(TimeZoneUTCOffsetHour, Hour, int32_t)template <typename Char> int32_t ScanTimeZoneUTCOffsetHour
(base::Vector<Char> str, int32_t s, int32_t* r) { return
ScanHour(str, s, r); }
372
373// TimeZoneUTCOffsetMinute
374SCAN_FORWARD(TimeZoneUTCOffsetMinute, MinuteSecond, int32_t)template <typename Char> int32_t ScanTimeZoneUTCOffsetMinute
(base::Vector<Char> str, int32_t s, int32_t* r) { return
ScanMinuteSecond(str, s, r); }
375
376// TimeZoneUTCOffsetSecond
377SCAN_FORWARD(TimeZoneUTCOffsetSecond, MinuteSecond, int32_t)template <typename Char> int32_t ScanTimeZoneUTCOffsetSecond
(base::Vector<Char> str, int32_t s, int32_t* r) { return
ScanMinuteSecond(str, s, r); }
378
379// TimeZoneUTCOffsetFractionalPart: FractionalPart
380// See PR1796
381SCAN_FORWARD(TimeZoneUTCOffsetFractionalPart, FractionalPart, int32_t)template <typename Char> int32_t ScanTimeZoneUTCOffsetFractionalPart
(base::Vector<Char> str, int32_t s, int32_t* r) { return
ScanFractionalPart(str, s, r); }
382
383// TimeZoneUTCOffsetFraction: DecimalSeparator TimeZoneUTCOffsetFractionalPart
384// See PR1796
385template <typename Char>
386int32_t ScanTimeZoneUTCOffsetFraction(base::Vector<Char> str, int32_t s,
387 int32_t* out) {
388 if ((str.length() < (s + 2)) || (!IsDecimalSeparator(str[s]))) return 0;
389 int32_t len;
390 if ((len = ScanTimeZoneUTCOffsetFractionalPart(str, s + 1, out)) > 0) {
391 return len + 1;
392 }
393 return 0;
394}
395
396// Note: "TimeZoneUTCOffset" is abbreviated as "TZUO" below
397// TimeZoneNumericUTCOffset:
398// TZUOSign TZUOHour
399// TZUOSign TZUOHour : TZUOMinute
400// TZUOSign TZUOHour : TZUOMinute : TZUOSecond [TZUOFraction]
401// TZUOSign TZUOHour TZUOMinute
402// TZUOSign TZUOHour TZUOMinute TZUOSecond [TZUOFraction]
403template <typename Char>
404int32_t ScanTimeZoneNumericUTCOffset(base::Vector<Char> str, int32_t s,
405 ParsedISO8601Result* r) {
406 int32_t len, hour, minute, second, nanosecond;
407 int32_t cur = s;
408 if ((str.length() < (cur + 1)) || (!IsSign(str[cur]))) return 0;
409 int32_t sign = (CanonicalSign(str[cur++]) == '-') ? -1 : 1;
410 if ((len = ScanTimeZoneUTCOffsetHour(str, cur, &hour)) == 0) return 0;
411 cur += len;
412 if ((cur + 1) > str.length()) {
413 // TZUOSign TZUOHour
414 r->tzuo_sign = sign;
415 r->tzuo_hour = hour;
416 return cur - s;
417 }
418 if (str[cur] == ':') {
419 cur++;
420 if ((len = ScanTimeZoneUTCOffsetMinute(str, cur, &minute)) == 0) return 0;
421 cur += len;
422 if ((cur + 1) > str.length() || str[cur] != ':') {
423 // TZUOSign TZUOHour : TZUOMinute
424 r->tzuo_sign = sign;
425 r->tzuo_hour = hour;
426 r->tzuo_minute = minute;
427 return cur - s;
428 }
429 cur++;
430 if ((len = ScanTimeZoneUTCOffsetSecond(str, cur, &second)) == 0) return 0;
431 } else {
432 if ((len = ScanTimeZoneUTCOffsetMinute(str, cur, &minute)) == 0) {
433 // TZUOSign TZUOHour
434 r->tzuo_sign = sign;
435 r->tzuo_hour = hour;
436 return cur - s;
437 }
438 cur += len;
439 if ((len = ScanTimeZoneUTCOffsetSecond(str, cur, &second)) == 0) {
440 // TZUOSign TZUOHour TZUOMinute
441 r->tzuo_sign = sign;
442 r->tzuo_hour = hour;
443 r->tzuo_minute = minute;
444 return cur - s;
445 }
446 }
447 cur += len;
448 len = ScanTimeZoneUTCOffsetFraction(str, cur, &nanosecond);
449 r->tzuo_sign = sign;
450 r->tzuo_hour = hour;
451 r->tzuo_minute = minute;
452 r->tzuo_second = second;
453 if (len > 0) r->tzuo_nanosecond = nanosecond;
454 return cur + len - s;
455}
456
457// TimeZoneUTCOffset:
458// TimeZoneNumericUTCOffset
459// UTCDesignator
460template <typename Char>
461int32_t ScanTimeZoneUTCOffset(base::Vector<Char> str, int32_t s,
462 ParsedISO8601Result* r) {
463 if (str.length() < (s + 1)) return 0;
464 if (AsciiAlphaToLower(str[s]) == 'z') {
465 // UTCDesignator
466 r->utc_designator = true;
467 return 1;
468 }
469 // TimeZoneNumericUTCOffset
470 return ScanTimeZoneNumericUTCOffset(str, s, r);
471}
472
473// TimeZoneIANANameComponent :
474// TZLeadingChar TZChar{0,13} but not one of . or ..
475template <typename Char>
476int32_t ScanTimeZoneIANANameComponent(base::Vector<Char> str, int32_t s) {
477 int32_t cur = s;
478 if (str.length() < (cur + 1) || !IsTZLeadingChar(str[cur++])) return 0;
479 while (((cur) < str.length()) && ((cur - s) < 14) && IsTZChar(str[cur])) {
480 cur++;
481 }
482 if ((cur - s) == 1 && str[s] == '.') return 0;
483 if ((cur - s) == 2 && str[s] == '.' && str[s + 1] == '.') return 0;
484 return cur - s;
485}
486
487// TimeZoneIANANameTail :
488// TimeZoneIANANameComponent
489// TimeZoneIANANameComponent / TimeZoneIANANameTail
490// TimeZoneIANAName :
491// TimeZoneIANANameTail
492// The spec text use tail recusion with TimeZoneIANANameComponent and
493// TimeZoneIANANameTail. In our implementation, we use an iteration loop
494// instead.
495template <typename Char>
496int32_t ScanTimeZoneIANAName(base::Vector<Char> str, int32_t s) {
497 int32_t cur = s;
498 int32_t len;
499 if ((len = ScanTimeZoneIANANameComponent(str, cur)) == 0) return 0;
500 cur += len;
501 while ((str.length() > (cur + 1)) && (str[cur] == '/')) {
502 cur++;
503 if ((len = ScanTimeZoneIANANameComponent(str, cur)) == 0) {
504 return 0;
505 }
506 // TimeZoneIANANameComponent / TimeZoneIANAName
507 cur += len;
508 }
509 return cur - s;
510}
511
512template <typename Char>
513int32_t ScanTimeZoneIANAName(base::Vector<Char> str, int32_t s,
514 ParsedISO8601Result* r) {
515 int32_t len;
516 if ((len = ScanTimeZoneIANAName(str, s)) == 0) return 0;
517 r->tzi_name_start = s;
518 r->tzi_name_length = len;
519 return len;
520}
521
522// TimeZoneUTCOffsetName
523// Sign Hour
524// Sign Hour : MinuteSecond
525// Sign Hour MinuteSecond
526// Sign Hour : MinuteSecond : MinuteSecond [Fraction]
527// Sign Hour MinuteSecond MinuteSecond [Fraction]
528//
529template <typename Char>
530int32_t ScanTimeZoneUTCOffsetName(base::Vector<Char> str, int32_t s) {
531 int32_t cur = s;
532 int32_t len;
533 if ((str.length() < (s + 3)) || !IsSign(str[cur++])) return 0;
534 int32_t hour, minute, second, fraction;
535 if ((len = ScanHour(str, cur, &hour)) == 0) return 0;
536 cur += len;
537 if ((cur + 1) > str.length()) {
538 // Sign Hour
539 return cur - s;
540 }
541 if (str[cur] == ':') {
542 // Sign Hour :
543 cur++;
544 if ((len = ScanMinuteSecond(str, cur, &minute)) == 0) return 0;
545 cur += len;
546 if ((cur + 1) > str.length() || (str[cur] != ':')) {
547 // Sign Hour : MinuteSecond
548 return cur - s;
549 }
550 cur++;
551 // Sign Hour : MinuteSecond :
552 if ((len = ScanMinuteSecond(str, cur, &second)) == 0) return 0;
553 cur += len;
554 len = ScanFraction(str, cur, &fraction);
555 return cur + len - s;
556 } else {
557 if ((len = ScanMinuteSecond(str, cur, &minute)) == 0) {
558 // Sign Hour
559 return cur - s;
560 }
561 cur += len;
562 if ((len = ScanMinuteSecond(str, cur, &second)) == 0) {
563 // Sign Hour MinuteSecond
564 return cur - s;
565 }
566 cur += len;
567 len = ScanFraction(str, cur, &fraction);
568 // Sign Hour MinuteSecond MinuteSecond [Fraction]
569 return cur + len - s;
570 }
571}
572
573// TimeZoneBracketedName
574// TimeZoneIANAName
575// "Etc/GMT" ASCIISign Hour
576// TimeZoneUTCOffsetName
577// Since "Etc/GMT" also fit TimeZoneIANAName so we need to try
578// "Etc/GMT" ASCIISign Hour first.
579template <typename Char>
580int32_t ScanEtcGMTAsciiSignHour(base::Vector<Char> str, int32_t s) {
581 if ((s + 10) > str.length()) return 0;
582 int32_t cur = s;
583 if ((str[cur++] != 'E') || (str[cur++] != 't') || (str[cur++] != 'c') ||
584 (str[cur++] != '/') || (str[cur++] != 'G') || (str[cur++] != 'M') ||
585 (str[cur++] != 'T')) {
586 return 0;
587 }
588 Char sign = str[cur++];
589 if (!IsAsciiSign(sign)) return 0;
590 int32_t hour;
591 int32_t len = ScanHour(str, cur, &hour);
592 if (len == 0) return 0;
593 // "Etc/GMT" ASCIISign Hour
594 return 10;
595}
596
597template <typename Char>
598int32_t ScanTimeZoneBracketedName(base::Vector<Char> str, int32_t s,
599 ParsedISO8601Result* r) {
600 int32_t len;
601 if ((len = ScanEtcGMTAsciiSignHour(str, s)) > 0) return len;
602 if ((len = ScanTimeZoneIANAName(str, s)) > 0) {
603 r->tzi_name_start = s;
604 r->tzi_name_length = len;
605 return len;
606 }
607 return ScanTimeZoneUTCOffsetName(str, s);
608}
609
610// TimeZoneBracketedAnnotation: '[' TimeZoneBracketedName ']'
611template <typename Char>
612int32_t ScanTimeZoneBracketedAnnotation(base::Vector<Char> str, int32_t s,
613 ParsedISO8601Result* r) {
614 if ((str.length() < (s + 3)) || (str[s] != '[')) return 0;
615 int32_t cur = s + 1;
616 cur += ScanTimeZoneBracketedName(str, cur, r);
617 if ((cur - s == 1) || str.length() < (cur + 1) || (str[cur++] != ']')) {
618 return 0;
619 }
620 return cur - s;
621}
622
623// TimeZoneOffsetRequired:
624// TimeZoneUTCOffset [TimeZoneBracketedAnnotation]
625template <typename Char>
626int32_t ScanTimeZoneOffsetRequired(base::Vector<Char> str, int32_t s,
627 ParsedISO8601Result* r) {
628 int32_t cur = s;
629 cur += ScanTimeZoneUTCOffset(str, cur, r);
630 if (cur == s) return 0;
631 return cur + ScanTimeZoneBracketedAnnotation(str, cur, r) - s;
632}
633
634// TimeZoneNameRequired:
635// [TimeZoneUTCOffset] TimeZoneBracketedAnnotation
636template <typename Char>
637int32_t ScanTimeZoneNameRequired(base::Vector<Char> str, int32_t s,
638 ParsedISO8601Result* r) {
639 int32_t cur = s;
640 cur += ScanTimeZoneUTCOffset(str, cur, r);
641 int32_t len = ScanTimeZoneBracketedAnnotation(str, cur, r);
642 if (len == 0) return 0;
643 return cur + len - s;
644}
645
646// TimeZone:
647// TimeZoneOffsetRequired
648// TimeZoneNameRequired
649// The lookahead is at most 1 char.
650SCAN_EITHER_FORWARD(TimeZone, TimeZoneOffsetRequired, TimeZoneNameRequired,template <typename Char> int32_t ScanTimeZone(base::Vector
<Char> str, int32_t s, ParsedISO8601Result* r) { int32_t
len; if ((len = ScanTimeZoneOffsetRequired(str, s, r)) > 0
) return len; return ScanTimeZoneNameRequired(str, s, r); }
651 ParsedISO8601Result)template <typename Char> int32_t ScanTimeZone(base::Vector
<Char> str, int32_t s, ParsedISO8601Result* r) { int32_t
len; if ((len = ScanTimeZoneOffsetRequired(str, s, r)) > 0
) return len; return ScanTimeZoneNameRequired(str, s, r); }
652
653// CalendarNameComponent:
654// CalChar {3,8}
655template <typename Char>
656int32_t ScanCalendarNameComponent(base::Vector<Char> str, int32_t s) {
657 int32_t cur = s;
658 while ((cur < str.length()) && IsAlphaNumeric(str[cur])) cur++;
659 if ((cur - s) < 3 || (cur - s) > 8) return 0;
660 return (cur - s);
661}
662
663// CalendarNameTail :
664// CalendarNameComponent
665// CalendarNameComponent - CalendarNameTail
666// CalendarName :
667// CalendarNameTail
668// The spec text use tail recusion with CalendarNameComponent and
669// CalendarNameTail. In our implementation, we use an iteration loop instead.
670template <typename Char>
671int32_t ScanCalendarName(base::Vector<Char> str, int32_t s,
672 ParsedISO8601Result* r) {
673 int32_t cur = s;
674 int32_t len;
675 if ((len = ScanCalendarNameComponent(str, cur)) == 0) return 0;
676 cur += len;
677 while ((str.length() > (cur + 1)) && (str[cur++] == '-')) {
678 if ((len = ScanCalendarNameComponent(str, cur)) == 0) return 0;
679 // CalendarNameComponent - CalendarName
680 cur += len;
681 }
682 r->calendar_name_start = s;
683 r->calendar_name_length = cur - s;
684 return cur - s;
685}
686
687// Calendar: '[u-ca=' CalendarName ']'
688template <typename Char>
689int32_t ScanCalendar(base::Vector<Char> str, int32_t s,
690 ParsedISO8601Result* r) {
691 if (str.length() < (s + 7)) return 0;
692 int32_t cur = s;
693 // "[u-ca="
694 if ((str[cur++] != '[') || (str[cur++] != 'u') || (str[cur++] != '-') ||
695 (str[cur++] != 'c') || (str[cur++] != 'a') || (str[cur++] != '=')) {
696 return 0;
697 }
698 int32_t len = ScanCalendarName(str, cur, r);
699 if (len == 0) return 0;
700 if ((str.length() < (cur + len + 1)) || (str[cur + len] != ']')) {
701 return 0;
702 }
703 return 6 + len + 1;
704}
705
706// CalendarTime: TimeSpec [TimeZone] [Calendar]
707template <typename Char>
708int32_t ScanCalendarTime(base::Vector<Char> str, int32_t s,
709 ParsedISO8601Result* r) {
710 int32_t cur = s;
711 cur += ScanTimeSpec(str, cur, r);
712 if (cur - s == 0) return 0;
713 cur += ScanTimeZone(str, cur, r);
714 cur += ScanCalendar(str, cur, r);
715 return cur - s;
716}
717
718// DateTime: Date [TimeSpecSeparator][TimeZone]
719template <typename Char>
720int32_t ScanDateTime(base::Vector<Char> str, int32_t s,
721 ParsedISO8601Result* r) {
722 int32_t cur = s;
723 cur += ScanDate(str, cur, r);
724 if (cur == s) return 0;
725 cur += ScanTimeSpecSeparator(str, cur, r);
726 return cur + ScanTimeZone(str, cur, r) - s;
727}
728
729// DateSpecYearMonth: DateYear ['-'] DateMonth
730template <typename Char>
731int32_t ScanDateSpecYearMonth(base::Vector<Char> str, int32_t s,
732 ParsedISO8601Result* r) {
733 int32_t date_year, date_month;
734 int32_t cur = s;
735 cur += ScanDateYear(str, cur, &date_year);
736 if (cur == s) return 0;
737 if (str.length() < (cur + 1)) return 0;
738 if (str[cur] == '-') cur++;
739 int32_t len = ScanDateMonth(str, cur, &date_month);
740 if (len == 0) return 0;
741 r->date_year = date_year;
742 r->date_month = date_month;
743 return cur + len - s;
744}
745
746// DateSpecMonthDay:
747// TwoDashopt DateMonth -opt DateDay
748template <typename Char>
749int32_t ScanDateSpecMonthDay(base::Vector<Char> str, int32_t s,
750 ParsedISO8601Result* r) {
751 if (str.length() < (s + 4)) return 0;
752 int32_t cur = s;
753 if (str[cur] == '-') {
754 // The first two dash are optional together
755 if (str[++cur] != '-') return 0;
756 // TwoDash
757 cur++;
758 }
759 int32_t date_month, date_day;
760 int32_t len = ScanDateMonth(str, cur, &date_month);
761 if (len == 0) return 0;
762 cur += len;
763 if (str.length() < (cur + 1)) return 0;
764 // '-'
765 if (str[cur] == '-') cur++;
766 len = ScanDateDay(str, cur, &date_day);
767 if (len == 0) return 0;
768 r->date_month = date_month;
769 r->date_day = date_day;
770 return cur + len - s;
771}
772
773// TemporalTimeZoneIdentifier:
774// TimeZoneNumericUTCOffset
775// TimeZoneIANAName
776template <typename Char>
777int32_t ScanTemporalTimeZoneIdentifier(base::Vector<Char> str, int32_t s,
778 ParsedISO8601Result* r) {
779 int32_t len;
780 if ((len = ScanTimeZoneNumericUTCOffset(str, s, r)) > 0) return len;
781 if ((len = ScanTimeZoneIANAName(str, s)) == 0) return 0;
782 r->tzi_name_start = s;
783 r->tzi_name_length = len;
784 return len;
785}
786
787// CalendarDateTime: DateTime [Calendar]
788template <typename Char>
789int32_t ScanCalendarDateTime(base::Vector<Char> str, int32_t s,
790 ParsedISO8601Result* r) {
791 int32_t len = ScanDateTime(str, 0, r);
792 if (len == 0) return 0;
793 return len + ScanCalendar(str, len, r);
794}
795
796// TemporalZonedDateTimeString:
797// Date [TimeSpecSeparator] TimeZoneNameRequired [Calendar]
798template <typename Char>
799int32_t ScanTemporalZonedDateTimeString(base::Vector<Char> str, int32_t s,
800 ParsedISO8601Result* r) {
801 // Date
802 int32_t cur = s;
803 cur += ScanDate(str, cur, r);
804 if (cur == s) return 0;
805
806 // TimeSpecSeparator
807 cur += ScanTimeSpecSeparator(str, cur, r);
808
809 // TimeZoneNameRequired
810 int32_t len = ScanTimeZoneNameRequired(str, cur, r);
811 if (len == 0) return 0;
812 cur += len;
813
814 // Calendar
815 return cur + ScanCalendar(str, cur, r) - s;
816}
817
818SCAN_FORWARD(TemporalDateString, CalendarDateTime, ParsedISO8601Result)template <typename Char> int32_t ScanTemporalDateString
(base::Vector<Char> str, int32_t s, ParsedISO8601Result
* r) { return ScanCalendarDateTime(str, s, r); }
819SCAN_FORWARD(TemporalDateTimeString, CalendarDateTime, ParsedISO8601Result)template <typename Char> int32_t ScanTemporalDateTimeString
(base::Vector<Char> str, int32_t s, ParsedISO8601Result
* r) { return ScanCalendarDateTime(str, s, r); }
820
821// TemporalTimeZoneString:
822// TemporalTimeZoneIdentifier
823// Date [TimeSpecSeparator] TimeZone [Calendar]
824template <typename Char>
825int32_t ScanDate_TimeSpecSeparator_TimeZone_Calendar(base::Vector<Char> str,
826 int32_t s,
827 ParsedISO8601Result* r) {
828 int32_t cur = s;
829 cur += ScanDate(str, cur, r);
830 if (cur == s) return 0;
831 cur += ScanTimeSpecSeparator(str, cur, r);
832 int32_t len = ScanTimeZone(str, cur, r);
833 if (len == 0) return 0;
834 cur += len;
835 return cur + ScanCalendar(str, cur, r) - s;
836}
837
838// The lookahead is at most 8 chars.
839SCAN_EITHER_FORWARD(TemporalTimeZoneString, TemporalTimeZoneIdentifier,template <typename Char> int32_t ScanTemporalTimeZoneString
(base::Vector<Char> str, int32_t s, ParsedISO8601Result
* r) { int32_t len; if ((len = ScanTemporalTimeZoneIdentifier
(str, s, r)) > 0) return len; return ScanDate_TimeSpecSeparator_TimeZone_Calendar
(str, s, r); }
840 Date_TimeSpecSeparator_TimeZone_Calendar,template <typename Char> int32_t ScanTemporalTimeZoneString
(base::Vector<Char> str, int32_t s, ParsedISO8601Result
* r) { int32_t len; if ((len = ScanTemporalTimeZoneIdentifier
(str, s, r)) > 0) return len; return ScanDate_TimeSpecSeparator_TimeZone_Calendar
(str, s, r); }
841 ParsedISO8601Result)template <typename Char> int32_t ScanTemporalTimeZoneString
(base::Vector<Char> str, int32_t s, ParsedISO8601Result
* r) { int32_t len; if ((len = ScanTemporalTimeZoneIdentifier
(str, s, r)) > 0) return len; return ScanDate_TimeSpecSeparator_TimeZone_Calendar
(str, s, r); }
842
843// TemporalTimeString
844// CalendarTime
845// CalendarDateTime
846// The lookahead is at most 7 chars.
847SCAN_EITHER_FORWARD(TemporalTimeString, CalendarTime, CalendarDateTime,template <typename Char> int32_t ScanTemporalTimeString
(base::Vector<Char> str, int32_t s, ParsedISO8601Result
* r) { int32_t len; if ((len = ScanCalendarTime(str, s, r)) >
0) return len; return ScanCalendarDateTime(str, s, r); }
848 ParsedISO8601Result)template <typename Char> int32_t ScanTemporalTimeString
(base::Vector<Char> str, int32_t s, ParsedISO8601Result
* r) { int32_t len; if ((len = ScanCalendarTime(str, s, r)) >
0) return len; return ScanCalendarDateTime(str, s, r); }
849
850// TemporalYearMonthString:
851// DateSpecYearMonth
852// CalendarDateTime
853// The lookahead is at most 11 chars.
854SCAN_EITHER_FORWARD(TemporalYearMonthString, DateSpecYearMonth,template <typename Char> int32_t ScanTemporalYearMonthString
(base::Vector<Char> str, int32_t s, ParsedISO8601Result
* r) { int32_t len; if ((len = ScanDateSpecYearMonth(str, s, r
)) > 0) return len; return ScanCalendarDateTime(str, s, r)
; }
855 CalendarDateTime, ParsedISO8601Result)template <typename Char> int32_t ScanTemporalYearMonthString
(base::Vector<Char> str, int32_t s, ParsedISO8601Result
* r) { int32_t len; if ((len = ScanDateSpecYearMonth(str, s, r
)) > 0) return len; return ScanCalendarDateTime(str, s, r)
; }
856
857// TemporalMonthDayString
858// DateSpecMonthDay
859// CalendarDateTime
860// The lookahead is at most 5 chars.
861SCAN_EITHER_FORWARD(TemporalMonthDayString, DateSpecMonthDay, CalendarDateTime,template <typename Char> int32_t ScanTemporalMonthDayString
(base::Vector<Char> str, int32_t s, ParsedISO8601Result
* r) { int32_t len; if ((len = ScanDateSpecMonthDay(str, s, r
)) > 0) return len; return ScanCalendarDateTime(str, s, r)
; }
862 ParsedISO8601Result)template <typename Char> int32_t ScanTemporalMonthDayString
(base::Vector<Char> str, int32_t s, ParsedISO8601Result
* r) { int32_t len; if ((len = ScanDateSpecMonthDay(str, s, r
)) > 0) return len; return ScanCalendarDateTime(str, s, r)
; }
863
864// TemporalRelativeToString:
865// TemporalDateTimeString
866// TemporalZonedDateTimeString
867// TemporalZonedDateTimeString is subset of TemporalDateTimeString
868// See https://github.com/tc39/proposal-temporal/issues/1939
869SCAN_FORWARD(TemporalRelativeToString, TemporalDateTimeString,template <typename Char> int32_t ScanTemporalRelativeToString
(base::Vector<Char> str, int32_t s, ParsedISO8601Result
* r) { return ScanTemporalDateTimeString(str, s, r); }
870 ParsedISO8601Result)template <typename Char> int32_t ScanTemporalRelativeToString
(base::Vector<Char> str, int32_t s, ParsedISO8601Result
* r) { return ScanTemporalDateTimeString(str, s, r); }
871
872// TemporalInstantString
873// Date TimeZoneOffsetRequired
874// Date DateTimeSeparator TimeSpec TimeZoneOffsetRequired
875template <typename Char>
876int32_t ScanTemporalInstantString(base::Vector<Char> str, int32_t s,
877 ParsedISO8601Result* r) {
878 // Date
879 int32_t cur = s;
880 cur += ScanDate(str, cur, r);
881 if (cur == s) return 0;
882
883 // TimeZoneOffsetRequired
884 int32_t len = ScanTimeZoneOffsetRequired(str, cur, r);
885 if (len > 0) return cur + len - s;
886
887 // DateTimeSeparator
888 if (!(((cur + 1) < str.length()) && IsDateTimeSeparator(str[cur++]))) {
889 return 0;
890 }
891 // TimeSpec
892 len = ScanTimeSpec(str, cur, r);
893 if (len == 0) return 0;
894 cur += len;
895
896 // TimeZoneOffsetRequired
897 len = ScanTimeZoneOffsetRequired(str, cur, r);
898 if (len == 0) return 0;
899 return cur + len - s;
900}
901
902// ==============================================================================
903#define SATISIFY(T, R)template <typename Char> bool SatisfyT(base::Vector<
Char> str, R* r) { R ret; int32_t len = ScanT(str, 0, &
ret); if ((len > 0) && (len == str.length())) { *r
= ret; return true; } return false; }
\
904 template <typename Char> \
905 bool Satisfy##T(base::Vector<Char> str, R* r) { \
906 R ret; \
907 int32_t len = Scan##T(str, 0, &ret); \
908 if ((len > 0) && (len == str.length())) { \
909 *r = ret; \
910 return true; \
911 } \
912 return false; \
913 }
914
915#define IF_SATISFY_RETURN(T){ if (SatisfyT(str, r)) return true; } \
916 { \
917 if (Satisfy##T(str, r)) return true; \
918 }
919
920#define SATISIFY_EITHER(T1, T2, T3, R)template <typename Char> bool SatisfyT1(base::Vector<
Char> str, R* r) { { if (SatisfyT2(str, r)) return true; }
{ if (SatisfyT3(str, r)) return true; } return false; }
\
921 template <typename Char> \
922 bool Satisfy##T1(base::Vector<Char> str, R* r) { \
923 IF_SATISFY_RETURN(T2){ if (SatisfyT2(str, r)) return true; } \
924 IF_SATISFY_RETURN(T3){ if (SatisfyT3(str, r)) return true; } \
925 return false; \
926 }
927
928SATISIFY(TemporalDateTimeString, ParsedISO8601Result)template <typename Char> bool SatisfyTemporalDateTimeString
(base::Vector<Char> str, ParsedISO8601Result* r) { ParsedISO8601Result
ret; int32_t len = ScanTemporalDateTimeString(str, 0, &ret
); if ((len > 0) && (len == str.length())) { *r = ret
; return true; } return false; }
929SATISIFY(TemporalDateString, ParsedISO8601Result)template <typename Char> bool SatisfyTemporalDateString
(base::Vector<Char> str, ParsedISO8601Result* r) { ParsedISO8601Result
ret; int32_t len = ScanTemporalDateString(str, 0, &ret);
if ((len > 0) && (len == str.length())) { *r = ret
; return true; } return false; }
930SATISIFY(CalendarTime, ParsedISO8601Result)template <typename Char> bool SatisfyCalendarTime(base::
Vector<Char> str, ParsedISO8601Result* r) { ParsedISO8601Result
ret; int32_t len = ScanCalendarTime(str, 0, &ret); if ((
len > 0) && (len == str.length())) { *r = ret; return
true; } return false; }
931SATISIFY(DateTime, ParsedISO8601Result)template <typename Char> bool SatisfyDateTime(base::Vector
<Char> str, ParsedISO8601Result* r) { ParsedISO8601Result
ret; int32_t len = ScanDateTime(str, 0, &ret); if ((len >
0) && (len == str.length())) { *r = ret; return true
; } return false; }
932SATISIFY(DateSpecYearMonth, ParsedISO8601Result)template <typename Char> bool SatisfyDateSpecYearMonth(
base::Vector<Char> str, ParsedISO8601Result* r) { ParsedISO8601Result
ret; int32_t len = ScanDateSpecYearMonth(str, 0, &ret); if
((len > 0) && (len == str.length())) { *r = ret; return
true; } return false; }
933SATISIFY(DateSpecMonthDay, ParsedISO8601Result)template <typename Char> bool SatisfyDateSpecMonthDay(base
::Vector<Char> str, ParsedISO8601Result* r) { ParsedISO8601Result
ret; int32_t len = ScanDateSpecMonthDay(str, 0, &ret); if
((len > 0) && (len == str.length())) { *r = ret; return
true; } return false; }
934SATISIFY(Date_TimeSpecSeparator_TimeZone_Calendar, ParsedISO8601Result)template <typename Char> bool SatisfyDate_TimeSpecSeparator_TimeZone_Calendar
(base::Vector<Char> str, ParsedISO8601Result* r) { ParsedISO8601Result
ret; int32_t len = ScanDate_TimeSpecSeparator_TimeZone_Calendar
(str, 0, &ret); if ((len > 0) && (len == str.length
())) { *r = ret; return true; } return false; }
935SATISIFY(CalendarDateTime, ParsedISO8601Result)template <typename Char> bool SatisfyCalendarDateTime(base
::Vector<Char> str, ParsedISO8601Result* r) { ParsedISO8601Result
ret; int32_t len = ScanCalendarDateTime(str, 0, &ret); if
((len > 0) && (len == str.length())) { *r = ret; return
true; } return false; }
936SATISIFY_EITHER(TemporalTimeString, CalendarTime, CalendarDateTime,template <typename Char> bool SatisfyTemporalTimeString
(base::Vector<Char> str, ParsedISO8601Result* r) { { if
(SatisfyCalendarTime(str, r)) return true; } { if (SatisfyCalendarDateTime
(str, r)) return true; } return false; }
937 ParsedISO8601Result)template <typename Char> bool SatisfyTemporalTimeString
(base::Vector<Char> str, ParsedISO8601Result* r) { { if
(SatisfyCalendarTime(str, r)) return true; } { if (SatisfyCalendarDateTime
(str, r)) return true; } return false; }
938SATISIFY_EITHER(TemporalYearMonthString, DateSpecYearMonth, CalendarDateTime,template <typename Char> bool SatisfyTemporalYearMonthString
(base::Vector<Char> str, ParsedISO8601Result* r) { { if
(SatisfyDateSpecYearMonth(str, r)) return true; } { if (SatisfyCalendarDateTime
(str, r)) return true; } return false; }
939 ParsedISO8601Result)template <typename Char> bool SatisfyTemporalYearMonthString
(base::Vector<Char> str, ParsedISO8601Result* r) { { if
(SatisfyDateSpecYearMonth(str, r)) return true; } { if (SatisfyCalendarDateTime
(str, r)) return true; } return false; }
940SATISIFY_EITHER(TemporalMonthDayString, DateSpecMonthDay, CalendarDateTime,template <typename Char> bool SatisfyTemporalMonthDayString
(base::Vector<Char> str, ParsedISO8601Result* r) { { if
(SatisfyDateSpecMonthDay(str, r)) return true; } { if (SatisfyCalendarDateTime
(str, r)) return true; } return false; }
941 ParsedISO8601Result)template <typename Char> bool SatisfyTemporalMonthDayString
(base::Vector<Char> str, ParsedISO8601Result* r) { { if
(SatisfyDateSpecMonthDay(str, r)) return true; } { if (SatisfyCalendarDateTime
(str, r)) return true; } return false; }
942SATISIFY(TimeZoneNumericUTCOffset, ParsedISO8601Result)template <typename Char> bool SatisfyTimeZoneNumericUTCOffset
(base::Vector<Char> str, ParsedISO8601Result* r) { ParsedISO8601Result
ret; int32_t len = ScanTimeZoneNumericUTCOffset(str, 0, &
ret); if ((len > 0) && (len == str.length())) { *r
= ret; return true; } return false; }
943SATISIFY(TimeZoneIANAName, ParsedISO8601Result)template <typename Char> bool SatisfyTimeZoneIANAName(base
::Vector<Char> str, ParsedISO8601Result* r) { ParsedISO8601Result
ret; int32_t len = ScanTimeZoneIANAName(str, 0, &ret); if
((len > 0) && (len == str.length())) { *r = ret; return
true; } return false; }
944SATISIFY_EITHER(TemporalTimeZoneIdentifier, TimeZoneNumericUTCOffset,template <typename Char> bool SatisfyTemporalTimeZoneIdentifier
(base::Vector<Char> str, ParsedISO8601Result* r) { { if
(SatisfyTimeZoneNumericUTCOffset(str, r)) return true; } { if
(SatisfyTimeZoneIANAName(str, r)) return true; } return false
; }
945 TimeZoneIANAName, ParsedISO8601Result)template <typename Char> bool SatisfyTemporalTimeZoneIdentifier
(base::Vector<Char> str, ParsedISO8601Result* r) { { if
(SatisfyTimeZoneNumericUTCOffset(str, r)) return true; } { if
(SatisfyTimeZoneIANAName(str, r)) return true; } return false
; }
946SATISIFY_EITHER(TemporalTimeZoneString, TemporalTimeZoneIdentifier,template <typename Char> bool SatisfyTemporalTimeZoneString
(base::Vector<Char> str, ParsedISO8601Result* r) { { if
(SatisfyTemporalTimeZoneIdentifier(str, r)) return true; } {
if (SatisfyDate_TimeSpecSeparator_TimeZone_Calendar(str, r))
return true; } return false; }
947 Date_TimeSpecSeparator_TimeZone_Calendar, ParsedISO8601Result)template <typename Char> bool SatisfyTemporalTimeZoneString
(base::Vector<Char> str, ParsedISO8601Result* r) { { if
(SatisfyTemporalTimeZoneIdentifier(str, r)) return true; } {
if (SatisfyDate_TimeSpecSeparator_TimeZone_Calendar(str, r))
return true; } return false; }
948SATISIFY(TemporalInstantString, ParsedISO8601Result)template <typename Char> bool SatisfyTemporalInstantString
(base::Vector<Char> str, ParsedISO8601Result* r) { ParsedISO8601Result
ret; int32_t len = ScanTemporalInstantString(str, 0, &ret
); if ((len > 0) && (len == str.length())) { *r = ret
; return true; } return false; }
949SATISIFY(TemporalZonedDateTimeString, ParsedISO8601Result)template <typename Char> bool SatisfyTemporalZonedDateTimeString
(base::Vector<Char> str, ParsedISO8601Result* r) { ParsedISO8601Result
ret; int32_t len = ScanTemporalZonedDateTimeString(str, 0, &
ret); if ((len > 0) && (len == str.length())) { *r
= ret; return true; } return false; }
950
951SATISIFY_EITHER(TemporalRelativeToString, TemporalDateTimeString,template <typename Char> bool SatisfyTemporalRelativeToString
(base::Vector<Char> str, ParsedISO8601Result* r) { { if
(SatisfyTemporalDateTimeString(str, r)) return true; } { if (
SatisfyTemporalZonedDateTimeString(str, r)) return true; } return
false; }
952 TemporalZonedDateTimeString, ParsedISO8601Result)template <typename Char> bool SatisfyTemporalRelativeToString
(base::Vector<Char> str, ParsedISO8601Result* r) { { if
(SatisfyTemporalDateTimeString(str, r)) return true; } { if (
SatisfyTemporalZonedDateTimeString(str, r)) return true; } return
false; }
953
954SATISIFY(CalendarName, ParsedISO8601Result)template <typename Char> bool SatisfyCalendarName(base::
Vector<Char> str, ParsedISO8601Result* r) { ParsedISO8601Result
ret; int32_t len = ScanCalendarName(str, 0, &ret); if ((
len > 0) && (len == str.length())) { *r = ret; return
true; } return false; }
955
956template <typename Char>
957bool SatisfyTemporalCalendarString(base::Vector<Char> str,
958 ParsedISO8601Result* r) {
959 IF_SATISFY_RETURN(CalendarName){ if (SatisfyCalendarName(str, r)) return true; }
960 IF_SATISFY_RETURN(TemporalInstantString){ if (SatisfyTemporalInstantString(str, r)) return true; }
961 IF_SATISFY_RETURN(CalendarDateTime){ if (SatisfyCalendarDateTime(str, r)) return true; }
962 IF_SATISFY_RETURN(CalendarTime){ if (SatisfyCalendarTime(str, r)) return true; }
963 IF_SATISFY_RETURN(DateSpecYearMonth){ if (SatisfyDateSpecYearMonth(str, r)) return true; }
964 IF_SATISFY_RETURN(DateSpecMonthDay){ if (SatisfyDateSpecMonthDay(str, r)) return true; }
965 return false;
966}
967
968// Duration
969
970SCAN_FORWARD(TimeFractionalPart, FractionalPart, int64_t)template <typename Char> int32_t ScanTimeFractionalPart
(base::Vector<Char> str, int32_t s, int64_t* r) { return
ScanFractionalPart(str, s, r); }
9
Calling 'ScanFractionalPart<const unsigned short>'
971
972template <typename Char>
973int32_t ScanFraction(base::Vector<Char> str, int32_t s, int64_t* out) {
974 if (str.length() < (s + 2) || !IsDecimalSeparator(str[s])) return 0;
6
Assuming the condition is false
7
Taking false branch
975 int32_t len = ScanTimeFractionalPart(str, s + 1, out);
8
Calling 'ScanTimeFractionalPart<const unsigned short>'
976 return (len == 0) ? 0 : len + 1;
977}
978
979SCAN_FORWARD(TimeFraction, Fraction, int64_t)template <typename Char> int32_t ScanTimeFraction(base::
Vector<Char> str, int32_t s, int64_t* r) { return ScanFraction
(str, s, r); }
5
Calling 'ScanFraction<const unsigned short>'
980
981// Digits : Digit [Digits]
982
983template <typename Char>
984int32_t ScanDigits(base::Vector<Char> str, int32_t s, int64_t* out) {
985 if (str.length() < (s + 1) || !IsDecimalDigit(str[s])) return 0;
986 *out = ToInt(str[s]);
987 int32_t len = 1;
988 while (s + len + 1 <= str.length() && IsDecimalDigit(str[s + len])) {
989 *out = 10 * (*out) + ToInt(str[s + len]);
990 len++;
991 }
992 return len;
993}
994
995SCAN_FORWARD(DurationYears, Digits, int64_t)template <typename Char> int32_t ScanDurationYears(base
::Vector<Char> str, int32_t s, int64_t* r) { return ScanDigits
(str, s, r); }
996SCAN_FORWARD(DurationMonths, Digits, int64_t)template <typename Char> int32_t ScanDurationMonths(base
::Vector<Char> str, int32_t s, int64_t* r) { return ScanDigits
(str, s, r); }
997SCAN_FORWARD(DurationWeeks, Digits, int64_t)template <typename Char> int32_t ScanDurationWeeks(base
::Vector<Char> str, int32_t s, int64_t* r) { return ScanDigits
(str, s, r); }
998SCAN_FORWARD(DurationDays, Digits, int64_t)template <typename Char> int32_t ScanDurationDays(base::
Vector<Char> str, int32_t s, int64_t* r) { return ScanDigits
(str, s, r); }
999
1000// DurationWholeHours : Digits
1001SCAN_FORWARD(DurationWholeHours, Digits, int64_t)template <typename Char> int32_t ScanDurationWholeHours
(base::Vector<Char> str, int32_t s, int64_t* r) { return
ScanDigits(str, s, r); }
1002
1003// DurationWholeMinutes : Digits
1004SCAN_FORWARD(DurationWholeMinutes, Digits, int64_t)template <typename Char> int32_t ScanDurationWholeMinutes
(base::Vector<Char> str, int32_t s, int64_t* r) { return
ScanDigits(str, s, r); }
1005
1006// DurationWholeSeconds : Digits
1007SCAN_FORWARD(DurationWholeSeconds, Digits, int64_t)template <typename Char> int32_t ScanDurationWholeSeconds
(base::Vector<Char> str, int32_t s, int64_t* r) { return
ScanDigits(str, s, r); }
1008
1009// DurationHoursFraction : TimeFraction
1010SCAN_FORWARD(DurationHoursFraction, TimeFraction, int64_t)template <typename Char> int32_t ScanDurationHoursFraction
(base::Vector<Char> str, int32_t s, int64_t* r) { return
ScanTimeFraction(str, s, r); }
4
Calling 'ScanTimeFraction<const unsigned short>'
1011
1012// DurationMinutesFraction : TimeFraction
1013SCAN_FORWARD(DurationMinutesFraction, TimeFraction, int64_t)template <typename Char> int32_t ScanDurationMinutesFraction
(base::Vector<Char> str, int32_t s, int64_t* r) { return
ScanTimeFraction(str, s, r); }
1014
1015// DurationSecondsFraction : TimeFraction
1016SCAN_FORWARD(DurationSecondsFraction, TimeFraction, int64_t)template <typename Char> int32_t ScanDurationSecondsFraction
(base::Vector<Char> str, int32_t s, int64_t* r) { return
ScanTimeFraction(str, s, r); }
1017
1018#define DURATION_WHOLE_FRACTION_DESIGNATOR(Name, name, d)template <typename Char> int32_t ScanDurationWholeNameFractionDesignator
( base::Vector<Char> str, int32_t s, ParsedISO8601Duration
* r) { int32_t cur = s; int64_t whole = 0; cur += ScanDurationWholeName
(str, cur, &whole); if (cur == s) return 0; int64_t fraction
= 0; int32_t len = ScanDurationNameFraction(str, cur, &fraction
); cur += len; if (str.length() < (cur + 1) || AsciiAlphaToLower
(str[cur++]) != (d)) return 0; r->whole_name = whole; r->
name_fraction = fraction; return cur - s; }
\
1019 template <typename Char> \
1020 int32_t ScanDurationWhole##Name##FractionDesignator( \
1021 base::Vector<Char> str, int32_t s, ParsedISO8601Duration* r) { \
1022 int32_t cur = s; \
1023 int64_t whole = 0; \
1024 cur += ScanDurationWhole##Name(str, cur, &whole); \
1025 if (cur == s) return 0; \
1026 int64_t fraction = 0; \
1027 int32_t len = ScanDuration##Name##Fraction(str, cur, &fraction); \
1028 cur += len; \
1029 if (str.length() < (cur + 1) || AsciiAlphaToLower(str[cur++]) != (d)) \
1030 return 0; \
1031 r->whole_##name = whole; \
1032 r->name##_fraction = fraction; \
1033 return cur - s; \
1034 }
1035
1036DURATION_WHOLE_FRACTION_DESIGNATOR(Seconds, seconds, 's')template <typename Char> int32_t ScanDurationWholeSecondsFractionDesignator
( base::Vector<Char> str, int32_t s, ParsedISO8601Duration
* r) { int32_t cur = s; int64_t whole = 0; cur += ScanDurationWholeSeconds
(str, cur, &whole); if (cur == s) return 0; int64_t fraction
= 0; int32_t len = ScanDurationSecondsFraction(str, cur, &
fraction); cur += len; if (str.length() < (cur + 1) || AsciiAlphaToLower
(str[cur++]) != ('s')) return 0; r->whole_seconds = whole;
r->seconds_fraction = fraction; return cur - s; }
1037DURATION_WHOLE_FRACTION_DESIGNATOR(Minutes, minutes, 'm')template <typename Char> int32_t ScanDurationWholeMinutesFractionDesignator
( base::Vector<Char> str, int32_t s, ParsedISO8601Duration
* r) { int32_t cur = s; int64_t whole = 0; cur += ScanDurationWholeMinutes
(str, cur, &whole); if (cur == s) return 0; int64_t fraction
= 0; int32_t len = ScanDurationMinutesFraction(str, cur, &
fraction); cur += len; if (str.length() < (cur + 1) || AsciiAlphaToLower
(str[cur++]) != ('m')) return 0; r->whole_minutes = whole;
r->minutes_fraction = fraction; return cur - s; }
1038DURATION_WHOLE_FRACTION_DESIGNATOR(Hours, hours, 'h')template <typename Char> int32_t ScanDurationWholeHoursFractionDesignator
( base::Vector<Char> str, int32_t s, ParsedISO8601Duration
* r) { int32_t cur = s; int64_t whole = 0; cur += ScanDurationWholeHours
(str, cur, &whole); if (cur == s) return 0; int64_t fraction
= 0; int32_t len = ScanDurationHoursFraction(str, cur, &
fraction); cur += len; if (str.length() < (cur + 1) || AsciiAlphaToLower
(str[cur++]) != ('h')) return 0; r->whole_hours = whole; r
->hours_fraction = fraction; return cur - s; }
1
Assuming 'cur' is not equal to 's'
2
Taking false branch
3
Calling 'ScanDurationHoursFraction<const unsigned short>'
1039
1040// DurationSecondsPart :
1041// DurationWholeSeconds DurationSecondsFractionopt SecondsDesignator
1042SCAN_FORWARD(DurationSecondsPart, DurationWholeSecondsFractionDesignator,template <typename Char> int32_t ScanDurationSecondsPart
(base::Vector<Char> str, int32_t s, ParsedISO8601Duration
* r) { return ScanDurationWholeSecondsFractionDesignator(str,
s, r); }
1043 ParsedISO8601Duration)template <typename Char> int32_t ScanDurationSecondsPart
(base::Vector<Char> str, int32_t s, ParsedISO8601Duration
* r) { return ScanDurationWholeSecondsFractionDesignator(str,
s, r); }
1044
1045// DurationMinutesPart :
1046// DurationWholeMinutes DurationMinutesFractionopt MinutesDesignator
1047// [DurationSecondsPart]
1048template <typename Char>
1049int32_t ScanDurationMinutesPart(base::Vector<Char> str, int32_t s,
1050 ParsedISO8601Duration* r) {
1051 int32_t cur = s + ScanDurationWholeMinutesFractionDesignator(str, s, r);
1052 if (cur == s) return 0;
1053 return cur + ScanDurationSecondsPart(str, cur, r) - s;
1054}
1055
1056// DurationHoursPart :
1057// DurationWholeHours DurationHoursFractionopt HoursDesignator
1058// DurationMinutesPart
1059//
1060// DurationWholeHours DurationHoursFractionopt HoursDesignator
1061// [DurationSecondsPart]
1062template <typename Char>
1063int32_t ScanDurationHoursPart(base::Vector<Char> str, int32_t s,
1064 ParsedISO8601Duration* r) {
1065 int32_t cur = s + ScanDurationWholeHoursFractionDesignator(str, s, r);
1066 if (cur == s) return 0;
1067 int32_t len = ScanDurationMinutesPart(str, cur, r);
1068 if (len > 0) return cur + len - s;
1069 return cur + ScanDurationSecondsPart(str, cur, r) - s;
1070}
1071
1072// DurationTime :
1073// DurationTimeDesignator DurationHoursPart
1074// DurationTimeDesignator DurationMinutesPart
1075// DurationTimeDesignator DurationSecondsPart
1076template <typename Char>
1077int32_t ScanDurationTime(base::Vector<Char> str, int32_t s,
1078 ParsedISO8601Duration* r) {
1079 int32_t cur = s;
1080 if (str.length() < (s + 1)) return 0;
1081 if (AsciiAlphaToLower(str[cur++]) != 't') return 0;
1082 if ((cur += ScanDurationHoursPart(str, cur, r)) - s > 1) return cur - s;
1083 if ((cur += ScanDurationMinutesPart(str, cur, r)) - s > 1) return cur - s;
1084 if ((cur += ScanDurationSecondsPart(str, cur, r)) - s > 1) return cur - s;
1085 return 0;
1086}
1087
1088#define DURATION_AND_DESIGNATOR(Name, name, d)template <typename Char> int32_t ScanDurationNameDesignator
(base::Vector<Char> str, int32_t s, ParsedISO8601Duration
* r) { int32_t cur = s; int64_t name; if ((cur += ScanDurationName
(str, cur, &name)) == s) return 0; if (str.length() < (
cur + 1) || AsciiAlphaToLower(str[cur++]) != (d)) { return 0;
} r->name = name; return cur - s; }
\
1089 template <typename Char> \
1090 int32_t ScanDuration##Name##Designator(base::Vector<Char> str, int32_t s, \
1091 ParsedISO8601Duration* r) { \
1092 int32_t cur = s; \
1093 int64_t name; \
1094 if ((cur += ScanDuration##Name(str, cur, &name)) == s) return 0; \
1095 if (str.length() < (cur + 1) || AsciiAlphaToLower(str[cur++]) != (d)) { \
1096 return 0; \
1097 } \
1098 r->name = name; \
1099 return cur - s; \
1100 }
1101
1102DURATION_AND_DESIGNATOR(Days, days, 'd')template <typename Char> int32_t ScanDurationDaysDesignator
(base::Vector<Char> str, int32_t s, ParsedISO8601Duration
* r) { int32_t cur = s; int64_t days; if ((cur += ScanDurationDays
(str, cur, &days)) == s) return 0; if (str.length() < (
cur + 1) || AsciiAlphaToLower(str[cur++]) != ('d')) { return 0
; } r->days = days; return cur - s; }
1103DURATION_AND_DESIGNATOR(Weeks, weeks, 'w')template <typename Char> int32_t ScanDurationWeeksDesignator
(base::Vector<Char> str, int32_t s, ParsedISO8601Duration
* r) { int32_t cur = s; int64_t weeks; if ((cur += ScanDurationWeeks
(str, cur, &weeks)) == s) return 0; if (str.length() <
(cur + 1) || AsciiAlphaToLower(str[cur++]) != ('w')) { return
0; } r->weeks = weeks; return cur - s; }
1104DURATION_AND_DESIGNATOR(Months, months, 'm')template <typename Char> int32_t ScanDurationMonthsDesignator
(base::Vector<Char> str, int32_t s, ParsedISO8601Duration
* r) { int32_t cur = s; int64_t months; if ((cur += ScanDurationMonths
(str, cur, &months)) == s) return 0; if (str.length() <
(cur + 1) || AsciiAlphaToLower(str[cur++]) != ('m')) { return
0; } r->months = months; return cur - s; }
1105DURATION_AND_DESIGNATOR(Years, years, 'y')template <typename Char> int32_t ScanDurationYearsDesignator
(base::Vector<Char> str, int32_t s, ParsedISO8601Duration
* r) { int32_t cur = s; int64_t years; if ((cur += ScanDurationYears
(str, cur, &years)) == s) return 0; if (str.length() <
(cur + 1) || AsciiAlphaToLower(str[cur++]) != ('y')) { return
0; } r->years = years; return cur - s; }
1106
1107// DurationDaysPart : DurationDays DaysDesignator
1108SCAN_FORWARD(DurationDaysPart, DurationDaysDesignator, ParsedISO8601Duration)template <typename Char> int32_t ScanDurationDaysPart(base
::Vector<Char> str, int32_t s, ParsedISO8601Duration* r
) { return ScanDurationDaysDesignator(str, s, r); }
1109
1110// DurationWeeksPart : DurationWeeks WeeksDesignator [DurationDaysPart]
1111template <typename Char>
1112int32_t ScanDurationWeeksPart(base::Vector<Char> str, int32_t s,
1113 ParsedISO8601Duration* r) {
1114 int32_t cur = s;
1115 if ((cur += ScanDurationWeeksDesignator(str, cur, r)) == s) return 0;
1116 return cur + ScanDurationDaysPart(str, cur, r) - s;
1117}
1118
1119// DurationMonthsPart :
1120// DurationMonths MonthsDesignator DurationWeeksPart
1121// DurationMonths MonthsDesignator [DurationDaysPart]
1122template <typename Char>
1123int32_t ScanDurationMonthsPart(base::Vector<Char> str, int32_t s,
1124 ParsedISO8601Duration* r) {
1125 int32_t cur = s;
1126 int32_t len;
1127 if ((cur += ScanDurationMonthsDesignator(str, cur, r)) == s) return 0;
1128 if ((len = ScanDurationWeeksPart(str, cur, r)) > 0) return cur + len - s;
1129 return cur + ScanDurationDaysPart(str, cur, r) - s;
1130}
1131
1132// DurationYearsPart :
1133// DurationYears YearsDesignator DurationMonthsPart
1134// DurationYears YearsDesignator DurationWeeksPart
1135// DurationYears YearsDesignator [DurationDaysPart]
1136template <typename Char>
1137int32_t ScanDurationYearsPart(base::Vector<Char> str, int32_t s,
1138 ParsedISO8601Duration* r) {
1139 int32_t cur = s;
1140 int32_t len;
1141 if ((cur += ScanDurationYearsDesignator(str, cur, r)) == s) return 0;
1142 if ((len = ScanDurationMonthsPart(str, cur, r)) > 0) return cur + len - s;
1143 if ((len = ScanDurationWeeksPart(str, cur, r)) > 0) return cur + len - s;
1144 return cur + ScanDurationDaysPart(str, cur, r) - s;
1145}
1146
1147// DurationDate :
1148// DurationYearsPart [DurationTime]
1149// DurationMonthsPart [DurationTime]
1150// DurationWeeksPart [DurationTime]
1151// DurationDaysPart [DurationTime]
1152template <typename Char>
1153int32_t ScanDurationDate(base::Vector<Char> str, int32_t s,
1154 ParsedISO8601Duration* r) {
1155 int32_t cur = s;
1156 do {
1157 if ((cur += ScanDurationYearsPart(str, cur, r)) > s) break;
1158 if ((cur += ScanDurationMonthsPart(str, cur, r)) > s) break;
1159 if ((cur += ScanDurationWeeksPart(str, cur, r)) > s) break;
1160 if ((cur += ScanDurationDaysPart(str, cur, r)) > s) break;
1161 return 0;
1162 } while (false);
1163 return cur + ScanDurationTime(str, cur, r) - s;
1164}
1165
1166// Duration :
1167// Signopt DurationDesignator DurationDate
1168// Signopt DurationDesignator DurationTime
1169template <typename Char>
1170int32_t ScanDuration(base::Vector<Char> str, int32_t s,
1171 ParsedISO8601Duration* r) {
1172 if (str.length() < (s + 2)) return 0;
1173 int32_t cur = s;
1174 int32_t sign =
1175 (IsSign(str[cur]) && CanonicalSign(str[cur++]) == '-') ? -1 : 1;
1176 if (AsciiAlphaToLower(str[cur++]) != 'p') return 0;
1177 int32_t len = ScanDurationDate(str, cur, r);
1178 if (len == 0) len = ScanDurationTime(str, cur, r);
1179 if (len == 0) return 0;
1180 r->sign = sign;
1181 return cur + len - s;
1182}
1183SCAN_FORWARD(TemporalDurationString, Duration, ParsedISO8601Duration)template <typename Char> int32_t ScanTemporalDurationString
(base::Vector<Char> str, int32_t s, ParsedISO8601Duration
* r) { return ScanDuration(str, s, r); }
1184
1185SATISIFY(TemporalDurationString, ParsedISO8601Duration)template <typename Char> bool SatisfyTemporalDurationString
(base::Vector<Char> str, ParsedISO8601Duration* r) { ParsedISO8601Duration
ret; int32_t len = ScanTemporalDurationString(str, 0, &ret
); if ((len > 0) && (len == str.length())) { *r = ret
; return true; } return false; }
1186
1187} // namespace
1188
1189#define IMPL_PARSE_METHOD(R, NAME)Maybe<R> TemporalParser::ParseNAME(Isolate* isolate, Handle
<String> iso_string) { bool valid; R parsed; iso_string
= String::Flatten(isolate, iso_string); { DisallowGarbageCollection
no_gc; String::FlatContent str_content = iso_string->GetFlatContent
(no_gc); if (str_content.IsOneByte()) { valid = SatisfyNAME(str_content
.ToOneByteVector(), &parsed); } else { valid = SatisfyNAME
(str_content.ToUC16Vector(), &parsed); } } if (valid) return
Just(parsed); return Nothing<R>(); }
\
1190 Maybe<R> TemporalParser::Parse##NAME(Isolate* isolate, \
1191 Handle<String> iso_string) { \
1192 bool valid; \
1193 R parsed; \
1194 iso_string = String::Flatten(isolate, iso_string); \
1195 { \
1196 DisallowGarbageCollection no_gc; \
1197 String::FlatContent str_content = iso_string->GetFlatContent(no_gc); \
1198 if (str_content.IsOneByte()) { \
1199 valid = Satisfy##NAME(str_content.ToOneByteVector(), &parsed); \
1200 } else { \
1201 valid = Satisfy##NAME(str_content.ToUC16Vector(), &parsed); \
1202 } \
1203 } \
1204 if (valid) return Just(parsed); \
1205 return Nothing<R>(); \
1206 }
1207
1208IMPL_PARSE_METHOD(ParsedISO8601Result, TemporalDateTimeString)Maybe<ParsedISO8601Result> TemporalParser::ParseTemporalDateTimeString
(Isolate* isolate, Handle<String> iso_string) { bool valid
; ParsedISO8601Result parsed; iso_string = String::Flatten(isolate
, iso_string); { DisallowGarbageCollection no_gc; String::FlatContent
str_content = iso_string->GetFlatContent(no_gc); if (str_content
.IsOneByte()) { valid = SatisfyTemporalDateTimeString(str_content
.ToOneByteVector(), &parsed); } else { valid = SatisfyTemporalDateTimeString
(str_content.ToUC16Vector(), &parsed); } } if (valid) return
Just(parsed); return Nothing<ParsedISO8601Result>(); }
1209IMPL_PARSE_METHOD(ParsedISO8601Result, TemporalDateString)Maybe<ParsedISO8601Result> TemporalParser::ParseTemporalDateString
(Isolate* isolate, Handle<String> iso_string) { bool valid
; ParsedISO8601Result parsed; iso_string = String::Flatten(isolate
, iso_string); { DisallowGarbageCollection no_gc; String::FlatContent
str_content = iso_string->GetFlatContent(no_gc); if (str_content
.IsOneByte()) { valid = SatisfyTemporalDateString(str_content
.ToOneByteVector(), &parsed); } else { valid = SatisfyTemporalDateString
(str_content.ToUC16Vector(), &parsed); } } if (valid) return
Just(parsed); return Nothing<ParsedISO8601Result>(); }
1210IMPL_PARSE_METHOD(ParsedISO8601Result, TemporalYearMonthString)Maybe<ParsedISO8601Result> TemporalParser::ParseTemporalYearMonthString
(Isolate* isolate, Handle<String> iso_string) { bool valid
; ParsedISO8601Result parsed; iso_string = String::Flatten(isolate
, iso_string); { DisallowGarbageCollection no_gc; String::FlatContent
str_content = iso_string->GetFlatContent(no_gc); if (str_content
.IsOneByte()) { valid = SatisfyTemporalYearMonthString(str_content
.ToOneByteVector(), &parsed); } else { valid = SatisfyTemporalYearMonthString
(str_content.ToUC16Vector(), &parsed); } } if (valid) return
Just(parsed); return Nothing<ParsedISO8601Result>(); }
1211IMPL_PARSE_METHOD(ParsedISO8601Result, TemporalMonthDayString)Maybe<ParsedISO8601Result> TemporalParser::ParseTemporalMonthDayString
(Isolate* isolate, Handle<String> iso_string) { bool valid
; ParsedISO8601Result parsed; iso_string = String::Flatten(isolate
, iso_string); { DisallowGarbageCollection no_gc; String::FlatContent
str_content = iso_string->GetFlatContent(no_gc); if (str_content
.IsOneByte()) { valid = SatisfyTemporalMonthDayString(str_content
.ToOneByteVector(), &parsed); } else { valid = SatisfyTemporalMonthDayString
(str_content.ToUC16Vector(), &parsed); } } if (valid) return
Just(parsed); return Nothing<ParsedISO8601Result>(); }
1212IMPL_PARSE_METHOD(ParsedISO8601Result, TemporalTimeString)Maybe<ParsedISO8601Result> TemporalParser::ParseTemporalTimeString
(Isolate* isolate, Handle<String> iso_string) { bool valid
; ParsedISO8601Result parsed; iso_string = String::Flatten(isolate
, iso_string); { DisallowGarbageCollection no_gc; String::FlatContent
str_content = iso_string->GetFlatContent(no_gc); if (str_content
.IsOneByte()) { valid = SatisfyTemporalTimeString(str_content
.ToOneByteVector(), &parsed); } else { valid = SatisfyTemporalTimeString
(str_content.ToUC16Vector(), &parsed); } } if (valid) return
Just(parsed); return Nothing<ParsedISO8601Result>(); }
1213IMPL_PARSE_METHOD(ParsedISO8601Result, TemporalInstantString)Maybe<ParsedISO8601Result> TemporalParser::ParseTemporalInstantString
(Isolate* isolate, Handle<String> iso_string) { bool valid
; ParsedISO8601Result parsed; iso_string = String::Flatten(isolate
, iso_string); { DisallowGarbageCollection no_gc; String::FlatContent
str_content = iso_string->GetFlatContent(no_gc); if (str_content
.IsOneByte()) { valid = SatisfyTemporalInstantString(str_content
.ToOneByteVector(), &parsed); } else { valid = SatisfyTemporalInstantString
(str_content.ToUC16Vector(), &parsed); } } if (valid) return
Just(parsed); return Nothing<ParsedISO8601Result>(); }
1214IMPL_PARSE_METHOD(ParsedISO8601Result, TemporalZonedDateTimeString)Maybe<ParsedISO8601Result> TemporalParser::ParseTemporalZonedDateTimeString
(Isolate* isolate, Handle<String> iso_string) { bool valid
; ParsedISO8601Result parsed; iso_string = String::Flatten(isolate
, iso_string); { DisallowGarbageCollection no_gc; String::FlatContent
str_content = iso_string->GetFlatContent(no_gc); if (str_content
.IsOneByte()) { valid = SatisfyTemporalZonedDateTimeString(str_content
.ToOneByteVector(), &parsed); } else { valid = SatisfyTemporalZonedDateTimeString
(str_content.ToUC16Vector(), &parsed); } } if (valid) return
Just(parsed); return Nothing<ParsedISO8601Result>(); }
1215IMPL_PARSE_METHOD(ParsedISO8601Result, TemporalTimeZoneString)Maybe<ParsedISO8601Result> TemporalParser::ParseTemporalTimeZoneString
(Isolate* isolate, Handle<String> iso_string) { bool valid
; ParsedISO8601Result parsed; iso_string = String::Flatten(isolate
, iso_string); { DisallowGarbageCollection no_gc; String::FlatContent
str_content = iso_string->GetFlatContent(no_gc); if (str_content
.IsOneByte()) { valid = SatisfyTemporalTimeZoneString(str_content
.ToOneByteVector(), &parsed); } else { valid = SatisfyTemporalTimeZoneString
(str_content.ToUC16Vector(), &parsed); } } if (valid) return
Just(parsed); return Nothing<ParsedISO8601Result>(); }
1216IMPL_PARSE_METHOD(ParsedISO8601Result, TemporalRelativeToString)Maybe<ParsedISO8601Result> TemporalParser::ParseTemporalRelativeToString
(Isolate* isolate, Handle<String> iso_string) { bool valid
; ParsedISO8601Result parsed; iso_string = String::Flatten(isolate
, iso_string); { DisallowGarbageCollection no_gc; String::FlatContent
str_content = iso_string->GetFlatContent(no_gc); if (str_content
.IsOneByte()) { valid = SatisfyTemporalRelativeToString(str_content
.ToOneByteVector(), &parsed); } else { valid = SatisfyTemporalRelativeToString
(str_content.ToUC16Vector(), &parsed); } } if (valid) return
Just(parsed); return Nothing<ParsedISO8601Result>(); }
1217IMPL_PARSE_METHOD(ParsedISO8601Result, TemporalCalendarString)Maybe<ParsedISO8601Result> TemporalParser::ParseTemporalCalendarString
(Isolate* isolate, Handle<String> iso_string) { bool valid
; ParsedISO8601Result parsed; iso_string = String::Flatten(isolate
, iso_string); { DisallowGarbageCollection no_gc; String::FlatContent
str_content = iso_string->GetFlatContent(no_gc); if (str_content
.IsOneByte()) { valid = SatisfyTemporalCalendarString(str_content
.ToOneByteVector(), &parsed); } else { valid = SatisfyTemporalCalendarString
(str_content.ToUC16Vector(), &parsed); } } if (valid) return
Just(parsed); return Nothing<ParsedISO8601Result>(); }
1218IMPL_PARSE_METHOD(ParsedISO8601Result, TimeZoneNumericUTCOffset)Maybe<ParsedISO8601Result> TemporalParser::ParseTimeZoneNumericUTCOffset
(Isolate* isolate, Handle<String> iso_string) { bool valid
; ParsedISO8601Result parsed; iso_string = String::Flatten(isolate
, iso_string); { DisallowGarbageCollection no_gc; String::FlatContent
str_content = iso_string->GetFlatContent(no_gc); if (str_content
.IsOneByte()) { valid = SatisfyTimeZoneNumericUTCOffset(str_content
.ToOneByteVector(), &parsed); } else { valid = SatisfyTimeZoneNumericUTCOffset
(str_content.ToUC16Vector(), &parsed); } } if (valid) return
Just(parsed); return Nothing<ParsedISO8601Result>(); }
1219IMPL_PARSE_METHOD(ParsedISO8601Duration, TemporalDurationString)Maybe<ParsedISO8601Duration> TemporalParser::ParseTemporalDurationString
(Isolate* isolate, Handle<String> iso_string) { bool valid
; ParsedISO8601Duration parsed; iso_string = String::Flatten(
isolate, iso_string); { DisallowGarbageCollection no_gc; String
::FlatContent str_content = iso_string->GetFlatContent(no_gc
); if (str_content.IsOneByte()) { valid = SatisfyTemporalDurationString
(str_content.ToOneByteVector(), &parsed); } else { valid =
SatisfyTemporalDurationString(str_content.ToUC16Vector(), &
parsed); } } if (valid) return Just(parsed); return Nothing<
ParsedISO8601Duration>(); }
1220
1221} // namespace internal
1222} // namespace v8