diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index cf1b928b..ff3e1445 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -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_; @@ -2005,55 +2005,40 @@ template struct formatter, Char> { private: format_specs specs_; - using arg_ref_type = detail::arg_ref; - arg_ref_type width_ref_; - arg_ref_type precision_ref_; + detail::arg_ref width_ref_; + detail::arg_ref precision_ref_; bool localized_ = false; basic_string_view format_str_; - using duration = std::chrono::duration; - - struct parse_range { - const Char* begin; - const Char* end; - }; - - FMT_CONSTEXPR parse_range do_parse(basic_format_parse_context& ctx) { - auto begin = ctx.begin(), end = ctx.end(); - if (begin == end || *begin == '}') return {begin, begin}; - - begin = detail::parse_align(begin, end, specs_); - if (begin == end) return {begin, begin}; - - begin = - detail::parse_dynamic_spec(begin, end, specs_.width, width_ref_, ctx); - if (begin == end) return {begin, begin}; - - auto checker = detail::chrono_format_checker(); - if (*begin == '.') { - checker.has_precision_integral = !std::is_floating_point::value; - begin = detail::parse_precision(begin, end, specs_.precision, - precision_ref_, ctx); - } - if (begin != end && *begin == 'L') { - ++begin; - localized_ = true; - } - end = detail::parse_chrono_format(begin, end, checker); - return {begin, end}; - } - public: FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) -> decltype(ctx.begin()) { - auto range = do_parse(ctx); - format_str_ = basic_string_view( - &*range.begin, detail::to_unsigned(range.end - range.begin)); - return range.end; + 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; + + auto checker = detail::chrono_format_checker(); + if (*it == '.') { + checker.has_precision_integral = !std::is_floating_point::value; + it = detail::parse_precision(it, end, specs_.precision, precision_ref_, + ctx); + } + if (it != end && *it == 'L') { + localized_ = true; + ++it; + } + end = detail::parse_chrono_format(it, end, checker); + format_str_ = {it, detail::to_unsigned(end - it)}; + return end; } template - auto format(const duration& d, FormatContext& ctx) const + auto format(std::chrono::duration d, FormatContext& ctx) const -> decltype(ctx.out()) { auto specs = specs_; auto precision = specs.precision; @@ -2087,7 +2072,7 @@ template struct formatter, Char> : formatter { FMT_CONSTEXPR formatter() { - this->format_str = detail::string_literal{}; + this->format_str_ = detail::string_literal{}; } template @@ -2125,7 +2110,7 @@ template struct formatter, Char> : formatter { FMT_CONSTEXPR formatter() { - this->format_str = detail::string_literal{}; + this->format_str_ = detail::string_literal{}; } template @@ -2168,51 +2153,46 @@ struct formatter, template struct formatter { private: - format_specs specs; - detail::arg_ref width_ref; + format_specs specs_; + detail::arg_ref width_ref_; protected: - basic_string_view format_str; - - FMT_CONSTEXPR auto do_parse(basic_format_parse_context& 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 format_str_; template auto do_format(const std::tm& tm, FormatContext& ctx, const Duration* subsecs) const -> decltype(ctx.out()) { - auto specs_copy = specs; - basic_memory_buffer buf; + auto specs = specs_; + auto buf = basic_memory_buffer(); auto out = std::back_inserter(buf); - detail::handle_dynamic_spec(specs_copy.width, - width_ref, ctx); + detail::handle_dynamic_spec(specs.width, width_ref_, + ctx); - const auto loc_ref = ctx.locale(); + auto loc_ref = ctx.locale(); detail::get_locale loc(static_cast(loc_ref), loc_ref); auto w = detail::tm_writer(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(buf.data(), buf.size()), specs_copy); + ctx.out(), basic_string_view(buf.data(), buf.size()), specs); } public: FMT_CONSTEXPR auto parse(basic_format_parse_context& 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 diff --git a/include/fmt/std.h b/include/fmt/std.h index b9e57b88..4c57b96b 100644 --- a/include/fmt/std.h +++ b/include/fmt/std.h @@ -88,8 +88,7 @@ inline void write_escaped_path( } // namespace detail FMT_EXPORT -template -struct formatter { +template struct formatter { private: format_specs specs_; detail::arg_ref width_ref_; @@ -114,8 +113,9 @@ struct formatter { ctx); auto quoted = basic_memory_buffer(); detail::write_escaped_path(quoted, p); - return detail::write( - ctx.out(), basic_string_view(quoted.data(), quoted.size()), specs); + return detail::write(ctx.out(), + basic_string_view(quoted.data(), quoted.size()), + specs); } }; FMT_END_NAMESPACE