diff options
author | Arnur Nigmetov <nigmetov@tugraz.at> | 2019-12-03 21:14:03 +0100 |
---|---|---|
committer | Arnur Nigmetov <nigmetov@tugraz.at> | 2020-02-18 15:02:39 +0100 |
commit | 6942d80c4d49239bca9cace9833aa74aee11ddcb (patch) | |
tree | 59797321de3b11800de28db8a4dc212828d11844 /matching/include/spdlog/fmt/bundled/chrono.h | |
parent | 919f04a0ad3406b9c02fbce3a9a92c03c9e85c94 (diff) |
Add matching distance code.
Diffstat (limited to 'matching/include/spdlog/fmt/bundled/chrono.h')
-rw-r--r-- | matching/include/spdlog/fmt/bundled/chrono.h | 452 |
1 files changed, 452 insertions, 0 deletions
diff --git a/matching/include/spdlog/fmt/bundled/chrono.h b/matching/include/spdlog/fmt/bundled/chrono.h new file mode 100644 index 0000000..209cdc2 --- /dev/null +++ b/matching/include/spdlog/fmt/bundled/chrono.h @@ -0,0 +1,452 @@ +// Formatting library for C++ - chrono support +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_CHRONO_H_ +#define FMT_CHRONO_H_ + +#include "format.h" +#include "locale.h" + +#include <chrono> +#include <ctime> +#include <locale> +#include <sstream> + +FMT_BEGIN_NAMESPACE + +namespace internal{ + +enum class numeric_system { + standard, + // Alternative numeric system, e.g. 十二 instead of 12 in ja_JP locale. + alternative +}; + +// Parses a put_time-like format string and invokes handler actions. +template <typename Char, typename Handler> +FMT_CONSTEXPR const Char *parse_chrono_format( + const Char *begin, const Char *end, Handler &&handler) { + auto ptr = begin; + while (ptr != end) { + auto c = *ptr; + if (c == '}') break; + if (c != '%') { + ++ptr; + continue; + } + if (begin != ptr) + handler.on_text(begin, ptr); + ++ptr; // consume '%' + if (ptr == end) + throw format_error("invalid format"); + c = *ptr++; + switch (c) { + case '%': + handler.on_text(ptr - 1, ptr); + break; + case 'n': { + const char newline[] = "\n"; + handler.on_text(newline, newline + 1); + break; + } + case 't': { + const char tab[] = "\t"; + handler.on_text(tab, tab + 1); + break; + } + // Day of the week: + case 'a': + handler.on_abbr_weekday(); + break; + case 'A': + handler.on_full_weekday(); + break; + case 'w': + handler.on_dec0_weekday(numeric_system::standard); + break; + case 'u': + handler.on_dec1_weekday(numeric_system::standard); + break; + // Month: + case 'b': + handler.on_abbr_month(); + break; + case 'B': + handler.on_full_month(); + break; + // Hour, minute, second: + case 'H': + handler.on_24_hour(numeric_system::standard); + break; + case 'I': + handler.on_12_hour(numeric_system::standard); + break; + case 'M': + handler.on_minute(numeric_system::standard); + break; + case 'S': + handler.on_second(numeric_system::standard); + break; + // Other: + case 'c': + handler.on_datetime(numeric_system::standard); + break; + case 'x': + handler.on_loc_date(numeric_system::standard); + break; + case 'X': + handler.on_loc_time(numeric_system::standard); + break; + case 'D': + handler.on_us_date(); + break; + case 'F': + handler.on_iso_date(); + break; + case 'r': + handler.on_12_hour_time(); + break; + case 'R': + handler.on_24_hour_time(); + break; + case 'T': + handler.on_iso_time(); + break; + case 'p': + handler.on_am_pm(); + break; + case 'z': + handler.on_utc_offset(); + break; + case 'Z': + handler.on_tz_name(); + break; + // Alternative representation: + case 'E': { + if (ptr == end) + throw format_error("invalid format"); + c = *ptr++; + switch (c) { + case 'c': + handler.on_datetime(numeric_system::alternative); + break; + case 'x': + handler.on_loc_date(numeric_system::alternative); + break; + case 'X': + handler.on_loc_time(numeric_system::alternative); + break; + default: + throw format_error("invalid format"); + } + break; + } + case 'O': + if (ptr == end) + throw format_error("invalid format"); + c = *ptr++; + switch (c) { + case 'w': + handler.on_dec0_weekday(numeric_system::alternative); + break; + case 'u': + handler.on_dec1_weekday(numeric_system::alternative); + break; + case 'H': + handler.on_24_hour(numeric_system::alternative); + break; + case 'I': + handler.on_12_hour(numeric_system::alternative); + break; + case 'M': + handler.on_minute(numeric_system::alternative); + break; + case 'S': + handler.on_second(numeric_system::alternative); + break; + default: + throw format_error("invalid format"); + } + break; + default: + throw format_error("invalid format"); + } + begin = ptr; + } + if (begin != ptr) + handler.on_text(begin, ptr); + return ptr; +} + +struct chrono_format_checker { + void report_no_date() { throw format_error("no date"); } + + template <typename Char> + void on_text(const Char *, const Char *) {} + void on_abbr_weekday() { report_no_date(); } + void on_full_weekday() { report_no_date(); } + void on_dec0_weekday(numeric_system) { report_no_date(); } + void on_dec1_weekday(numeric_system) { report_no_date(); } + void on_abbr_month() { report_no_date(); } + void on_full_month() { report_no_date(); } + void on_24_hour(numeric_system) {} + void on_12_hour(numeric_system) {} + void on_minute(numeric_system) {} + void on_second(numeric_system) {} + void on_datetime(numeric_system) { report_no_date(); } + void on_loc_date(numeric_system) { report_no_date(); } + void on_loc_time(numeric_system) { report_no_date(); } + void on_us_date() { report_no_date(); } + void on_iso_date() { report_no_date(); } + void on_12_hour_time() {} + void on_24_hour_time() {} + void on_iso_time() {} + void on_am_pm() {} + void on_utc_offset() { report_no_date(); } + void on_tz_name() { report_no_date(); } +}; + +template <typename Int> +inline int to_int(Int value) { + FMT_ASSERT(value >= (std::numeric_limits<int>::min)() && + value <= (std::numeric_limits<int>::max)(), "invalid value"); + return static_cast<int>(value); +} + +template <typename FormatContext, typename OutputIt> +struct chrono_formatter { + FormatContext &context; + OutputIt out; + std::chrono::seconds s; + std::chrono::milliseconds ms; + + typedef typename FormatContext::char_type char_type; + + explicit chrono_formatter(FormatContext &ctx, OutputIt o) + : context(ctx), out(o) {} + + int hour() const { return to_int((s.count() / 3600) % 24); } + + int hour12() const { + auto hour = to_int((s.count() / 3600) % 12); + return hour > 0 ? hour : 12; + } + + int minute() const { return to_int((s.count() / 60) % 60); } + int second() const { return to_int(s.count() % 60); } + + std::tm time() const { + auto time = std::tm(); + time.tm_hour = hour(); + time.tm_min = minute(); + time.tm_sec = second(); + return time; + } + + void write(int value, int width) { + typedef typename int_traits<int>::main_type main_type; + main_type n = to_unsigned(value); + int num_digits = internal::count_digits(n); + if (width > num_digits) + out = std::fill_n(out, width - num_digits, '0'); + out = format_decimal<char_type>(out, n, num_digits); + } + + void format_localized(const tm &time, const char *format) { + auto locale = context.locale().template get<std::locale>(); + auto &facet = std::use_facet<std::time_put<char_type>>(locale); + std::basic_ostringstream<char_type> os; + os.imbue(locale); + facet.put(os, os, ' ', &time, format, format + std::strlen(format)); + auto str = os.str(); + std::copy(str.begin(), str.end(), out); + } + + void on_text(const char_type *begin, const char_type *end) { + std::copy(begin, end, out); + } + + // These are not implemented because durations don't have date information. + void on_abbr_weekday() {} + void on_full_weekday() {} + void on_dec0_weekday(numeric_system) {} + void on_dec1_weekday(numeric_system) {} + void on_abbr_month() {} + void on_full_month() {} + void on_datetime(numeric_system) {} + void on_loc_date(numeric_system) {} + void on_loc_time(numeric_system) {} + void on_us_date() {} + void on_iso_date() {} + void on_utc_offset() {} + void on_tz_name() {} + + void on_24_hour(numeric_system ns) { + if (ns == numeric_system::standard) + return write(hour(), 2); + auto time = tm(); + time.tm_hour = hour(); + format_localized(time, "%OH"); + } + + void on_12_hour(numeric_system ns) { + if (ns == numeric_system::standard) + return write(hour12(), 2); + auto time = tm(); + time.tm_hour = hour(); + format_localized(time, "%OI"); + } + + void on_minute(numeric_system ns) { + if (ns == numeric_system::standard) + return write(minute(), 2); + auto time = tm(); + time.tm_min = minute(); + format_localized(time, "%OM"); + } + + void on_second(numeric_system ns) { + if (ns == numeric_system::standard) { + write(second(), 2); + if (ms != std::chrono::milliseconds(0)) { + *out++ = '.'; + write(to_int(ms.count()), 3); + } + return; + } + auto time = tm(); + time.tm_sec = second(); + format_localized(time, "%OS"); + } + + void on_12_hour_time() { format_localized(time(), "%r"); } + + void on_24_hour_time() { + write(hour(), 2); + *out++ = ':'; + write(minute(), 2); + } + + void on_iso_time() { + on_24_hour_time(); + *out++ = ':'; + write(second(), 2); + } + + void on_am_pm() { format_localized(time(), "%p"); } +}; +} // namespace internal + +template <typename Period> FMT_CONSTEXPR const char *get_units() { + return FMT_NULL; +} +template <> FMT_CONSTEXPR const char *get_units<std::atto>() { return "as"; } +template <> FMT_CONSTEXPR const char *get_units<std::femto>() { return "fs"; } +template <> FMT_CONSTEXPR const char *get_units<std::pico>() { return "ps"; } +template <> FMT_CONSTEXPR const char *get_units<std::nano>() { return "ns"; } +template <> FMT_CONSTEXPR const char *get_units<std::micro>() { return "µs"; } +template <> FMT_CONSTEXPR const char *get_units<std::milli>() { return "ms"; } +template <> FMT_CONSTEXPR const char *get_units<std::centi>() { return "cs"; } +template <> FMT_CONSTEXPR const char *get_units<std::deci>() { return "ds"; } +template <> FMT_CONSTEXPR const char *get_units<std::ratio<1>>() { return "s"; } +template <> FMT_CONSTEXPR const char *get_units<std::deca>() { return "das"; } +template <> FMT_CONSTEXPR const char *get_units<std::hecto>() { return "hs"; } +template <> FMT_CONSTEXPR const char *get_units<std::kilo>() { return "ks"; } +template <> FMT_CONSTEXPR const char *get_units<std::mega>() { return "Ms"; } +template <> FMT_CONSTEXPR const char *get_units<std::giga>() { return "Gs"; } +template <> FMT_CONSTEXPR const char *get_units<std::tera>() { return "Ts"; } +template <> FMT_CONSTEXPR const char *get_units<std::peta>() { return "Ps"; } +template <> FMT_CONSTEXPR const char *get_units<std::exa>() { return "Es"; } +template <> FMT_CONSTEXPR const char *get_units<std::ratio<60>>() { + return "m"; +} +template <> FMT_CONSTEXPR const char *get_units<std::ratio<3600>>() { + return "h"; +} + +template <typename Rep, typename Period, typename Char> +struct formatter<std::chrono::duration<Rep, Period>, Char> { + private: + align_spec spec; + internal::arg_ref<Char> width_ref; + mutable basic_string_view<Char> format_str; + typedef std::chrono::duration<Rep, Period> duration; + + struct spec_handler { + formatter &f; + basic_parse_context<Char> &context; + + typedef internal::arg_ref<Char> arg_ref_type; + + template <typename Id> + FMT_CONSTEXPR arg_ref_type make_arg_ref(Id arg_id) { + context.check_arg_id(arg_id); + return arg_ref_type(arg_id); + } + + FMT_CONSTEXPR arg_ref_type make_arg_ref(internal::auto_id) { + return arg_ref_type(context.next_arg_id()); + } + + void on_error(const char *msg) { throw format_error(msg); } + void on_fill(Char fill) { f.spec.fill_ = fill; } + void on_align(alignment align) { f.spec.align_ = align; } + void on_width(unsigned width) { f.spec.width_ = width; } + + template <typename Id> + void on_dynamic_width(Id arg_id) { + f.width_ref = make_arg_ref(arg_id); + } + }; + + public: + formatter() : spec() {} + + FMT_CONSTEXPR auto parse(basic_parse_context<Char> &ctx) + -> decltype(ctx.begin()) { + auto begin = ctx.begin(), end = ctx.end(); + if (begin == end) return begin; + spec_handler handler{*this, ctx}; + begin = internal::parse_align(begin, end, handler); + if (begin == end) return begin; + begin = internal::parse_width(begin, end, handler); + end = parse_chrono_format(begin, end, internal::chrono_format_checker()); + format_str = basic_string_view<Char>(&*begin, internal::to_unsigned(end - begin)); + return end; + } + + template <typename FormatContext> + auto format(const duration &d, FormatContext &ctx) + -> decltype(ctx.out()) { + auto begin = format_str.begin(), end = format_str.end(); + memory_buffer buf; + typedef output_range<decltype(ctx.out()), Char> range; + basic_writer<range> w(range(ctx.out())); + if (begin == end || *begin == '}') { + if (const char *unit = get_units<Period>()) + format_to(buf, "{}{}", d.count(), unit); + else if (Period::den == 1) + format_to(buf, "{}[{}]s", d.count(), Period::num); + else + format_to(buf, "{}[{}/{}]s", d.count(), Period::num, Period::den); + internal::handle_dynamic_spec<internal::width_checker>( + spec.width_, width_ref, ctx); + } else { + auto out = std::back_inserter(buf); + internal::chrono_formatter<FormatContext, decltype(out)> f(ctx, out); + f.s = std::chrono::duration_cast<std::chrono::seconds>(d); + f.ms = std::chrono::duration_cast<std::chrono::milliseconds>(d - f.s); + parse_chrono_format(begin, end, f); + } + w.write(buf.data(), buf.size(), spec); + return w.out(); + } +}; + +FMT_END_NAMESPACE + +#endif // FMT_CHRONO_H_ |