File: | out/../deps/v8/src/temporal/temporal-parser.cc |
Warning: | line 178, column 8 Assigned value is garbage or undefined |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
11 | namespace v8 { | |||
12 | namespace internal { | |||
13 | ||||
14 | namespace { | |||
15 | ||||
16 | // Temporal #prod-NonzeroDigit | |||
17 | inline constexpr bool IsNonZeroDecimalDigit(base::uc32 c) { | |||
18 | return base::IsInRange(c, '1', '9'); | |||
19 | } | |||
20 | ||||
21 | // Temporal #prod-TZLeadingChar | |||
22 | inline constexpr bool IsTZLeadingChar(base::uc32 c) { | |||
23 | return base::IsInRange(AsciiAlphaToLower(c), 'a', 'z') || c == '.' || | |||
24 | c == '_'; | |||
25 | } | |||
26 | ||||
27 | // Temporal #prod-TZChar | |||
28 | inline constexpr bool IsTZChar(base::uc32 c) { | |||
29 | return IsTZLeadingChar(c) || c == '-'; | |||
30 | } | |||
31 | ||||
32 | // Temporal #prod-DecimalSeparator | |||
33 | inline constexpr bool IsDecimalSeparator(base::uc32 c) { | |||
34 | return c == '.' || c == ','; | |||
35 | } | |||
36 | ||||
37 | // Temporal #prod-DateTimeSeparator | |||
38 | inline constexpr bool IsDateTimeSeparator(base::uc32 c) { | |||
39 | return c == ' ' || AsciiAlphaToLower(c) == 't'; | |||
40 | } | |||
41 | ||||
42 | // Temporal #prod-ASCIISign | |||
43 | inline constexpr bool IsAsciiSign(base::uc32 c) { return c == '-' || c == '+'; } | |||
44 | ||||
45 | // Temporal #prod-Sign | |||
46 | inline constexpr bool IsSign(base::uc32 c) { | |||
47 | return c == 0x2212 || IsAsciiSign(c); | |||
48 | } | |||
49 | ||||
50 | inline constexpr base::uc32 CanonicalSign(base::uc32 c) { | |||
51 | return c == 0x2212 ? '-' : c; | |||
52 | } | |||
53 | ||||
54 | inline 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] | |||
84 | template <typename Char> | |||
85 | bool 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 | ||||
91 | template <typename Char> | |||
92 | int32_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 | |||
100 | template <typename Char> | |||
101 | bool 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 | ||||
106 | template <typename Char> | |||
107 | int32_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 | |||
137 | SCAN_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 | |||
140 | SCAN_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 | |||
145 | template <typename Char> | |||
146 | int32_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 | ||||
158 | constexpr int kPowerOfTen[] = {1, 10, 100, 1000, 10000, | |||
159 | 100000, 1000000, 10000000, 100000000}; | |||
160 | ||||
161 | // FractionalPart : Digit{1,9} | |||
162 | template <typename Char> | |||
163 | int32_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; | |||
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 | ||||
174 | template <typename Char> | |||
175 | int32_t ScanFractionalPart(base::Vector<Char> str, int32_t s, int64_t* out) { | |||
176 | int32_t out32; | |||
177 | int32_t len = ScanFractionalPart(str, s, &out32); | |||
178 | *out = out32; | |||
| ||||
179 | return len; | |||
180 | } | |||
181 | ||||
182 | // TimeFraction: FractionalPart | |||
183 | SCAN_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 , . | |||
187 | template <typename Char> | |||
188 | int32_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 , . | |||
197 | template <typename Char> | |||
198 | int32_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 | ||||
205 | template <typename Char> | |||
206 | int32_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] | |||
217 | template <typename Char> | |||
218 | int32_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' | |||
266 | template <typename Char> | |||
267 | int32_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 | |||
275 | template <typename Char> | |||
276 | int32_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 | |||
292 | template <typename Char> | |||
293 | int32_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. | |||
308 | SCAN_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 | |||
315 | template <typename Char> | |||
316 | int32_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 | |||
332 | template <typename Char> | |||
333 | int32_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 | |||
347 | template <typename Char> | |||
348 | int32_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 | |||
371 | SCAN_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 | |||
374 | SCAN_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 | |||
377 | SCAN_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 | |||
381 | SCAN_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 | |||
385 | template <typename Char> | |||
386 | int32_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] | |||
403 | template <typename Char> | |||
404 | int32_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 | |||
460 | template <typename Char> | |||
461 | int32_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 .. | |||
475 | template <typename Char> | |||
476 | int32_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. | |||
495 | template <typename Char> | |||
496 | int32_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 | ||||
512 | template <typename Char> | |||
513 | int32_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 | // | |||
529 | template <typename Char> | |||
530 | int32_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. | |||
579 | template <typename Char> | |||
580 | int32_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 | ||||
597 | template <typename Char> | |||
598 | int32_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 ']' | |||
611 | template <typename Char> | |||
612 | int32_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] | |||
625 | template <typename Char> | |||
626 | int32_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 | |||
636 | template <typename Char> | |||
637 | int32_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. | |||
650 | SCAN_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} | |||
655 | template <typename Char> | |||
656 | int32_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. | |||
670 | template <typename Char> | |||
671 | int32_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 ']' | |||
688 | template <typename Char> | |||
689 | int32_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] | |||
707 | template <typename Char> | |||
708 | int32_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] | |||
719 | template <typename Char> | |||
720 | int32_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 | |||
730 | template <typename Char> | |||
731 | int32_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 | |||
748 | template <typename Char> | |||
749 | int32_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 | |||
776 | template <typename Char> | |||
777 | int32_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] | |||
788 | template <typename Char> | |||
789 | int32_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] | |||
798 | template <typename Char> | |||
799 | int32_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 | ||||
818 | SCAN_FORWARD(TemporalDateString, CalendarDateTime, ParsedISO8601Result)template <typename Char> int32_t ScanTemporalDateString (base::Vector<Char> str, int32_t s, ParsedISO8601Result * r) { return ScanCalendarDateTime(str, s, r); } | |||
819 | SCAN_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] | |||
824 | template <typename Char> | |||
825 | int32_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. | |||
839 | SCAN_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. | |||
847 | SCAN_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. | |||
854 | SCAN_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. | |||
861 | SCAN_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 | |||
869 | SCAN_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 | |||
875 | template <typename Char> | |||
876 | int32_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 | ||||
928 | SATISIFY(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; } | |||
929 | SATISIFY(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; } | |||
930 | SATISIFY(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; } | |||
931 | SATISIFY(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; } | |||
932 | SATISIFY(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; } | |||
933 | SATISIFY(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; } | |||
934 | SATISIFY(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; } | |||
935 | SATISIFY(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; } | |||
936 | SATISIFY_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; } | |||
938 | SATISIFY_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; } | |||
940 | SATISIFY_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; } | |||
942 | SATISIFY(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; } | |||
943 | SATISIFY(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; } | |||
944 | SATISIFY_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 ; } | |||
946 | SATISIFY_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; } | |||
948 | SATISIFY(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; } | |||
949 | SATISIFY(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 | ||||
951 | SATISIFY_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 | ||||
954 | SATISIFY(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 | ||||
956 | template <typename Char> | |||
957 | bool 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 | ||||
970 | SCAN_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); } | |||
971 | ||||
972 | template <typename Char> | |||
973 | int32_t ScanFraction(base::Vector<Char> str, int32_t s, int64_t* out) { | |||
974 | if (str.length() < (s + 2) || !IsDecimalSeparator(str[s])) return 0; | |||
975 | int32_t len = ScanTimeFractionalPart(str, s + 1, out); | |||
976 | return (len == 0) ? 0 : len + 1; | |||
977 | } | |||
978 | ||||
979 | SCAN_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); } | |||
980 | ||||
981 | // Digits : Digit [Digits] | |||
982 | ||||
983 | template <typename Char> | |||
984 | int32_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 | ||||
995 | SCAN_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); } | |||
996 | SCAN_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); } | |||
997 | SCAN_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); } | |||
998 | SCAN_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 | |||
1001 | SCAN_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 | |||
1004 | SCAN_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 | |||
1007 | SCAN_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 | |||
1010 | SCAN_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); } | |||
1011 | ||||
1012 | // DurationMinutesFraction : TimeFraction | |||
1013 | SCAN_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 | |||
1016 | SCAN_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 | ||||
1036 | DURATION_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; } | |||
1037 | DURATION_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; } | |||
1038 | DURATION_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; } | |||
| ||||
1039 | ||||
1040 | // DurationSecondsPart : | |||
1041 | // DurationWholeSeconds DurationSecondsFractionopt SecondsDesignator | |||
1042 | SCAN_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] | |||
1048 | template <typename Char> | |||
1049 | int32_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] | |||
1062 | template <typename Char> | |||
1063 | int32_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 | |||
1076 | template <typename Char> | |||
1077 | int32_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 | ||||
1102 | DURATION_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; } | |||
1103 | DURATION_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; } | |||
1104 | DURATION_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; } | |||
1105 | DURATION_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 | |||
1108 | SCAN_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] | |||
1111 | template <typename Char> | |||
1112 | int32_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] | |||
1122 | template <typename Char> | |||
1123 | int32_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] | |||
1136 | template <typename Char> | |||
1137 | int32_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] | |||
1152 | template <typename Char> | |||
1153 | int32_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 | |||
1169 | template <typename Char> | |||
1170 | int32_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 | } | |||
1183 | SCAN_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 | ||||
1185 | SATISIFY(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 | ||||
1208 | IMPL_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>(); } | |||
1209 | IMPL_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>(); } | |||
1210 | IMPL_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>(); } | |||
1211 | IMPL_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>(); } | |||
1212 | IMPL_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>(); } | |||
1213 | IMPL_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>(); } | |||
1214 | IMPL_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>(); } | |||
1215 | IMPL_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>(); } | |||
1216 | IMPL_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>(); } | |||
1217 | IMPL_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>(); } | |||
1218 | IMPL_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>(); } | |||
1219 | IMPL_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 |