Skip to content

Commit

Permalink
Update file structure
Browse files Browse the repository at this point in the history
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 `<papilio/format.hpp>`
  • Loading branch information
HenryAWE committed Jun 7, 2024
1 parent 107df57 commit af1dede
Show file tree
Hide file tree
Showing 5 changed files with 362 additions and 344 deletions.
272 changes: 269 additions & 3 deletions include/papilio/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4231,6 +4231,275 @@ class enum_formatter
std_formatter_data m_data{.type = U's'};
};

PAPILIO_EXPORT template <std::integral T, typename CharT>
requires(!std::is_same_v<T, bool> && !char_like<T>)
class formatter<T, CharT>
{
public:
template <typename ParseContext>
auto parse(ParseContext& ctx) -> typename ParseContext::iterator
{
using namespace std::literals;

using parser_t = std_formatter_parser<ParseContext, false>;

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 <typename FormatContext>
auto format(T val, FormatContext& ctx) const -> typename FormatContext::iterator
{
if(m_data.type == U'c')
{
if(std::cmp_greater(val, std::numeric_limits<std::uint32_t>::max()))
throw format_error("integer value out of range");

codepoint_formatter fmt;
fmt.set_data(m_data);
return fmt.format(static_cast<char32_t>(val), ctx);
}
else
{
int_formatter<T, CharT> fmt;
fmt.set_data(m_data);
return fmt.format(val, ctx);
}
}

private:
std_formatter_data m_data;
};

PAPILIO_EXPORT template <std::floating_point T, typename CharT>
class formatter<T, CharT>
{
public:
template <typename ParseContext>
auto parse(ParseContext& ctx) -> typename ParseContext::iterator
{
using namespace std::literals;

using parser_t = std_formatter_parser<ParseContext, false>;

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 <typename FormatContext>
auto format(T val, FormatContext& ctx) const -> typename FormatContext::iterator
{
float_formatter<T, CharT> fmt;
fmt.set_data(m_data);
return fmt.format(val, ctx);
}

private:
std_formatter_data m_data;
};

PAPILIO_EXPORT template <typename CharT>
class formatter<utf::codepoint, CharT>
{
public:
template <typename ParseContext>
auto parse(ParseContext& ctx) -> typename ParseContext::iterator
{
using namespace std::literals;

using parser_t = std_formatter_parser<ParseContext, false>;

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 <typename FormatContext>
auto format(utf::codepoint cp, FormatContext& ctx) const -> typename FormatContext::iterator
{
if(!m_data.contains_type(U'c'))
{
int_formatter<std::uint32_t, CharT> fmt;
fmt.set_data(m_data);
return fmt.format(static_cast<char32_t>(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 <typename CharT>
class formatter<bool, CharT>
{
public:
template <typename ParseContext>
auto parse(ParseContext& ctx) -> typename ParseContext::iterator
{
using namespace std::literals;

using parser_t = std_formatter_parser<ParseContext, false>;

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 <typename FormatContext>
auto format(bool val, FormatContext& ctx) const -> typename FormatContext::iterator
{
if(!m_data.contains_type(U's'))
{
int_formatter<std::uint8_t, CharT> fmt;
fmt.set_data(m_data);
return fmt.format(static_cast<std::uint8_t>(val), ctx);
}
else
{
string_formatter<CharT> 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<CharT> 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<CharT> true_sv(true_str, 4);
static constexpr CharT false_str[] = {'f', 'a', 'l', 's', 'e'};
std::basic_string_view<CharT> false_sv(false_str, 5);

return val ? true_sv : false_sv;
}
else
{
const auto& facet = std::use_facet<std::numpunct<CharT>>(loc);
return val ? facet.truename() : facet.falsename();
}
}
};

PAPILIO_EXPORT template <typename CharT>
class formatter<utf::basic_string_container<CharT>, CharT>
{
public:
using string_container_type = utf::basic_string_container<CharT>;

template <typename ParseContext>
auto parse(ParseContext& ctx) -> typename ParseContext::iterator
{
using namespace std::literals;

using parser_t = std_formatter_parser<ParseContext, true>;

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 <typename FormatContext>
auto format(const string_container_type& str, FormatContext& ctx) const -> typename FormatContext::iterator
{
string_formatter<CharT> fmt;
fmt.set_data(m_data);
return fmt.format(str, ctx);
}

private:
std_formatter_data m_data;
};

PAPILIO_EXPORT template <typename CharT>
class formatter<const void*, CharT>
{
public:
template <typename ParseContext>
auto parse(ParseContext& ctx) -> typename ParseContext::iterator
{
using namespace std::literals;

using parser_t = std_formatter_parser<ParseContext, true>;

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 <typename FormatContext>
auto format(const void* p, FormatContext& ctx) const -> typename FormatContext::iterator
{
int_formatter<std::uintptr_t, CharT> fmt;
fmt.set_data(m_data);
return fmt.format(reinterpret_cast<std::uintptr_t>(p), ctx);
}

private:
std_formatter_data m_data{.type = U'x', .alternate_form = true};
};

template <typename T, typename CharT>
requires std::is_enum_v<T>
class formatter<T, CharT> : public enum_formatter<T, CharT>
{};

namespace detail
{
template <typename CharT, typename OutputIt, typename Context>
Expand All @@ -4253,9 +4522,6 @@ namespace detail
}
} // namespace detail

PAPILIO_EXPORT template <typename OutputIt>
struct format_to_n_result;

PAPILIO_EXPORT template <typename OutputIt>
OutputIt vformat_to(
OutputIt out,
Expand Down
73 changes: 69 additions & 4 deletions include/papilio/format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,12 +430,77 @@ std::wstring format(const std::locale& loc, wformat_string<Args...> fmt, Args&&.
loc, fmt.get(), PAPILIO_NS make_wformat_args(std::forward<Args>(args)...)
);
}
} // namespace papilio

#include "format/fundamental.inl"
#include "format/tuple.inl"
#include "format/misc.inl"
// ^^^ format APIs ^^^ / vvv formatters vvv

PAPILIO_EXPORT template <typename R, typename CharT>
class formatter<joiner<R, CharT>, CharT>
{
public:
formatter() = default;
formatter(const formatter&) = default;

formatter& operator=(const formatter&) = default;

using joiner_t = joiner<R, CharT>;
using range_type = typename joiner_t::range_type;
using value_type = std::ranges::range_value_t<range_type>;

template <typename ParseContext, typename FormatContext>
requires formattable_with<value_type, FormatContext>
auto format(const joiner_t& j, ParseContext& parse_ctx, FormatContext& fmt_ctx) const
{
using formatter_t = typename FormatContext::template formatter_type<value_type>;

if constexpr(formatter_traits<formatter_t>::template parsable<FormatContext>())
{
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 <typename FormatContext>
static void append_sep(FormatContext& fmt_ctx, const joiner_t& j)
{
using context_t = format_context_traits<FormatContext>;
context_t::append(fmt_ctx, j.separator());
}
};
} // namespace papilio

#include "detail/suffix.hpp"

#include "formatter/tuple.hpp"
#include "formatter/misc.hpp"

#endif

Loading

0 comments on commit af1dede

Please sign in to comment.