Skip to content

Commit

Permalink
address comments and abstract the calendar elements into a base class…
Browse files Browse the repository at this point in the history
… so that we can reuse the parse function
  • Loading branch information
zivshek committed Mar 30, 2024
1 parent 94def7a commit 6cc5d66
Showing 1 changed file with 31 additions and 66 deletions.
97 changes: 31 additions & 66 deletions include/fmt/chrono.h
Original file line number Diff line number Diff line change
Expand Up @@ -2042,8 +2042,9 @@ using month = std::chrono::month;
using year = std::chrono::year;
using year_month_day = std::chrono::year_month_day;
#else
class calendar_base {};
// A fallback version of weekday.
class weekday {
class weekday : calendar_base {
private:
unsigned char value_;

Expand All @@ -2054,7 +2055,7 @@ class weekday {
constexpr auto c_encoding() const noexcept -> unsigned { return value_; }
};

class day {
class day : calendar_base {
private:
unsigned char value_;

Expand All @@ -2065,7 +2066,7 @@ class day {
constexpr explicit operator unsigned() const noexcept { return value_; }
};

class month {
class month : calendar_base {
private:
unsigned char value_;

Expand All @@ -2076,7 +2077,7 @@ class month {
constexpr explicit operator unsigned() const noexcept { return value_; }
};

class year {
class year : calendar_base {
private:
int value_;

Expand All @@ -2086,15 +2087,16 @@ class year {
constexpr explicit operator int() const noexcept { return value_; }
};

class year_month_day {
class year_month_day : calendar_base {
private:
fmt::year year_;
fmt::month month_;
fmt::day day_;

public:
year_month_day() = default;
constexpr year_month_day(const year& y, const month& m, const day& d) noexcept
constexpr year_month_day(const fmt::year& y, const fmt::month& m,
const fmt::day& d) noexcept
: year_(y), month_(m), day_(d) {}
constexpr fmt::year year() const noexcept { return year_; }
constexpr fmt::month month() const noexcept { return month_; }
Expand All @@ -2103,133 +2105,96 @@ class year_month_day {
#endif

template <typename Char>
struct formatter<weekday, Char> : formatter<std::tm, Char> {
private:
bool localized{false};
struct formatter<calendar_base, Char> : formatter<std::tm, Char> {
protected:
bool localized_{false};
bool use_tm_formatter_{false};

public:
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
-> decltype(ctx.begin()) {
auto begin = ctx.begin(), end = ctx.end();
if (begin != end && *begin == 'L') {
++begin;
localized = true;
auto it = ctx.begin(), end = ctx.end();
if (it != end && *it == 'L') {
++it;
localized_ = true;
}
use_tm_formatter_ = !localized && (begin != nullptr);
return use_tm_formatter_ ? formatter<std::tm, Char>::parse(ctx) : begin;
auto empty = (it == end || *it == '}');
use_tm_formatter_ = !empty && !localized_;
return use_tm_formatter_ ? formatter<std::tm, Char>::parse(ctx) : it;
}
};

template <typename Char>
struct formatter<weekday, Char> : formatter<calendar_base, Char> {
public:
template <typename FormatContext>
auto format(weekday wd, FormatContext& ctx) const -> decltype(ctx.out()) {
auto time = std::tm();
time.tm_wday = static_cast<int>(wd.c_encoding());
if (use_tm_formatter_) {
return formatter<std::tm, Char>::format(time, ctx);
}
detail::get_locale loc(localized, ctx.locale());
detail::get_locale loc(localized_, ctx.locale());
auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), time);
w.on_abbr_weekday();
return w.out();
}
};

template <typename Char>
struct formatter<day, Char> : formatter<std::tm, Char> {
private:
bool use_tm_formatter_{false};

struct formatter<day, Char> : formatter<calendar_base, Char> {
public:
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
-> decltype(ctx.begin()) {
use_tm_formatter_ = ctx.begin() != nullptr;
return formatter<std::tm, Char>::parse(ctx);
}

template <typename FormatContext>
auto format(day d, FormatContext& ctx) const -> decltype(ctx.out()) {
auto time = std::tm();
time.tm_mday = static_cast<int>(static_cast<unsigned>(d));
if (use_tm_formatter_) {
return formatter<std::tm, Char>::format(time, ctx);
}
detail::get_locale loc(false, ctx.locale());
detail::get_locale loc(localized_, ctx.locale());
auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), time);
w.on_day_of_month(detail::numeric_system::standard);
return w.out();
}
};

template <typename Char>
struct formatter<month, Char> : formatter<std::tm, Char> {
private:
bool localized{false};
bool use_tm_formatter_{false};

struct formatter<month, Char> : formatter<calendar_base, Char> {
public:
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
-> decltype(ctx.begin()) {
auto begin = ctx.begin(), end = ctx.end();
if (begin != end && *begin == 'L') {
++begin;
localized = true;
}
use_tm_formatter_ = !localized && (begin != nullptr);
return use_tm_formatter_ ? formatter<std::tm, Char>::parse(ctx) : begin;
}

template <typename FormatContext>
auto format(month m, FormatContext& ctx) const -> decltype(ctx.out()) {
auto time = std::tm();
time.tm_mon = static_cast<int>(static_cast<unsigned>(m)) - 1;
if (use_tm_formatter_) {
return formatter<std::tm, Char>::format(time, ctx);
}
detail::get_locale loc(localized, ctx.locale());
detail::get_locale loc(localized_, ctx.locale());
auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), time);
w.on_abbr_month();
return w.out();
}
};

template <typename Char>
struct formatter<year, Char> : formatter<std::tm, Char> {
private:
bool use_tm_formatter_{false};

struct formatter<year, Char> : formatter<calendar_base, Char> {
public:
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
-> decltype(ctx.begin()) {
use_tm_formatter_ = ctx.begin() != nullptr;
return formatter<std::tm, Char>::parse(ctx);
}

template <typename FormatContext>
auto format(year y, FormatContext& ctx) const -> decltype(ctx.out()) {
auto time = std::tm();
time.tm_year = static_cast<int>(y) - 1900;
if (use_tm_formatter_) {
return formatter<std::tm, Char>::format(time, ctx);
}
detail::get_locale loc(false, ctx.locale());
detail::get_locale loc(localized_, ctx.locale());
auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), time);
w.on_year(detail::numeric_system::standard);
return w.out();
}
};

template <typename Char>
struct formatter<year_month_day, Char> : formatter<std::tm, Char> {
private:
bool use_tm_formatter_{false};

struct formatter<year_month_day, Char> : formatter<calendar_base, Char> {
public:
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
-> decltype(ctx.begin()) {
use_tm_formatter_ = ctx.begin() != nullptr;
return formatter<std::tm, Char>::parse(ctx);
}

template <typename FormatContext>
auto format(year_month_day val, FormatContext& ctx) const
-> decltype(ctx.out()) {
Expand All @@ -2240,7 +2205,7 @@ struct formatter<year_month_day, Char> : formatter<std::tm, Char> {
if (use_tm_formatter_) {
return formatter<std::tm, Char>::format(time, ctx);
}
detail::get_locale loc(true, ctx.locale());
detail::get_locale loc(localized_, ctx.locale());
auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), time);
w.on_iso_date();
return w.out();
Expand Down

0 comments on commit 6cc5d66

Please sign in to comment.