From af1dede1812f07b76621533e13a5a0439232a5d6 Mon Sep 17 00:00:00 2001 From: AWE Henry Date: Fri, 7 Jun 2024 16:03:47 +0800 Subject: [PATCH] Update file structure 1. Move the formatters of fundamental types into core module 2. Move some formatters of miscellaneous types into separate files 3. Move the formatter of internal type `papilio::joiner` into `` --- include/papilio/core.hpp | 272 ++++++++++++++++- include/papilio/format.hpp | 73 ++++- include/papilio/format/fundamental.inl | 273 ------------------ .../{format/misc.inl => formatter/misc.hpp} | 75 +---- .../{format/tuple.inl => formatter/tuple.hpp} | 13 +- 5 files changed, 362 insertions(+), 344 deletions(-) delete mode 100644 include/papilio/format/fundamental.inl rename include/papilio/{format/misc.inl => formatter/misc.hpp} (58%) rename include/papilio/{format/tuple.inl => formatter/tuple.hpp} (91%) diff --git a/include/papilio/core.hpp b/include/papilio/core.hpp index 513f4bf..feb25e5 100755 --- a/include/papilio/core.hpp +++ b/include/papilio/core.hpp @@ -4231,6 +4231,275 @@ class enum_formatter std_formatter_data m_data{.type = U's'}; }; +PAPILIO_EXPORT template +requires(!std::is_same_v && !char_like) +class formatter +{ +public: + template + auto parse(ParseContext& ctx) -> typename ParseContext::iterator + { + using namespace std::literals; + + using parser_t = std_formatter_parser; + + parser_t parser; + + typename ParseContext::iterator it{}; + std::tie(m_data, it) = parser.parse(ctx, U"XxBbodc"sv); + + ctx.advance_to(it); + return it; + } + + template + auto format(T val, FormatContext& ctx) const -> typename FormatContext::iterator + { + if(m_data.type == U'c') + { + if(std::cmp_greater(val, std::numeric_limits::max())) + throw format_error("integer value out of range"); + + codepoint_formatter fmt; + fmt.set_data(m_data); + return fmt.format(static_cast(val), ctx); + } + else + { + int_formatter fmt; + fmt.set_data(m_data); + return fmt.format(val, ctx); + } + } + +private: + std_formatter_data m_data; +}; + +PAPILIO_EXPORT template +class formatter +{ +public: + template + auto parse(ParseContext& ctx) -> typename ParseContext::iterator + { + using namespace std::literals; + + using parser_t = std_formatter_parser; + + parser_t parser; + + typename ParseContext::iterator it{}; + std::tie(m_data, it) = parser.parse(ctx, U"fFgGeEaA"sv); + + ctx.advance_to(it); + return it; + } + + template + auto format(T val, FormatContext& ctx) const -> typename FormatContext::iterator + { + float_formatter fmt; + fmt.set_data(m_data); + return fmt.format(val, ctx); + } + +private: + std_formatter_data m_data; +}; + +PAPILIO_EXPORT template +class formatter +{ +public: + template + auto parse(ParseContext& ctx) -> typename ParseContext::iterator + { + using namespace std::literals; + + using parser_t = std_formatter_parser; + + parser_t parser; + + typename ParseContext::iterator it{}; + std::tie(m_data, it) = parser.parse(ctx, U"XxBbodc"sv); + + ctx.advance_to(it); + return it; + } + + template + auto format(utf::codepoint cp, FormatContext& ctx) const -> typename FormatContext::iterator + { + if(!m_data.contains_type(U'c')) + { + int_formatter fmt; + fmt.set_data(m_data); + return fmt.format(static_cast(cp), ctx); + } + else + { + codepoint_formatter fmt; + fmt.set_data(m_data); + return fmt.format(cp, ctx); + } + } + +private: + std_formatter_data m_data; +}; + +PAPILIO_EXPORT template +class formatter +{ +public: + template + auto parse(ParseContext& ctx) -> typename ParseContext::iterator + { + using namespace std::literals; + + using parser_t = std_formatter_parser; + + parser_t parser; + + typename ParseContext::iterator it{}; + std::tie(m_data, it) = parser.parse(ctx, U"sXxBbod"sv); + + ctx.advance_to(it); + return it; + } + + template + auto format(bool val, FormatContext& ctx) const -> typename FormatContext::iterator + { + if(!m_data.contains_type(U's')) + { + int_formatter fmt; + fmt.set_data(m_data); + return fmt.format(static_cast(val), ctx); + } + else + { + string_formatter fmt; + fmt.set_data(m_data); + const auto str = get_str(val, ctx.getloc_ref()); + return fmt.format(str, ctx); + } + } + +private: + std_formatter_data m_data; + + utf::basic_string_container get_str(bool val, locale_ref loc) const + { + if(!m_data.use_locale) [[likely]] + { + static constexpr CharT true_str[] = {'t', 'r', 'u', 'e'}; + std::basic_string_view true_sv(true_str, 4); + static constexpr CharT false_str[] = {'f', 'a', 'l', 's', 'e'}; + std::basic_string_view false_sv(false_str, 5); + + return val ? true_sv : false_sv; + } + else + { + const auto& facet = std::use_facet>(loc); + return val ? facet.truename() : facet.falsename(); + } + } +}; + +PAPILIO_EXPORT template +class formatter, CharT> +{ +public: + using string_container_type = utf::basic_string_container; + + template + auto parse(ParseContext& ctx) -> typename ParseContext::iterator + { + using namespace std::literals; + + using parser_t = std_formatter_parser; + + parser_t parser; + + typename ParseContext::iterator it{}; + std::tie(m_data, it) = parser.parse(ctx, U"s"sv); + + ctx.advance_to(it); + return it; + } + + template + auto format(const string_container_type& str, FormatContext& ctx) const -> typename FormatContext::iterator + { + string_formatter fmt; + fmt.set_data(m_data); + return fmt.format(str, ctx); + } + +private: + std_formatter_data m_data; +}; + +PAPILIO_EXPORT template +class formatter +{ +public: + template + auto parse(ParseContext& ctx) -> typename ParseContext::iterator + { + using namespace std::literals; + + using parser_t = std_formatter_parser; + + parser_t parser; + + typename ParseContext::iterator it{}; + std::tie(m_data, it) = parser.parse(ctx, U"pP"sv); + + if(m_data.use_locale) + throw format_error("invalid format"); + + switch(m_data.type) + { + case U'\0': + case U'p': + m_data.type = 'x'; + break; + + case U'P': + m_data.type = 'X'; + break; + + default: + PAPILIO_UNREACHABLE(); + } + + m_data.alternate_form = true; + + ctx.advance_to(it); + return it; + } + + template + auto format(const void* p, FormatContext& ctx) const -> typename FormatContext::iterator + { + int_formatter fmt; + fmt.set_data(m_data); + return fmt.format(reinterpret_cast(p), ctx); + } + +private: + std_formatter_data m_data{.type = U'x', .alternate_form = true}; +}; + +template +requires std::is_enum_v +class formatter : public enum_formatter +{}; + namespace detail { template @@ -4253,9 +4522,6 @@ namespace detail } } // namespace detail -PAPILIO_EXPORT template -struct format_to_n_result; - PAPILIO_EXPORT template OutputIt vformat_to( OutputIt out, diff --git a/include/papilio/format.hpp b/include/papilio/format.hpp index cb12b2b..189897b 100644 --- a/include/papilio/format.hpp +++ b/include/papilio/format.hpp @@ -430,12 +430,77 @@ std::wstring format(const std::locale& loc, wformat_string fmt, Args&&. loc, fmt.get(), PAPILIO_NS make_wformat_args(std::forward(args)...) ); } -} // namespace papilio -#include "format/fundamental.inl" -#include "format/tuple.inl" -#include "format/misc.inl" +// ^^^ format APIs ^^^ / vvv formatters vvv + +PAPILIO_EXPORT template +class formatter, CharT> +{ +public: + formatter() = default; + formatter(const formatter&) = default; + + formatter& operator=(const formatter&) = default; + + using joiner_t = joiner; + using range_type = typename joiner_t::range_type; + using value_type = std::ranges::range_value_t; + + template + requires formattable_with + auto format(const joiner_t& j, ParseContext& parse_ctx, FormatContext& fmt_ctx) const + { + using formatter_t = typename FormatContext::template formatter_type; + + if constexpr(formatter_traits::template parsable()) + { + formatter_t fmt; + parse_ctx.advance_to(fmt.parse(parse_ctx)); + + bool first = true; + for(auto&& i : j) + { + if(!first) + append_sep(fmt_ctx, j); + first = false; + + fmt_ctx.advance_to( + fmt.format(i, fmt_ctx) + ); + } + } + else + { + bool first = true; + for(auto&& i : j) + { + if(!first) + append_sep(fmt_ctx, j); + first = false; + + fmt_ctx.advance_to( + PAPILIO_NS format_to(fmt_ctx.out(), "{}", i) + ); + } + } + + return fmt_ctx.out(); + } + +private: + template + static void append_sep(FormatContext& fmt_ctx, const joiner_t& j) + { + using context_t = format_context_traits; + context_t::append(fmt_ctx, j.separator()); + } +}; +} // namespace papilio #include "detail/suffix.hpp" +#include "formatter/tuple.hpp" +#include "formatter/misc.hpp" + #endif + diff --git a/include/papilio/format/fundamental.inl b/include/papilio/format/fundamental.inl deleted file mode 100644 index f8cb23b..0000000 --- a/include/papilio/format/fundamental.inl +++ /dev/null @@ -1,273 +0,0 @@ -#include - -namespace papilio -{ -PAPILIO_EXPORT template -requires(!std::is_same_v && !char_like) -class formatter -{ -public: - template - auto parse(ParseContext& ctx) -> typename ParseContext::iterator - { - using namespace std::literals; - - using parser_t = std_formatter_parser; - - parser_t parser; - - typename ParseContext::iterator it{}; - std::tie(m_data, it) = parser.parse(ctx, U"XxBbodc"sv); - - ctx.advance_to(it); - return it; - } - - template - auto format(T val, FormatContext& ctx) const -> typename FormatContext::iterator - { - if(m_data.type == U'c') - { - if(std::cmp_greater(val, std::numeric_limits::max())) - throw format_error("integer value out of range"); - - codepoint_formatter fmt; - fmt.set_data(m_data); - return fmt.format(static_cast(val), ctx); - } - else - { - int_formatter fmt; - fmt.set_data(m_data); - return fmt.format(val, ctx); - } - } - -private: - std_formatter_data m_data; -}; - -PAPILIO_EXPORT template -class formatter -{ -public: - template - auto parse(ParseContext& ctx) -> typename ParseContext::iterator - { - using namespace std::literals; - - using parser_t = std_formatter_parser; - - parser_t parser; - - typename ParseContext::iterator it{}; - std::tie(m_data, it) = parser.parse(ctx, U"fFgGeEaA"sv); - - ctx.advance_to(it); - return it; - } - - template - auto format(T val, FormatContext& ctx) const -> typename FormatContext::iterator - { - float_formatter fmt; - fmt.set_data(m_data); - return fmt.format(val, ctx); - } - -private: - std_formatter_data m_data; -}; - -PAPILIO_EXPORT template -class formatter -{ -public: - template - auto parse(ParseContext& ctx) -> typename ParseContext::iterator - { - using namespace std::literals; - - using parser_t = std_formatter_parser; - - parser_t parser; - - typename ParseContext::iterator it{}; - std::tie(m_data, it) = parser.parse(ctx, U"XxBbodc"sv); - - ctx.advance_to(it); - return it; - } - - template - auto format(utf::codepoint cp, FormatContext& ctx) const -> typename FormatContext::iterator - { - if(!m_data.contains_type(U'c')) - { - int_formatter fmt; - fmt.set_data(m_data); - return fmt.format(static_cast(cp), ctx); - } - else - { - codepoint_formatter fmt; - fmt.set_data(m_data); - return fmt.format(cp, ctx); - } - } - -private: - std_formatter_data m_data; -}; - -PAPILIO_EXPORT template -class formatter -{ -public: - template - auto parse(ParseContext& ctx) -> typename ParseContext::iterator - { - using namespace std::literals; - - using parser_t = std_formatter_parser; - - parser_t parser; - - typename ParseContext::iterator it{}; - std::tie(m_data, it) = parser.parse(ctx, U"sXxBbod"sv); - - ctx.advance_to(it); - return it; - } - - template - auto format(bool val, FormatContext& ctx) const -> typename FormatContext::iterator - { - if(!m_data.contains_type(U's')) - { - int_formatter fmt; - fmt.set_data(m_data); - return fmt.format(static_cast(val), ctx); - } - else - { - string_formatter fmt; - fmt.set_data(m_data); - const auto str = get_str(val, ctx.getloc_ref()); - return fmt.format(str, ctx); - } - } - -private: - std_formatter_data m_data; - - utf::basic_string_container get_str(bool val, locale_ref loc) const - { - if(!m_data.use_locale) [[likely]] - { - static constexpr CharT true_str[] = {'t', 'r', 'u', 'e'}; - std::basic_string_view true_sv(true_str, 4); - static constexpr CharT false_str[] = {'f', 'a', 'l', 's', 'e'}; - std::basic_string_view false_sv(false_str, 5); - - return val ? true_sv : false_sv; - } - else - { - const auto& facet = std::use_facet>(loc); - return val ? facet.truename() : facet.falsename(); - } - } -}; - -PAPILIO_EXPORT template -class formatter, CharT> -{ -public: - using string_container_type = utf::basic_string_container; - - template - auto parse(ParseContext& ctx) -> typename ParseContext::iterator - { - using namespace std::literals; - - using parser_t = std_formatter_parser; - - parser_t parser; - - typename ParseContext::iterator it{}; - std::tie(m_data, it) = parser.parse(ctx, U"s"sv); - - ctx.advance_to(it); - return it; - } - - template - auto format(const string_container_type& str, FormatContext& ctx) const -> typename FormatContext::iterator - { - string_formatter fmt; - fmt.set_data(m_data); - return fmt.format(str, ctx); - } - -private: - std_formatter_data m_data; -}; - -PAPILIO_EXPORT template -class formatter -{ -public: - template - auto parse(ParseContext& ctx) -> typename ParseContext::iterator - { - using namespace std::literals; - - using parser_t = std_formatter_parser; - - parser_t parser; - - typename ParseContext::iterator it{}; - std::tie(m_data, it) = parser.parse(ctx, U"pP"sv); - - if(m_data.use_locale) - throw format_error("invalid format"); - - switch(m_data.type) - { - case U'\0': - case U'p': - m_data.type = 'x'; - break; - - case U'P': - m_data.type = 'X'; - break; - - default: - PAPILIO_UNREACHABLE(); - } - - m_data.alternate_form = true; - - ctx.advance_to(it); - return it; - } - - template - auto format(const void* p, FormatContext& ctx) const -> typename FormatContext::iterator - { - int_formatter fmt; - fmt.set_data(m_data); - return fmt.format(reinterpret_cast(p), ctx); - } - -private: - std_formatter_data m_data{.type = U'x', .alternate_form = true}; -}; - -template -requires std::is_enum_v -class formatter : public enum_formatter -{}; -} // namespace papilio diff --git a/include/papilio/format/misc.inl b/include/papilio/formatter/misc.hpp similarity index 58% rename from include/papilio/format/misc.inl rename to include/papilio/formatter/misc.hpp index a6edc1c..d0030e8 100644 --- a/include/papilio/format/misc.inl +++ b/include/papilio/formatter/misc.hpp @@ -1,74 +1,19 @@ +#ifndef PAPILIO_FORMATTER_MISC_HPP +#define PAPILIO_FORMATTER_MISC_HPP + +#pragma once + #include #include #ifdef PAPILIO_HAS_LIB_STACKTRACE # include #endif -#include "../utility.hpp" +#include "../core.hpp" +#include "../format.hpp" +#include "../detail/prefix.hpp" namespace papilio { -PAPILIO_EXPORT template -class formatter, CharT> -{ -public: - formatter() = default; - formatter(const formatter&) = default; - - formatter& operator=(const formatter&) = default; - - using joiner_t = joiner; - using range_type = typename joiner_t::range_type; - using value_type = std::ranges::range_value_t; - - template - requires formattable_with - auto format(const joiner_t& j, ParseContext& parse_ctx, FormatContext& fmt_ctx) const - { - using formatter_t = typename FormatContext::template formatter_type; - - if constexpr(formatter_traits::template parsable()) - { - formatter_t fmt; - parse_ctx.advance_to(fmt.parse(parse_ctx)); - - bool first = true; - for(auto&& i : j) - { - if(!first) - append_sep(fmt_ctx, j); - first = false; - - fmt_ctx.advance_to( - fmt.format(i, fmt_ctx) - ); - } - } - else - { - bool first = true; - for(auto&& i : j) - { - if(!first) - append_sep(fmt_ctx, j); - first = false; - - fmt_ctx.advance_to( - PAPILIO_NS format_to(fmt_ctx.out(), "{}", i) - ); - } - } - - return fmt_ctx.out(); - } - -private: - template - static void append_sep(FormatContext& fmt_ctx, const joiner_t& j) - { - using context_t = format_context_traits; - context_t::append(fmt_ctx, j.separator()); - } -}; PAPILIO_EXPORT template class formatter @@ -173,3 +118,7 @@ class formatter #endif } // namespace papilio + +#include "../detail/suffix.hpp" + +#endif diff --git a/include/papilio/format/tuple.inl b/include/papilio/formatter/tuple.hpp similarity index 91% rename from include/papilio/format/tuple.inl rename to include/papilio/formatter/tuple.hpp index 30b1ac8..c47ffcb 100644 --- a/include/papilio/format/tuple.inl +++ b/include/papilio/formatter/tuple.hpp @@ -1,5 +1,12 @@ +#ifndef PAPILIO_FORMATTER_TUPLE_HPP +#define PAPILIO_FORMATTER_TUPLE_HPP + +#pragma once + #include -#include "../utility.hpp" +#include "../core.hpp" +#include "../format.hpp" +#include "../detail/prefix.hpp" namespace papilio { @@ -82,3 +89,7 @@ class formatter string_view_type m_closing = PAPILIO_TSTRING_VIEW(CharT, ")"); }; } // namespace papilio + +#include "../detail/suffix.hpp" + +#endif