summaryrefslogtreecommitdiffstats
path: root/src/fmtlib/fmt/chrono.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/fmtlib/fmt/chrono.h209
1 files changed, 75 insertions, 134 deletions
diff --git a/src/fmtlib/fmt/chrono.h b/src/fmtlib/fmt/chrono.h
index 55e8a50..ff3e144 100644
--- a/src/fmtlib/fmt/chrono.h
+++ b/src/fmtlib/fmt/chrono.h
@@ -377,8 +377,8 @@ auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc)
unit_t unit;
write_codecvt(unit, in, loc);
// In UTF-8 is used one to four one-byte code units.
- unicode_to_utf8<code_unit, basic_memory_buffer<char, unit_t::max_size * 4>>
- u;
+ auto u =
+ to_utf8<code_unit, basic_memory_buffer<char, unit_t::max_size * 4>>();
if (!u.convert({unit.buf, to_unsigned(unit.end - unit.buf)}))
FMT_THROW(format_error("failed to format time"));
return copy_str<char>(u.c_str(), u.c_str() + u.size(), out);
@@ -519,7 +519,7 @@ inline std::tm gmtime(std::time_t time) {
}
#endif
};
- dispatcher gt(time);
+ auto gt = dispatcher(time);
// Too big time values may be unsupported.
if (!gt.run()) FMT_THROW(format_error("time_t value out of range"));
return gt.tm_;
@@ -530,50 +530,7 @@ inline std::tm gmtime(
return gmtime(std::chrono::system_clock::to_time_t(time_point));
}
-FMT_BEGIN_DETAIL_NAMESPACE
-
-// DEPRECATED!
-template <typename Char>
-FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
- format_specs<Char>& specs) -> const Char* {
- FMT_ASSERT(begin != end, "");
- auto align = align::none;
- auto p = begin + code_point_length(begin);
- if (end - p <= 0) p = begin;
- for (;;) {
- switch (to_ascii(*p)) {
- case '<':
- align = align::left;
- break;
- case '>':
- align = align::right;
- break;
- case '^':
- align = align::center;
- break;
- }
- if (align != align::none) {
- if (p != begin) {
- auto c = *begin;
- if (c == '}') return begin;
- if (c == '{') {
- throw_format_error("invalid fill character '{'");
- return begin;
- }
- specs.fill = {begin, to_unsigned(p - begin)};
- begin = p + 1;
- } else {
- ++begin;
- }
- break;
- } else if (p == begin) {
- break;
- }
- p = begin;
- }
- specs.align = align;
- return begin;
-}
+namespace detail {
// Writes two-digit numbers a, b and c separated by sep to buf.
// The method by Pavel Novikov based on
@@ -1997,7 +1954,7 @@ struct chrono_formatter {
}
};
-FMT_END_DETAIL_NAMESPACE
+} // namespace detail
#if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907
using weekday = std::chrono::weekday;
@@ -2047,80 +2004,67 @@ template <typename Char> struct formatter<weekday, Char> {
template <typename Rep, typename Period, typename Char>
struct formatter<std::chrono::duration<Rep, Period>, Char> {
private:
- format_specs<Char> specs;
- int precision = -1;
- using arg_ref_type = detail::arg_ref<Char>;
- arg_ref_type width_ref;
- arg_ref_type precision_ref;
- bool localized = false;
- basic_string_view<Char> format_str;
- using duration = std::chrono::duration<Rep, Period>;
+ format_specs<Char> specs_;
+ detail::arg_ref<Char> width_ref_;
+ detail::arg_ref<Char> precision_ref_;
+ bool localized_ = false;
+ basic_string_view<Char> format_str_;
- using iterator = typename basic_format_parse_context<Char>::iterator;
- struct parse_range {
- iterator begin;
- iterator end;
- };
-
- FMT_CONSTEXPR parse_range do_parse(basic_format_parse_context<Char>& ctx) {
- auto begin = ctx.begin(), end = ctx.end();
- if (begin == end || *begin == '}') return {begin, begin};
+ public:
+ FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
+ -> decltype(ctx.begin()) {
+ auto it = ctx.begin(), end = ctx.end();
+ if (it == end || *it == '}') return it;
- begin = detail::parse_align(begin, end, specs);
- if (begin == end) return {begin, begin};
+ it = detail::parse_align(it, end, specs_);
+ if (it == end) return it;
- begin = detail::parse_dynamic_spec(begin, end, specs.width, width_ref, ctx);
- if (begin == end) return {begin, begin};
+ it = detail::parse_dynamic_spec(it, end, specs_.width, width_ref_, ctx);
+ if (it == end) return it;
auto checker = detail::chrono_format_checker();
- if (*begin == '.') {
+ if (*it == '.') {
checker.has_precision_integral = !std::is_floating_point<Rep>::value;
- begin =
- detail::parse_precision(begin, end, precision, precision_ref, ctx);
+ it = detail::parse_precision(it, end, specs_.precision, precision_ref_,
+ ctx);
}
- if (begin != end && *begin == 'L') {
- ++begin;
- localized = true;
+ if (it != end && *it == 'L') {
+ localized_ = true;
+ ++it;
}
- end = detail::parse_chrono_format(begin, end, checker);
- return {begin, end};
- }
-
- public:
- FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
- -> decltype(ctx.begin()) {
- auto range = do_parse(ctx);
- format_str = basic_string_view<Char>(
- &*range.begin, detail::to_unsigned(range.end - range.begin));
- return range.end;
+ end = detail::parse_chrono_format(it, end, checker);
+ format_str_ = {it, detail::to_unsigned(end - it)};
+ return end;
}
template <typename FormatContext>
- auto format(const duration& d, FormatContext& ctx) const
+ auto format(std::chrono::duration<Rep, Period> d, FormatContext& ctx) const
-> decltype(ctx.out()) {
- auto specs_copy = specs;
- auto precision_copy = precision;
- auto begin = format_str.begin(), end = format_str.end();
+ auto specs = specs_;
+ auto precision = specs.precision;
+ specs.precision = -1;
+ auto begin = format_str_.begin(), end = format_str_.end();
// As a possible future optimization, we could avoid extra copying if width
// is not specified.
- basic_memory_buffer<Char> buf;
+ auto buf = basic_memory_buffer<Char>();
auto out = std::back_inserter(buf);
- detail::handle_dynamic_spec<detail::width_checker>(specs_copy.width,
- width_ref, ctx);
- detail::handle_dynamic_spec<detail::precision_checker>(precision_copy,
- precision_ref, ctx);
+ detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref_,
+ ctx);
+ detail::handle_dynamic_spec<detail::precision_checker>(precision,
+ precision_ref_, ctx);
if (begin == end || *begin == '}') {
- out = detail::format_duration_value<Char>(out, d.count(), precision_copy);
+ out = detail::format_duration_value<Char>(out, d.count(), precision);
detail::format_duration_unit<Char, Period>(out);
} else {
- detail::chrono_formatter<FormatContext, decltype(out), Rep, Period> f(
- ctx, out, d);
- f.precision = precision_copy;
- f.localized = localized;
+ using chrono_formatter =
+ detail::chrono_formatter<FormatContext, decltype(out), Rep, Period>;
+ auto f = chrono_formatter(ctx, out, d);
+ f.precision = precision;
+ f.localized = localized_;
detail::parse_chrono_format(begin, end, f);
}
return detail::write(
- ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs_copy);
+ ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs);
}
};
@@ -2128,21 +2072,23 @@ 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->format_str = detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>{};
+ this->format_str_ = detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>{};
}
template <typename FormatContext>
auto format(std::chrono::time_point<std::chrono::system_clock, Duration> val,
FormatContext& ctx) const -> decltype(ctx.out()) {
using period = typename Duration::period;
- if (period::num != 1 || period::den != 1 ||
- std::is_floating_point<typename Duration::rep>::value) {
+ if (detail::const_check(
+ period::num != 1 || period::den != 1 ||
+ std::is_floating_point<typename Duration::rep>::value)) {
const auto epoch = val.time_since_epoch();
auto subsecs = std::chrono::duration_cast<Duration>(
epoch - std::chrono::duration_cast<std::chrono::seconds>(epoch));
if (subsecs.count() < 0) {
- auto second = std::chrono::seconds(1);
+ auto second =
+ std::chrono::duration_cast<Duration>(std::chrono::seconds(1));
if (epoch.count() < ((Duration::min)() + second).count())
FMT_THROW(format_error("duration is too small"));
subsecs += second;
@@ -2164,7 +2110,7 @@ template <typename Char, typename Duration>
struct formatter<std::chrono::local_time<Duration>, Char>
: formatter<std::tm, Char> {
FMT_CONSTEXPR formatter() {
- this->format_str = detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>{};
+ this->format_str_ = detail::string_literal<Char, '%', 'F', ' ', '%', 'T'>{};
}
template <typename FormatContext>
@@ -2207,51 +2153,46 @@ struct formatter<std::chrono::time_point<std::chrono::utc_clock, Duration>,
template <typename Char> struct formatter<std::tm, Char> {
private:
- format_specs<Char> specs;
- detail::arg_ref<Char> width_ref;
+ format_specs<Char> specs_;
+ detail::arg_ref<Char> width_ref_;
protected:
- basic_string_view<Char> format_str;
-
- FMT_CONSTEXPR auto do_parse(basic_format_parse_context<Char>& ctx)
- -> decltype(ctx.begin()) {
- auto begin = ctx.begin(), end = ctx.end();
- if (begin == end || *begin == '}') return begin;
-
- begin = detail::parse_align(begin, end, specs);
- if (begin == end) return end;
-
- begin = detail::parse_dynamic_spec(begin, end, specs.width, width_ref, ctx);
- if (begin == end) return end;
-
- end = detail::parse_chrono_format(begin, end, detail::tm_format_checker());
- // Replace default format_str only if the new spec is not empty.
- if (end != begin) format_str = {begin, detail::to_unsigned(end - begin)};
- return end;
- }
+ basic_string_view<Char> format_str_;
template <typename FormatContext, typename Duration>
auto do_format(const std::tm& tm, FormatContext& ctx,
const Duration* subsecs) const -> decltype(ctx.out()) {
- auto specs_copy = specs;
- basic_memory_buffer<Char> buf;
+ auto specs = specs_;
+ auto buf = basic_memory_buffer<Char>();
auto out = std::back_inserter(buf);
- detail::handle_dynamic_spec<detail::width_checker>(specs_copy.width,
- width_ref, ctx);
+ detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref_,
+ ctx);
- const auto loc_ref = ctx.locale();
+ auto loc_ref = ctx.locale();
detail::get_locale loc(static_cast<bool>(loc_ref), loc_ref);
auto w =
detail::tm_writer<decltype(out), Char, Duration>(loc, out, tm, subsecs);
- detail::parse_chrono_format(format_str.begin(), format_str.end(), w);
+ detail::parse_chrono_format(format_str_.begin(), format_str_.end(), w);
return detail::write(
- ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs_copy);
+ ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs);
}
public:
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
-> decltype(ctx.begin()) {
- return this->do_parse(ctx);
+ auto it = ctx.begin(), end = ctx.end();
+ if (it == end || *it == '}') return it;
+
+ it = detail::parse_align(it, end, specs_);
+ if (it == end) return it;
+
+ it = detail::parse_dynamic_spec(it, end, specs_.width, width_ref_, ctx);
+ if (it == end) return it;
+
+ end = detail::parse_chrono_format(it, end, detail::tm_format_checker());
+ // Replace the default format_str only if the new spec is not empty.
+ if (end != it) format_str_ = {it, detail::to_unsigned(end - it)};
+ return end;
}
template <typename FormatContext>