diff --git a/include/fmt/format.h b/include/fmt/format.h index de3a6c6b..a8091cbf 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -955,6 +955,8 @@ class FMT_SO_VISIBILITY("default") format_error : public std::runtime_error { using std::runtime_error::runtime_error; }; +class loc_value; + namespace detail { template struct fixed_string { FMT_CONSTEXPR20 fixed_string(const Char (&s)[N]) { @@ -979,95 +981,6 @@ constexpr auto compile_string_to_view(basic_string_view s) } } // namespace detail -// A generic formatting context with custom output iterator and character -// (code unit) support. Char is the format string code unit type which can be -// different from OutputIt::value_type. -template class generic_context { - private: - OutputIt out_; - basic_format_args args_; - detail::locale_ref loc_; - - public: - using char_type = Char; - using iterator = OutputIt; - using parse_context_type FMT_DEPRECATED = parse_context; - template - using formatter_type FMT_DEPRECATED = formatter; - enum { builtin_types = FMT_BUILTIN_TYPES }; - - constexpr generic_context(OutputIt out, - basic_format_args args, - detail::locale_ref loc = {}) - : out_(out), args_(args), loc_(loc) {} - generic_context(generic_context&&) = default; - generic_context(const generic_context&) = delete; - void operator=(const generic_context&) = delete; - - constexpr auto arg(int id) const -> basic_format_arg { - return args_.get(id); - } - auto arg(basic_string_view name) -> basic_format_arg { - return args_.get(name); - } - FMT_CONSTEXPR auto arg_id(basic_string_view name) -> int { - return args_.get_id(name); - } - - FMT_CONSTEXPR auto out() -> iterator { return out_; } - - void advance_to(iterator it) { - if (!detail::is_back_insert_iterator()) out_ = it; - } - - FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; } -}; - -class loc_value { - private: - basic_format_arg value_; - - public: - template ::value)> - loc_value(T value) : value_(value) {} - - template ::value)> - loc_value(T) {} - - template auto visit(Visitor&& vis) -> decltype(vis(0)) { - return value_.visit(vis); - } -}; - -// A locale facet that formats values in UTF-8. -// It is parameterized on the locale to avoid the heavy include. -template class format_facet : public Locale::facet { - private: - std::string separator_; - std::string grouping_; - std::string decimal_point_; - - protected: - virtual auto do_put(appender out, loc_value val, - const format_specs& specs) const -> bool; - - public: - static FMT_API typename Locale::id id; - - explicit format_facet(Locale& loc); - explicit format_facet(string_view sep = "", - std::initializer_list g = {3}, - std::string decimal_point = ".") - : separator_(sep.data(), sep.size()), - grouping_(g.begin(), g.end()), - decimal_point_(decimal_point) {} - - auto put(appender out, loc_value val, const format_specs& specs) const - -> bool { - return do_put(out, val, specs); - } -}; - FMT_END_EXPORT namespace detail { @@ -2050,8 +1963,8 @@ FMT_API auto write_loc(appender out, loc_value value, const format_specs& specs, locale_ref loc) -> bool; #endif template -inline auto write_loc(OutputIt, loc_value, const format_specs&, locale_ref) - -> bool { +inline auto write_loc(OutputIt, const loc_value&, const format_specs&, + locale_ref) -> bool { return false; } @@ -3767,6 +3680,95 @@ void vformat_to(buffer& buf, basic_string_view fmt, FMT_BEGIN_EXPORT +// A generic formatting context with custom output iterator and character +// (code unit) support. Char is the format string code unit type which can be +// different from OutputIt::value_type. +template class generic_context { + private: + OutputIt out_; + basic_format_args args_; + detail::locale_ref loc_; + + public: + using char_type = Char; + using iterator = OutputIt; + using parse_context_type FMT_DEPRECATED = parse_context; + template + using formatter_type FMT_DEPRECATED = formatter; + enum { builtin_types = FMT_BUILTIN_TYPES }; + + constexpr generic_context(OutputIt out, + basic_format_args args, + detail::locale_ref loc = {}) + : out_(out), args_(args), loc_(loc) {} + generic_context(generic_context&&) = default; + generic_context(const generic_context&) = delete; + void operator=(const generic_context&) = delete; + + constexpr auto arg(int id) const -> basic_format_arg { + return args_.get(id); + } + auto arg(basic_string_view name) -> basic_format_arg { + return args_.get(name); + } + FMT_CONSTEXPR auto arg_id(basic_string_view name) -> int { + return args_.get_id(name); + } + + FMT_CONSTEXPR auto out() -> iterator { return out_; } + + void advance_to(iterator it) { + if (!detail::is_back_insert_iterator()) out_ = it; + } + + FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; } +}; + +class loc_value { + private: + basic_format_arg value_; + + public: + template ::value)> + loc_value(T value) : value_(value) {} + + template ::value)> + loc_value(T) {} + + template auto visit(Visitor&& vis) -> decltype(vis(0)) { + return value_.visit(vis); + } +}; + +// A locale facet that formats values in UTF-8. +// It is parameterized on the locale to avoid the heavy include. +template class format_facet : public Locale::facet { + private: + std::string separator_; + std::string grouping_; + std::string decimal_point_; + + protected: + virtual auto do_put(appender out, loc_value val, + const format_specs& specs) const -> bool; + + public: + static FMT_API typename Locale::id id; + + explicit format_facet(Locale& loc); + explicit format_facet(string_view sep = "", + std::initializer_list g = {3}, + std::string decimal_point = ".") + : separator_(sep.data(), sep.size()), + grouping_(g.begin(), g.end()), + decimal_point_(decimal_point) {} + + auto put(appender out, loc_value val, const format_specs& specs) const + -> bool { + return do_put(out, val, specs); + } +}; + #define FMT_FORMAT_AS(Type, Base) \ template \ struct formatter : formatter { \