| 14457 | TOML_NODISCARD |
| 14458 | TOML_NEVER_INLINE |
| 14459 | time parse_time(bool part_of_datetime = false) |
| 14460 | { |
| 14461 | return_if_error({}); |
| 14462 | assert_not_eof(); |
| 14463 | TOML_ASSERT_ASSUME(is_decimal_digit(*cp)); |
| 14464 | push_parse_scope("time"sv); |
| 14465 | |
| 14466 | static constexpr size_t max_digits = 64; // far more than necessary but needed to allow fractional |
| 14467 | // millisecond truncation per the spec |
| 14468 | uint32_t digits[max_digits]; |
| 14469 | |
| 14470 | // "HH" |
| 14471 | if (!consume_digit_sequence(digits, 2u)) |
| 14472 | set_error_and_return_default("expected 2-digit hour, saw '"sv, to_sv(cp), "'"sv); |
| 14473 | const auto hour = digits[1] + digits[0] * 10u; |
| 14474 | if (hour > 23u) |
| 14475 | set_error_and_return_default("expected hour between 0 to 59 (inclusive), saw "sv, hour); |
| 14476 | set_error_and_return_if_eof({}); |
| 14477 | |
| 14478 | // ':' |
| 14479 | if (*cp != U':') |
| 14480 | set_error_and_return_default("expected ':', saw '"sv, to_sv(*cp), "'"sv); |
| 14481 | advance_and_return_if_error_or_eof({}); |
| 14482 | |
| 14483 | // "MM" |
| 14484 | if (!consume_digit_sequence(digits, 2u)) |
| 14485 | set_error_and_return_default("expected 2-digit minute, saw '"sv, to_sv(cp), "'"sv); |
| 14486 | const auto minute = digits[1] + digits[0] * 10u; |
| 14487 | if (minute > 59u) |
| 14488 | set_error_and_return_default("expected minute between 0 and 59 (inclusive), saw "sv, minute); |
| 14489 | auto time = toml::time{ hour, minute }; |
| 14490 | |
| 14491 | // ':' |
| 14492 | if constexpr (TOML_LANG_UNRELEASED) // toml/issues/671 (allow omission of seconds) |
| 14493 | { |
| 14494 | if (is_eof() || is_value_terminator(*cp) || (part_of_datetime && is_match(*cp, U'+', U'-', U'Z', U'z'))) |
| 14495 | return time; |
| 14496 | } |
| 14497 | else |
| 14498 | set_error_and_return_if_eof({}); |
| 14499 | if (*cp != U':') |
| 14500 | set_error_and_return_default("expected ':', saw '"sv, to_sv(*cp), "'"sv); |
| 14501 | advance_and_return_if_error_or_eof({}); |
| 14502 | |
| 14503 | // "SS" |
| 14504 | if (!consume_digit_sequence(digits, 2u)) |
| 14505 | set_error_and_return_default("expected 2-digit second, saw '"sv, to_sv(cp), "'"sv); |
| 14506 | const auto second = digits[1] + digits[0] * 10u; |
| 14507 | if (second > 59u) |
| 14508 | set_error_and_return_default("expected second between 0 and 59 (inclusive), saw "sv, second); |
| 14509 | time.second = static_cast<decltype(time.second)>(second); |
| 14510 | |
| 14511 | // '.' (early-exiting is allowed; fractional is optional) |
| 14512 | if (is_eof() || is_value_terminator(*cp) || (part_of_datetime && is_match(*cp, U'+', U'-', U'Z', U'z'))) |
| 14513 | return time; |
| 14514 | if (*cp != U'.') |
| 14515 | set_error_and_return_default("expected '.', saw '"sv, to_sv(*cp), "'"sv); |
| 14516 | advance_and_return_if_error_or_eof({}); |
nothing calls this directly
no outgoing calls
no test coverage detected