Skip to content

Commit

Permalink
Update formatter implementations
Browse files Browse the repository at this point in the history
1. Parser for time formatting specification
2. Cleanup
  • Loading branch information
HenryAWE committed Jul 30, 2024
1 parent 492b20f commit c492f0a
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 26 deletions.
67 changes: 50 additions & 17 deletions include/papilio/formatter/chrono.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,45 @@

namespace papilio
{
PAPILIO_EXPORT template <typename CharT>
struct chrono_formatter_data
{
using string_container_type = utf::basic_string_container<CharT>;

simple_formatter_data basic;
string_container_type chrono_spec;
};

template <typename ParseContext>
PAPILIO_EXPORT class chrono_formatter_parser
{
public:
using char_type = typename ParseContext::char_type;
using iterator = typename ParseContext::iterator;

using result_type = chrono_formatter_data<char_type>;
using interpreter_type = basic_interpreter<typename ParseContext::format_context_type>;

static std::pair<result_type, iterator> parse(ParseContext& ctx)
{
result_type result;

simple_formatter_parser<ParseContext, true> basic_parser;
auto [basic_result, it] = basic_parser.parse(ctx);
result.basic = basic_result;

auto spec_end = std::find_if(
it,
ctx.end(),
[](char32_t v)
{ return v == U'}'; }
);
result.chrono_spec.assign(it, spec_end);

return std::make_pair(std::move(result), spec_end);
}
};

template <typename CharT>
class formatter<std::tm, CharT>
{
Expand All @@ -20,50 +59,44 @@ class formatter<std::tm, CharT>
auto parse(ParseContext& ctx)
-> typename ParseContext::iterator
{
simple_formatter_parser<ParseContext> parser;
chrono_formatter_parser<ParseContext> parser;
auto [result, it] = parser.parse(ctx);

m_data = result;
auto end = std::find_if(
it,
ctx.end(),
[](char32_t v)
{ return v == U'}'; }
);

m_fmt.assign(it, end);

return end;
return it;
}

template <typename Context>
auto format(const std::tm& val, Context& ctx) const
-> typename Context::iterator
{
if(m_fmt.empty())
if(m_data.chrono_spec.empty())
{
CharT buf[24];
default_tm_fmt_impl(val, buf);

string_formatter<CharT> fmt;
fmt.set_data(m_data);
fmt.set_data(m_data.basic);
return fmt.format(std::basic_string_view<CharT>(buf, 24), ctx);
}
else
{
std::basic_stringstream<CharT> ss;
ss.imbue(ctx.getloc());
ss << std::put_time(&val, m_fmt.c_str());
if(m_data.basic.use_locale)
ss.imbue(ctx.getloc());
else
ss.imbue(std::locale::classic());
ss << std::put_time(&val, m_data.chrono_spec.c_str());

string_formatter<CharT> fmt;
fmt.set_data(m_data);
fmt.set_data(m_data.basic);
return fmt.format(std::move(ss).str(), ctx);
}
}

private:
simple_formatter_data m_data;
utf::basic_string_container<CharT> m_fmt;
chrono_formatter_data<CharT> m_data;

// Simulating `asctime()` but without the trailing newline
static void default_tm_fmt_impl(const std::tm& val, std::span<CharT, 24> buf)
Expand Down
1 change: 0 additions & 1 deletion include/papilio/formatter/misc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

namespace papilio
{

PAPILIO_EXPORT template <typename CharT>
class formatter<std::thread::id, CharT>
{
Expand Down
62 changes: 54 additions & 8 deletions include/papilio/formatter/tuple.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,50 @@

namespace papilio
{
template <tuple_like Tuple, typename CharT>
class formatter<Tuple, CharT>
namespace detail
{
template <typename CharT>
class tuple_fmt_base
{
public:
using string_view_type = std::basic_string_view<CharT>;

protected:
// ", "
static string_view_type default_sep() noexcept
{
static constexpr CharT str[2] = {',', ' '};
return string_view_type(str, 2);
}

// "("
static string_view_type default_opening() noexcept
{
static constexpr CharT ch = '(';
return string_view_type(&ch, 1);
}

// ")"
static string_view_type default_closing() noexcept
{
static constexpr CharT ch = ')';
return string_view_type(&ch, 1);
}

// ": "
static string_view_type pair_sep() noexcept
{
static constexpr CharT str[2] = {':', ' '};
return string_view_type(str, 2);
}
};
} // namespace detail

PAPILIO_EXPORT template <tuple_like Tuple, typename CharT>
class formatter<Tuple, CharT> : public detail::tuple_fmt_base<CharT>
{
using my_base = detail::tuple_fmt_base<CharT>;

public:
using string_view_type = std::basic_string_view<CharT>;

Expand Down Expand Up @@ -40,14 +81,14 @@ class formatter<Tuple, CharT>
{ // Pair-like only
if(type == U'm')
{
set_separator(PAPILIO_TSTRING_VIEW(CharT, ": "));
set_brackets(string_view_type(), string_view_type());
set_separator(my_base::pair_sep());
clear_brackets();
++it;
}
}
if(type == U'n')
{
set_brackets(string_view_type(), string_view_type());
clear_brackets();
++it;
}

Expand Down Expand Up @@ -84,9 +125,14 @@ class formatter<Tuple, CharT>
}

private:
string_view_type m_sep = PAPILIO_TSTRING_VIEW(CharT, ", ");
string_view_type m_opening = PAPILIO_TSTRING_VIEW(CharT, "(");
string_view_type m_closing = PAPILIO_TSTRING_VIEW(CharT, ")");
string_view_type m_sep = my_base::default_sep();
string_view_type m_opening = my_base::default_opening();
string_view_type m_closing = my_base::default_closing();

void clear_brackets() noexcept
{
set_brackets(string_view_type(), string_view_type());
}
};
} // namespace papilio

Expand Down

0 comments on commit c492f0a

Please sign in to comment.