diff options
Diffstat (limited to '')
-rw-r--r-- | src/fmtlib/fmt/chrono.h | 209 |
1 files changed, 75 insertions, 134 deletions
diff --git a/src/fmtlib/fmt/chrono.h b/src/fmtlib/fmt/chrono.h index 55e8a50..ff3e144 100644 --- a/src/fmtlib/fmt/chrono.h +++ b/src/fmtlib/fmt/chrono.h @@ -377,8 +377,8 @@ auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc) unit_t unit; write_codecvt(unit, in, loc); // In UTF-8 is used one to four one-byte code units. - unicode_to_utf8<code_unit, basic_memory_buffer<char, unit_t::max_size * 4>> - u; + auto u = + to_utf8<code_unit, basic_memory_buffer<char, unit_t::max_size * 4>>(); if (!u.convert({unit.buf, to_unsigned(unit.end - unit.buf)})) FMT_THROW(format_error("failed to format time")); return copy_str<char>(u.c_str(), u.c_str() + u.size(), out); @@ -519,7 +519,7 @@ inline std::tm gmtime(std::time_t time) { } #endif }; - dispatcher gt(time); + auto gt = dispatcher(time); // Too big time values may be unsupported. if (!gt.run()) FMT_THROW(format_error("time_t value out of range")); return gt.tm_; @@ -530,50 +530,7 @@ inline std::tm gmtime( return gmtime(std::chrono::system_clock::to_time_t(time_point)); } -FMT_BEGIN_DETAIL_NAMESPACE - -// DEPRECATED! -template <typename Char> -FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end, - format_specs<Char>& specs) -> const Char* { - FMT_ASSERT(begin != end, ""); - auto align = align::none; - auto p = begin + code_point_length(begin); - if (end - p <= 0) p = begin; - for (;;) { - switch (to_ascii(*p)) { - case '<': - align = align::left; - break; - case '>': - align = align::right; - break; - case '^': - align = align::center; - break; - } - if (align != align::none) { - if (p != begin) { - auto c = *begin; - if (c == '}') return begin; - if (c == '{') { - throw_format_error("invalid fill character '{'"); - return begin; - } - specs.fill = {begin, to_unsigned(p - begin)}; - begin = p + 1; - } else { - ++begin; - } - break; - } else if (p == begin) { - break; - } - p = begin; - } - specs.align = align; - return begin; -} +namespace detail { // Writes two-digit numbers a, b and c separated by sep to buf. // The method by Pavel Novikov based on @@ -1997,7 +1954,7 @@ struct chrono_formatter { } }; -FMT_END_DETAIL_NAMESPACE +} // namespace detail #if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907 using weekday = std::chrono::weekday; @@ -2047,80 +2004,67 @@ template <typename Char> struct formatter<weekday, Char> { template <typename Rep, typename Period, typename Char> struct formatter<std::chrono::duration<Rep, Period>, Char> { private: - format_specs<Char> specs; - int precision = -1; - using arg_ref_type = detail::arg_ref<Char>; - arg_ref_type width_ref; - arg_ref_type precision_ref; - bool localized = false; - basic_string_view<Char> format_str; - using duration = std::chrono::duration<Rep, Period>; + format_specs<Char> specs_; + detail::arg_ref<Char> width_ref_; + detail::arg_ref<Char> precision_ref_; + bool localized_ = false; + basic_string_view<Char> format_str_; - using iterator = typename basic_format_parse_context<Char>::iterator; - struct parse_range { - iterator begin; - iterator end; - }; - - FMT_CONSTEXPR parse_range do_parse(basic_format_parse_context<Char>& ctx) { - auto begin = ctx.begin(), end = ctx.end(); - if (begin == end || *begin == '}') return {begin, begin}; + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx) + -> decltype(ctx.begin()) { + auto it = ctx.begin(), end = ctx.end(); + if (it == end || *it == '}') return it; - begin = detail::parse_align(begin, end, specs); - if (begin == end) return {begin, begin}; + it = detail::parse_align(it, end, specs_); + if (it == end) return it; - begin = detail::parse_dynamic_spec(begin, end, specs.width, width_ref, ctx); - if (begin == end) return {begin, begin}; + it = detail::parse_dynamic_spec(it, end, specs_.width, width_ref_, ctx); + if (it == end) return it; auto checker = detail::chrono_format_checker(); - if (*begin == '.') { + if (*it == '.') { checker.has_precision_integral = !std::is_floating_point<Rep>::value; - begin = - detail::parse_precision(begin, end, precision, precision_ref, ctx); + it = detail::parse_precision(it, end, specs_.precision, precision_ref_, + ctx); } - if (begin != end && *begin == 'L') { - ++begin; - localized = true; + if (it != end && *it == 'L') { + localized_ = true; + ++it; } - end = detail::parse_chrono_format(begin, end, checker); - return {begin, end}; - } - - public: - FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx) - -> decltype(ctx.begin()) { - auto range = do_parse(ctx); - format_str = basic_string_view<Char>( - &*range.begin, detail::to_unsigned(range.end - range.begin)); - return range.end; + end = detail::parse_chrono_format(it, end, checker); + format_str_ = {it, detail::to_unsigned(end - it)}; + return end; } template <typename FormatContext> - auto format(const duration& d, FormatContext& ctx) const + auto format(std::chrono::duration<Rep, Period> d, FormatContext& ctx) const -> decltype(ctx.out()) { - auto specs_copy = specs; - auto precision_copy = precision; - auto begin = format_str.begin(), end = format_str.end(); + auto specs = specs_; + auto precision = specs.precision; + specs.precision = -1; + auto begin = format_str_.begin(), end = format_str_.end(); // As a possible future optimization, we could avoid extra copying if width // is not specified. - basic_memory_buffer<Char> buf; + auto buf = basic_memory_buffer<Char>(); auto out = std::back_inserter(buf); - detail::handle_dynamic_spec<detail::width_checker>(specs_copy.width, - width_ref, ctx); - detail::handle_dynamic_spec<detail::precision_checker>(precision_copy, - precision_ref, ctx); + detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref_, + ctx); + detail::handle_dynamic_spec<detail::precision_checker>(precision, + precision_ref_, ctx); if (begin == end || *begin == '}') { - out = detail::format_duration_value<Char>(out, d.count(), precision_copy); + out = detail::format_duration_value<Char>(out, d.count(), precision); detail::format_duration_unit<Char, Period>(out); } else { - detail::chrono_formatter<FormatContext, decltype(out), Rep, Period> f( - ctx, out, d); - f.precision = precision_copy; - f.localized = localized; + using chrono_formatter = + detail::chrono_formatter<FormatContext, decltype(out), Rep, Period>; + auto f = chrono_formatter(ctx, out, d); + f.precision = precision; + f.localized = localized_; detail::parse_chrono_format(begin, end, f); } return detail::write( - ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs_copy); + ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs); } }; @@ -2128,21 +2072,23 @@ template <typename Char, typename Duration> struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>, Char> : formatter<std::tm, Char> { FMT_CONSTEXPR formatter() { - this->format_str = detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>{}; + this->format_str_ = detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>{}; } template <typename FormatContext> auto format(std::chrono::time_point<std::chrono::system_clock, Duration> val, FormatContext& ctx) const -> decltype(ctx.out()) { using period = typename Duration::period; - if (period::num != 1 || period::den != 1 || - std::is_floating_point<typename Duration::rep>::value) { + if (detail::const_check( + period::num != 1 || period::den != 1 || + std::is_floating_point<typename Duration::rep>::value)) { const auto epoch = val.time_since_epoch(); auto subsecs = std::chrono::duration_cast<Duration>( epoch - std::chrono::duration_cast<std::chrono::seconds>(epoch)); if (subsecs.count() < 0) { - auto second = std::chrono::seconds(1); + auto second = + std::chrono::duration_cast<Duration>(std::chrono::seconds(1)); if (epoch.count() < ((Duration::min)() + second).count()) FMT_THROW(format_error("duration is too small")); subsecs += second; @@ -2164,7 +2110,7 @@ template <typename Char, typename Duration> struct formatter<std::chrono::local_time<Duration>, Char> : formatter<std::tm, Char> { FMT_CONSTEXPR formatter() { - this->format_str = detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>{}; + this->format_str_ = detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>{}; } template <typename FormatContext> @@ -2207,51 +2153,46 @@ struct formatter<std::chrono::time_point<std::chrono::utc_clock, Duration>, template <typename Char> struct formatter<std::tm, Char> { private: - format_specs<Char> specs; - detail::arg_ref<Char> width_ref; + format_specs<Char> specs_; + detail::arg_ref<Char> width_ref_; protected: - basic_string_view<Char> format_str; - - FMT_CONSTEXPR auto do_parse(basic_format_parse_context<Char>& ctx) - -> decltype(ctx.begin()) { - auto begin = ctx.begin(), end = ctx.end(); - if (begin == end || *begin == '}') return begin; - - begin = detail::parse_align(begin, end, specs); - if (begin == end) return end; - - begin = detail::parse_dynamic_spec(begin, end, specs.width, width_ref, ctx); - if (begin == end) return end; - - end = detail::parse_chrono_format(begin, end, detail::tm_format_checker()); - // Replace default format_str only if the new spec is not empty. - if (end != begin) format_str = {begin, detail::to_unsigned(end - begin)}; - return end; - } + basic_string_view<Char> format_str_; template <typename FormatContext, typename Duration> auto do_format(const std::tm& tm, FormatContext& ctx, const Duration* subsecs) const -> decltype(ctx.out()) { - auto specs_copy = specs; - basic_memory_buffer<Char> buf; + auto specs = specs_; + auto buf = basic_memory_buffer<Char>(); auto out = std::back_inserter(buf); - detail::handle_dynamic_spec<detail::width_checker>(specs_copy.width, - width_ref, ctx); + detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref_, + ctx); - const auto loc_ref = ctx.locale(); + auto loc_ref = ctx.locale(); detail::get_locale loc(static_cast<bool>(loc_ref), loc_ref); auto w = detail::tm_writer<decltype(out), Char, Duration>(loc, out, tm, subsecs); - detail::parse_chrono_format(format_str.begin(), format_str.end(), w); + detail::parse_chrono_format(format_str_.begin(), format_str_.end(), w); return detail::write( - ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs_copy); + ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs); } public: FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx) -> decltype(ctx.begin()) { - return this->do_parse(ctx); + auto it = ctx.begin(), end = ctx.end(); + if (it == end || *it == '}') return it; + + it = detail::parse_align(it, end, specs_); + if (it == end) return it; + + it = detail::parse_dynamic_spec(it, end, specs_.width, width_ref_, ctx); + if (it == end) return it; + + end = detail::parse_chrono_format(it, end, detail::tm_format_checker()); + // Replace the default format_str only if the new spec is not empty. + if (end != it) format_str_ = {it, detail::to_unsigned(end - it)}; + return end; } template <typename FormatContext> |