mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-30 10:47:35 +02:00
Add format spec checker
This commit is contained in:
committed by
Victor Zverovich
parent
fbbfc3b03c
commit
7911d8d3f5
@ -569,6 +569,22 @@ FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin,
|
|||||||
handler.on_text(tab, tab + 1);
|
handler.on_text(tab, tab + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Year
|
||||||
|
case 'Y':
|
||||||
|
handler.on_year(numeric_system::standard);
|
||||||
|
break;
|
||||||
|
case 'y':
|
||||||
|
handler.on_last2_year(numeric_system::standard);
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
handler.on_base_year(numeric_system::standard);
|
||||||
|
break;
|
||||||
|
case 'G':
|
||||||
|
handler.on_iso_week_based_year();
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
handler.on_iso_week_based_year_last2();
|
||||||
|
break;
|
||||||
// Day of the week:
|
// Day of the week:
|
||||||
case 'a':
|
case 'a':
|
||||||
handler.on_abbr_weekday();
|
handler.on_abbr_weekday();
|
||||||
@ -584,11 +600,34 @@ FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin,
|
|||||||
break;
|
break;
|
||||||
// Month:
|
// Month:
|
||||||
case 'b':
|
case 'b':
|
||||||
|
case 'h':
|
||||||
handler.on_abbr_month();
|
handler.on_abbr_month();
|
||||||
break;
|
break;
|
||||||
case 'B':
|
case 'B':
|
||||||
handler.on_full_month();
|
handler.on_full_month();
|
||||||
break;
|
break;
|
||||||
|
case 'm':
|
||||||
|
handler.on_dec_month(numeric_system::standard);
|
||||||
|
break;
|
||||||
|
// Day of the year/month
|
||||||
|
case 'U':
|
||||||
|
handler.on_dec0_week_of_year(numeric_system::standard);
|
||||||
|
break;
|
||||||
|
case 'W':
|
||||||
|
handler.on_dec1_week_of_year(numeric_system::standard);
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
handler.on_iso_week_of_year(numeric_system::standard);
|
||||||
|
break;
|
||||||
|
case 'j':
|
||||||
|
handler.on_day_of_year();
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
handler.on_day_of_month_zero(numeric_system::standard);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
handler.on_day_of_month_space(numeric_system::standard);
|
||||||
|
break;
|
||||||
// Hour, minute, second:
|
// Hour, minute, second:
|
||||||
case 'H':
|
case 'H':
|
||||||
handler.on_24_hour(numeric_system::standard);
|
handler.on_24_hour(numeric_system::standard);
|
||||||
@ -647,6 +686,15 @@ FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin,
|
|||||||
if (ptr == end) FMT_THROW(format_error("invalid format"));
|
if (ptr == end) FMT_THROW(format_error("invalid format"));
|
||||||
c = *ptr++;
|
c = *ptr++;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
case 'Y':
|
||||||
|
handler.on_year(numeric_system::alternative);
|
||||||
|
break;
|
||||||
|
case 'y':
|
||||||
|
handler.on_offset_year();
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
handler.on_base_year(numeric_system::alternative);
|
||||||
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
handler.on_datetime(numeric_system::alternative);
|
handler.on_datetime(numeric_system::alternative);
|
||||||
break;
|
break;
|
||||||
@ -665,6 +713,27 @@ FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin,
|
|||||||
if (ptr == end) FMT_THROW(format_error("invalid format"));
|
if (ptr == end) FMT_THROW(format_error("invalid format"));
|
||||||
c = *ptr++;
|
c = *ptr++;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
case 'y':
|
||||||
|
handler.on_last2_year(numeric_system::alternative);
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
handler.on_dec_month(numeric_system::alternative);
|
||||||
|
break;
|
||||||
|
case 'U':
|
||||||
|
handler.on_dec0_week_of_year(numeric_system::alternative);
|
||||||
|
break;
|
||||||
|
case 'W':
|
||||||
|
handler.on_dec1_week_of_year(numeric_system::alternative);
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
handler.on_iso_week_of_year(numeric_system::alternative);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
handler.on_day_of_month_zero(numeric_system::alternative);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
handler.on_day_of_month_space(numeric_system::alternative);
|
||||||
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
handler.on_dec0_weekday(numeric_system::alternative);
|
handler.on_dec0_weekday(numeric_system::alternative);
|
||||||
break;
|
break;
|
||||||
@ -700,12 +769,25 @@ template <typename Derived> struct null_chrono_spec_handler {
|
|||||||
FMT_CONSTEXPR void unsupported() {
|
FMT_CONSTEXPR void unsupported() {
|
||||||
static_cast<Derived*>(this)->unsupported();
|
static_cast<Derived*>(this)->unsupported();
|
||||||
}
|
}
|
||||||
|
FMT_CONSTEXPR void on_year(numeric_system) { unsupported(); }
|
||||||
|
FMT_CONSTEXPR void on_last2_year(numeric_system) { unsupported(); }
|
||||||
|
FMT_CONSTEXPR void on_offset_year() { unsupported(); }
|
||||||
|
FMT_CONSTEXPR void on_base_year(numeric_system) { unsupported(); }
|
||||||
|
FMT_CONSTEXPR void on_iso_week_based_year() { unsupported(); }
|
||||||
|
FMT_CONSTEXPR void on_iso_week_based_year_last2() { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_abbr_weekday() { unsupported(); }
|
FMT_CONSTEXPR void on_abbr_weekday() { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_full_weekday() { unsupported(); }
|
FMT_CONSTEXPR void on_full_weekday() { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_dec0_weekday(numeric_system) { unsupported(); }
|
FMT_CONSTEXPR void on_dec0_weekday(numeric_system) { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_dec1_weekday(numeric_system) { unsupported(); }
|
FMT_CONSTEXPR void on_dec1_weekday(numeric_system) { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_abbr_month() { unsupported(); }
|
FMT_CONSTEXPR void on_abbr_month() { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_full_month() { unsupported(); }
|
FMT_CONSTEXPR void on_full_month() { unsupported(); }
|
||||||
|
FMT_CONSTEXPR void on_dec_month(numeric_system) { unsupported(); }
|
||||||
|
FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system) { unsupported(); }
|
||||||
|
FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system) { unsupported(); }
|
||||||
|
FMT_CONSTEXPR void on_iso_week_of_year(numeric_system) { unsupported(); }
|
||||||
|
FMT_CONSTEXPR void on_day_of_year() { unsupported(); }
|
||||||
|
FMT_CONSTEXPR void on_day_of_month_zero(numeric_system) { unsupported(); }
|
||||||
|
FMT_CONSTEXPR void on_day_of_month_space(numeric_system) { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_24_hour(numeric_system) { unsupported(); }
|
FMT_CONSTEXPR void on_24_hour(numeric_system) { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_12_hour(numeric_system) { unsupported(); }
|
FMT_CONSTEXPR void on_12_hour(numeric_system) { unsupported(); }
|
||||||
FMT_CONSTEXPR void on_minute(numeric_system) { unsupported(); }
|
FMT_CONSTEXPR void on_minute(numeric_system) { unsupported(); }
|
||||||
@ -1006,6 +1088,19 @@ struct chrono_formatter {
|
|||||||
void on_iso_date() {}
|
void on_iso_date() {}
|
||||||
void on_utc_offset() {}
|
void on_utc_offset() {}
|
||||||
void on_tz_name() {}
|
void on_tz_name() {}
|
||||||
|
void on_year(numeric_system) {}
|
||||||
|
void on_last2_year(numeric_system) {}
|
||||||
|
void on_offset_year() {}
|
||||||
|
void on_base_year(numeric_system) {}
|
||||||
|
void on_iso_week_based_year() {}
|
||||||
|
void on_iso_week_based_year_last2() {}
|
||||||
|
void on_dec_month(numeric_system) {}
|
||||||
|
void on_dec0_week_of_year(numeric_system) {}
|
||||||
|
void on_dec1_week_of_year(numeric_system) {}
|
||||||
|
void on_iso_week_of_year(numeric_system) {}
|
||||||
|
void on_day_of_year() {}
|
||||||
|
void on_day_of_month_zero(numeric_system) {}
|
||||||
|
void on_day_of_month_space(numeric_system) {}
|
||||||
|
|
||||||
void on_24_hour(numeric_system ns) {
|
void on_24_hour(numeric_system ns) {
|
||||||
if (handle_nan_inf()) return;
|
if (handle_nan_inf()) return;
|
||||||
@ -1261,6 +1356,51 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FMT_BEGIN_DETAIL_NAMESPACE
|
||||||
|
|
||||||
|
struct tm_format_checker : null_chrono_spec_handler<tm_format_checker> {
|
||||||
|
FMT_NORETURN void unsupported() { FMT_THROW(format_error("no format")); }
|
||||||
|
|
||||||
|
template <typename Char>
|
||||||
|
FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
|
||||||
|
FMT_CONSTEXPR void on_year(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_last2_year(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_offset_year() {}
|
||||||
|
FMT_CONSTEXPR void on_base_year(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_iso_week_based_year() {}
|
||||||
|
FMT_CONSTEXPR void on_iso_week_based_year_last2() {}
|
||||||
|
FMT_CONSTEXPR void on_abbr_weekday() {}
|
||||||
|
FMT_CONSTEXPR void on_full_weekday() {}
|
||||||
|
FMT_CONSTEXPR void on_dec0_weekday(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_dec1_weekday(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_abbr_month() {}
|
||||||
|
FMT_CONSTEXPR void on_full_month() {}
|
||||||
|
FMT_CONSTEXPR void on_dec_month(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_iso_week_of_year(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_day_of_year() {}
|
||||||
|
FMT_CONSTEXPR void on_day_of_month_zero(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_day_of_month_space(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_24_hour(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_12_hour(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_minute(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_second(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_datetime(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_loc_date(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_loc_time(numeric_system) {}
|
||||||
|
FMT_CONSTEXPR void on_us_date() {}
|
||||||
|
FMT_CONSTEXPR void on_iso_date() {}
|
||||||
|
FMT_CONSTEXPR void on_12_hour_time() {}
|
||||||
|
FMT_CONSTEXPR void on_24_hour_time() {}
|
||||||
|
FMT_CONSTEXPR void on_iso_time() {}
|
||||||
|
FMT_CONSTEXPR void on_am_pm() {}
|
||||||
|
FMT_CONSTEXPR void on_utc_offset() {}
|
||||||
|
FMT_CONSTEXPR void on_tz_name() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
FMT_END_DETAIL_NAMESPACE
|
||||||
|
|
||||||
template <typename Char, typename Duration>
|
template <typename Char, typename Duration>
|
||||||
struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
|
struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
|
||||||
Char> : formatter<std::tm, Char> {
|
Char> : formatter<std::tm, Char> {
|
||||||
@ -1270,11 +1410,11 @@ struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
|
|||||||
|
|
||||||
template <typename ParseContext>
|
template <typename ParseContext>
|
||||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||||
auto it = ctx.begin();
|
auto begin = ctx.begin();
|
||||||
if (it != ctx.end() && *it == ':') ++it;
|
auto end = ctx.end();
|
||||||
auto end = it;
|
if (begin != end && *begin == ':') ++begin;
|
||||||
while (end != ctx.end() && *end != '}') ++end;
|
end = detail::parse_chrono_format(begin, end, detail::tm_format_checker());
|
||||||
if (end != it) this->specs = {it, detail::to_unsigned(end - it)};
|
if (end != begin) this->specs = {begin, detail::to_unsigned(end - begin)};
|
||||||
return end;
|
return end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1307,12 +1447,11 @@ template <typename Char> struct formatter<std::tm, Char> {
|
|||||||
|
|
||||||
template <typename ParseContext>
|
template <typename ParseContext>
|
||||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||||
auto it = ctx.begin();
|
auto begin = ctx.begin();
|
||||||
if (it != ctx.end() && *it == ':') ++it;
|
auto end = ctx.end();
|
||||||
auto end = it;
|
if (begin != end && *begin == ':') ++begin;
|
||||||
while (end != ctx.end() && *end != '}') ++end;
|
end = detail::parse_chrono_format(begin, end, detail::tm_format_checker());
|
||||||
auto size = detail::to_unsigned(end - it);
|
specs = {begin, detail::to_unsigned(end - begin)};
|
||||||
specs = {it, size};
|
|
||||||
// basic_string_view<>::compare isn't constexpr before C++17
|
// basic_string_view<>::compare isn't constexpr before C++17
|
||||||
if (specs.size() == 2 && specs[0] == Char('%')) {
|
if (specs.size() == 2 && specs[0] == Char('%')) {
|
||||||
if (specs[1] == Char('F'))
|
if (specs[1] == Char('F'))
|
||||||
|
Reference in New Issue
Block a user