Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify and improve chrono formatting #3010

Merged
merged 6 commits into from
Aug 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 13 additions & 28 deletions include/fmt/chrono.h
Original file line number Diff line number Diff line change
Expand Up @@ -2002,32 +2002,18 @@ template <typename Char, typename Duration>
struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
Char> : formatter<std::tm, Char> {
FMT_CONSTEXPR formatter() {
this->do_parse(default_specs,
default_specs + sizeof(default_specs) / sizeof(Char));
}

template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return this->do_parse(ctx.begin(), ctx.end(), true);
basic_string_view<Char> default_specs =
detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>{};
this->do_parse(default_specs.begin(), default_specs.end());
}

template <typename FormatContext>
auto format(std::chrono::time_point<std::chrono::system_clock> val,
FormatContext& ctx) const -> decltype(ctx.out()) {
return formatter<std::tm, Char>::format(localtime(val), ctx);
}

// EDG frontend (Intel, NVHPC compilers) can't determine array length.
static constexpr const Char default_specs[5] = {'%', 'F', ' ', '%', 'T'};
};

#if FMT_CPLUSPLUS < 201703L
template <typename Char, typename Duration>
constexpr const Char
formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
Char>::default_specs[];
#endif

template <typename Char> struct formatter<std::tm, Char> {
private:
enum class spec {
Expand All @@ -2039,13 +2025,18 @@ template <typename Char> struct formatter<std::tm, Char> {
basic_string_view<Char> specs;

protected:
template <typename It>
FMT_CONSTEXPR auto do_parse(It begin, It end, bool with_default = false)
-> It {
template <typename It> FMT_CONSTEXPR auto do_parse(It begin, It end) -> It {
if (begin != end && *begin == ':') ++begin;
end = detail::parse_chrono_format(begin, end, detail::tm_format_checker());
if (!with_default || end != begin)
specs = {begin, detail::to_unsigned(end - begin)};
// Replace default spec only if the new spec is not empty.
if (end != begin) specs = {begin, detail::to_unsigned(end - begin)};
return end;
}

public:
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
-> decltype(ctx.begin()) {
auto end = this->do_parse(ctx.begin(), ctx.end());
// basic_string_view<>::compare isn't constexpr before C++17.
if (specs.size() == 2 && specs[0] == Char('%')) {
if (specs[1] == Char('F'))
Expand All @@ -2056,12 +2047,6 @@ template <typename Char> struct formatter<std::tm, Char> {
return end;
}

public:
template <typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
return this->do_parse(ctx.begin(), ctx.end());
}

template <typename FormatContext>
auto format(const std::tm& tm, FormatContext& ctx) const
-> decltype(ctx.out()) {
Expand Down
12 changes: 12 additions & 0 deletions include/fmt/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,18 @@ FMT_CONSTEXPR inline void abort_fuzzing_if(bool condition) {
#endif
}

template <typename CharT, CharT... C> struct string_literal {
static constexpr CharT value[sizeof...(C)] = {C...};
constexpr operator basic_string_view<CharT>() const {
return {value, sizeof...(C)};
}
};

#if FMT_CPLUSPLUS < 201703L
template <typename CharT, CharT... C>
constexpr CharT string_literal<CharT, C...>::value[sizeof...(C)];
#endif

template <typename Streambuf> class formatbuf : public Streambuf {
private:
using char_type = typename Streambuf::char_type;
Expand Down
10 changes: 0 additions & 10 deletions include/fmt/ranges.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,16 +309,6 @@ OutputIt write_range_entry(OutputIt out, const Arg& v) {
return write<Char>(out, v);
}

template <typename CharT, CharT... C> struct string_literal {
static constexpr CharT value[sizeof...(C)] = {C...};
constexpr operator basic_string_view<CharT>() const {
return {value, sizeof...(C)};
}
};

template <typename CharT, CharT... C>
constexpr CharT string_literal<CharT, C...>::value[sizeof...(C)];

} // namespace detail

template <typename T> struct is_tuple_like {
Expand Down