22 #ifndef FMT_SAFE_DURATION_CAST 23 # define FMT_SAFE_DURATION_CAST 1 25 #if FMT_SAFE_DURATION_CAST 35 template <
typename To,
typename From,
36 FMT_ENABLE_IF(!std::is_same<From, To>::value &&
37 std::numeric_limits<From>::is_signed ==
38 std::numeric_limits<To>::is_signed)>
39 FMT_CONSTEXPR To lossless_integral_conversion(
const From from,
int& ec) {
41 using F = std::numeric_limits<From>;
42 using T = std::numeric_limits<To>;
43 static_assert(F::is_integer,
"From must be integral");
44 static_assert(T::is_integer,
"To must be integral");
47 if (F::digits <= T::digits) {
51 if (from < (T::min)() || from > (T::max)()) {
57 return static_cast<To
>(from);
64 template <
typename To,
typename From,
65 FMT_ENABLE_IF(!std::is_same<From, To>::value &&
66 std::numeric_limits<From>::is_signed !=
67 std::numeric_limits<To>::is_signed)>
68 FMT_CONSTEXPR To lossless_integral_conversion(
const From from,
int& ec) {
70 using F = std::numeric_limits<From>;
71 using T = std::numeric_limits<To>;
72 static_assert(F::is_integer,
"From must be integral");
73 static_assert(T::is_integer,
"To must be integral");
75 if (detail::const_check(F::is_signed && !T::is_signed)) {
77 if (fmt::detail::is_negative(from)) {
82 if (F::digits > T::digits &&
83 from > static_cast<From>(detail::max_value<To>())) {
89 if (!F::is_signed && T::is_signed && F::digits >= T::digits &&
90 from > static_cast<From>(detail::max_value<To>())) {
94 return static_cast<To
>(from);
97 template <
typename To,
typename From,
98 FMT_ENABLE_IF(std::is_same<From, To>::value)>
99 FMT_CONSTEXPR To lossless_integral_conversion(
const From from,
int& ec) {
118 template <
typename To,
typename From,
119 FMT_ENABLE_IF(!std::is_same<From, To>::value)>
120 FMT_CONSTEXPR To safe_float_conversion(
const From from,
int& ec) {
122 using T = std::numeric_limits<To>;
123 static_assert(std::is_floating_point<From>::value,
"From must be floating");
124 static_assert(std::is_floating_point<To>::value,
"To must be floating");
127 if (std::isfinite(from)) {
128 if (from >= T::lowest() && from <= (T::max)()) {
129 return static_cast<To
>(from);
137 return static_cast<To
>(from);
140 template <
typename To,
typename From,
141 FMT_ENABLE_IF(std::is_same<From, To>::value)>
142 FMT_CONSTEXPR To safe_float_conversion(
const From from,
int& ec) {
144 static_assert(std::is_floating_point<From>::value,
"From must be floating");
151 template <
typename To,
typename FromRep,
typename FromPeriod,
152 FMT_ENABLE_IF(std::is_integral<FromRep>::value),
153 FMT_ENABLE_IF(std::is_integral<typename To::rep>::value)>
156 using From = std::chrono::duration<FromRep, FromPeriod>;
161 : std::ratio_divide<typename From::period, typename To::period> {};
163 static_assert(Factor::num > 0,
"num must be positive");
164 static_assert(Factor::den > 0,
"den must be positive");
170 using IntermediateRep =
171 typename std::common_type<
typename From::rep,
typename To::rep,
172 decltype(Factor::num)>::type;
175 IntermediateRep count =
176 lossless_integral_conversion<IntermediateRep>(from.count(), ec);
179 if (detail::const_check(Factor::num != 1)) {
180 const auto max1 = detail::max_value<IntermediateRep>() / Factor::num;
186 (std::numeric_limits<IntermediateRep>::min)() / Factor::num;
191 count *= Factor::num;
194 if (detail::const_check(Factor::den != 1)) count /= Factor::den;
195 auto tocount = lossless_integral_conversion<typename To::rep>(count, ec);
196 return ec ? To() : To(tocount);
202 template <
typename To,
typename FromRep,
typename FromPeriod,
203 FMT_ENABLE_IF(std::is_floating_point<FromRep>::value),
204 FMT_ENABLE_IF(std::is_floating_point<typename To::rep>::value)>
207 using From = std::chrono::duration<FromRep, FromPeriod>;
209 if (std::isnan(from.count())) {
211 return To{std::numeric_limits<typename To::rep>::quiet_NaN()};
217 if (std::isinf(from.count())) {
218 return To{from.count()};
224 : std::ratio_divide<typename From::period, typename To::period> {};
226 static_assert(Factor::num > 0,
"num must be positive");
227 static_assert(Factor::den > 0,
"den must be positive");
233 using IntermediateRep =
234 typename std::common_type<
typename From::rep,
typename To::rep,
235 decltype(Factor::num)>::type;
239 IntermediateRep count =
240 safe_float_conversion<IntermediateRep>(from.count(), ec);
246 if (Factor::num != 1) {
247 constexpr
auto max1 = detail::max_value<IntermediateRep>() /
248 static_cast<IntermediateRep>(Factor::num);
253 constexpr
auto min1 = std::numeric_limits<IntermediateRep>::lowest() /
254 static_cast<IntermediateRep
>(Factor::num);
259 count *=
static_cast<IntermediateRep
>(Factor::num);
263 if (Factor::den != 1) {
264 using common_t =
typename std::common_type<IntermediateRep, intmax_t>::type;
265 count /=
static_cast<common_t
>(Factor::den);
269 using ToRep =
typename To::rep;
271 const ToRep tocount = safe_float_conversion<ToRep>(count, ec);
285 inline null<> localtime_r FMT_NOMACRO(...) {
return null<>(); }
286 inline null<> localtime_s(...) {
return null<>(); }
287 inline null<> gmtime_r(...) {
return null<>(); }
288 inline null<> gmtime_s(...) {
return null<>(); }
292 inline std::tm localtime(std::time_t time) {
297 dispatcher(std::time_t t) : time_(t) {}
300 using namespace fmt::detail;
301 return handle(localtime_r(&time_, &tm_));
304 bool handle(std::tm* tm) {
return tm !=
nullptr; }
307 using namespace fmt::detail;
308 return fallback(localtime_s(&tm_, &time_));
311 bool fallback(
int res) {
return res == 0; }
315 using namespace fmt::detail;
316 std::tm* tm = std::localtime(&time_);
318 return tm !=
nullptr;
324 if (!lt.run()) FMT_THROW(
format_error(
"time_t value out of range"));
328 inline std::tm localtime(
329 std::chrono::time_point<std::chrono::system_clock> time_point) {
330 return localtime(std::chrono::system_clock::to_time_t(time_point));
334 inline std::tm gmtime(std::time_t time) {
339 dispatcher(std::time_t t) : time_(t) {}
342 using namespace fmt::detail;
343 return handle(gmtime_r(&time_, &tm_));
346 bool handle(std::tm* tm) {
return tm !=
nullptr; }
349 using namespace fmt::detail;
350 return fallback(gmtime_s(&tm_, &time_));
353 bool fallback(
int res) {
return res == 0; }
357 std::tm* tm = std::gmtime(&time_);
359 return tm !=
nullptr;
365 if (!gt.run()) FMT_THROW(
format_error(
"time_t value out of range"));
369 inline std::tm gmtime(
370 std::chrono::time_point<std::chrono::system_clock> time_point) {
371 return gmtime(std::chrono::system_clock::to_time_t(time_point));
375 inline size_t strftime(
char* str,
size_t count,
const char* format,
376 const std::tm* time) {
377 return std::strftime(str, count, format, time);
380 inline size_t strftime(
wchar_t* str,
size_t count,
const wchar_t* format,
381 const std::tm* time) {
382 return std::wcsftime(str, count, format, time);
386 template <
typename Char>
387 struct formatter<
std::chrono::time_point<std::chrono::system_clock>, Char>
389 template <
typename FormatContext>
390 auto format(std::chrono::time_point<std::chrono::system_clock> val,
391 FormatContext& ctx) -> decltype(ctx.out()) {
392 std::tm time = localtime(val);
398 template <
typename ParseContext>
399 auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
400 auto it = ctx.begin();
401 if (it != ctx.end() && *it ==
':') ++it;
403 while (end != ctx.end() && *end !=
'}') ++end;
404 tm_format.reserve(detail::to_unsigned(end - it + 1));
405 tm_format.append(it, end);
406 tm_format.push_back(
'\0');
410 template <
typename FormatContext>
411 auto format(
const std::tm& tm, FormatContext& ctx) -> decltype(ctx.out()) {
413 size_t start = buf.
size();
415 size_t size = buf.
capacity() - start;
416 size_t count = detail::strftime(&buf[start], size, &tm_format[0], &tm);
418 buf.
resize(start + count);
421 if (size >= tm_format.size() * 256) {
428 const size_t MIN_GROWTH = 10;
431 return std::copy(buf.begin(), buf.end(), ctx.out());
438 template <
typename Period> FMT_CONSTEXPR
const char* get_units() {
441 template <> FMT_CONSTEXPR
const char* get_units<std::atto>() {
return "as"; }
442 template <> FMT_CONSTEXPR
const char* get_units<std::femto>() {
return "fs"; }
443 template <> FMT_CONSTEXPR
const char* get_units<std::pico>() {
return "ps"; }
444 template <> FMT_CONSTEXPR
const char* get_units<std::nano>() {
return "ns"; }
445 template <> FMT_CONSTEXPR
const char* get_units<std::micro>() {
return "µs"; }
446 template <> FMT_CONSTEXPR
const char* get_units<std::milli>() {
return "ms"; }
447 template <> FMT_CONSTEXPR
const char* get_units<std::centi>() {
return "cs"; }
448 template <> FMT_CONSTEXPR
const char* get_units<std::deci>() {
return "ds"; }
449 template <> FMT_CONSTEXPR
const char* get_units<std::ratio<1>>() {
return "s"; }
450 template <> FMT_CONSTEXPR
const char* get_units<std::deca>() {
return "das"; }
451 template <> FMT_CONSTEXPR
const char* get_units<std::hecto>() {
return "hs"; }
452 template <> FMT_CONSTEXPR
const char* get_units<std::kilo>() {
return "ks"; }
453 template <> FMT_CONSTEXPR
const char* get_units<std::mega>() {
return "Ms"; }
454 template <> FMT_CONSTEXPR
const char* get_units<std::giga>() {
return "Gs"; }
455 template <> FMT_CONSTEXPR
const char* get_units<std::tera>() {
return "Ts"; }
456 template <> FMT_CONSTEXPR
const char* get_units<std::peta>() {
return "Ps"; }
457 template <> FMT_CONSTEXPR
const char* get_units<std::exa>() {
return "Es"; }
458 template <> FMT_CONSTEXPR
const char* get_units<std::ratio<60>>() {
461 template <> FMT_CONSTEXPR
const char* get_units<std::ratio<3600>>() {
465 enum class numeric_system {
472 template <
typename Char,
typename Handler>
473 FMT_CONSTEXPR
const Char* parse_chrono_format(
const Char* begin,
484 if (begin != ptr) handler.on_text(begin, ptr);
486 if (ptr == end) FMT_THROW(
format_error(
"invalid format"));
490 handler.on_text(ptr - 1, ptr);
493 const Char newline[] = {
'\n'};
494 handler.on_text(newline, newline + 1);
498 const Char tab[] = {
'\t'};
499 handler.on_text(tab, tab + 1);
504 handler.on_abbr_weekday();
507 handler.on_full_weekday();
510 handler.on_dec0_weekday(numeric_system::standard);
513 handler.on_dec1_weekday(numeric_system::standard);
517 handler.on_abbr_month();
520 handler.on_full_month();
524 handler.on_24_hour(numeric_system::standard);
527 handler.on_12_hour(numeric_system::standard);
530 handler.on_minute(numeric_system::standard);
533 handler.on_second(numeric_system::standard);
537 handler.on_datetime(numeric_system::standard);
540 handler.on_loc_date(numeric_system::standard);
543 handler.on_loc_time(numeric_system::standard);
546 handler.on_us_date();
549 handler.on_iso_date();
552 handler.on_12_hour_time();
555 handler.on_24_hour_time();
558 handler.on_iso_time();
564 handler.on_duration_value();
567 handler.on_duration_unit();
570 handler.on_utc_offset();
573 handler.on_tz_name();
577 if (ptr == end) FMT_THROW(
format_error(
"invalid format"));
581 handler.on_datetime(numeric_system::alternative);
584 handler.on_loc_date(numeric_system::alternative);
587 handler.on_loc_time(numeric_system::alternative);
595 if (ptr == end) FMT_THROW(
format_error(
"invalid format"));
599 handler.on_dec0_weekday(numeric_system::alternative);
602 handler.on_dec1_weekday(numeric_system::alternative);
605 handler.on_24_hour(numeric_system::alternative);
608 handler.on_12_hour(numeric_system::alternative);
611 handler.on_minute(numeric_system::alternative);
614 handler.on_second(numeric_system::alternative);
625 if (begin != ptr) handler.on_text(begin, ptr);
630 FMT_NORETURN
void report_no_date() { FMT_THROW(
format_error(
"no date")); }
632 template <
typename Char>
void on_text(
const Char*,
const Char*) {}
633 FMT_NORETURN
void on_abbr_weekday() { report_no_date(); }
634 FMT_NORETURN
void on_full_weekday() { report_no_date(); }
635 FMT_NORETURN
void on_dec0_weekday(numeric_system) { report_no_date(); }
636 FMT_NORETURN
void on_dec1_weekday(numeric_system) { report_no_date(); }
637 FMT_NORETURN
void on_abbr_month() { report_no_date(); }
638 FMT_NORETURN
void on_full_month() { report_no_date(); }
639 void on_24_hour(numeric_system) {}
640 void on_12_hour(numeric_system) {}
641 void on_minute(numeric_system) {}
642 void on_second(numeric_system) {}
643 FMT_NORETURN
void on_datetime(numeric_system) { report_no_date(); }
644 FMT_NORETURN
void on_loc_date(numeric_system) { report_no_date(); }
645 FMT_NORETURN
void on_loc_time(numeric_system) { report_no_date(); }
646 FMT_NORETURN
void on_us_date() { report_no_date(); }
647 FMT_NORETURN
void on_iso_date() { report_no_date(); }
648 void on_12_hour_time() {}
649 void on_24_hour_time() {}
650 void on_iso_time() {}
652 void on_duration_value() {}
653 void on_duration_unit() {}
654 FMT_NORETURN
void on_utc_offset() { report_no_date(); }
655 FMT_NORETURN
void on_tz_name() { report_no_date(); }
658 template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
659 inline bool isnan(T) {
662 template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
663 inline bool isnan(T
value) {
664 return std::isnan(value);
667 template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
668 inline bool isfinite(T) {
671 template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
672 inline bool isfinite(T value) {
673 return std::isfinite(value);
677 template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
678 inline int to_nonnegative_int(T value,
int upper) {
679 FMT_ASSERT(value >= 0 && value <= upper,
"invalid value");
681 return static_cast<int>(value);
683 template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
684 inline int to_nonnegative_int(T value,
int upper) {
686 std::isnan(value) || (value >= 0 && value <= static_cast<T>(upper)),
689 return static_cast<int>(value);
692 template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
693 inline T mod(T x,
int y) {
694 return x %
static_cast<T
>(y);
696 template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
697 inline T mod(T x,
int y) {
698 return std::fmod(x, static_cast<T>(y));
703 template <typename T, bool INTEGRAL = std::is_integral<T>::value>
709 using type =
typename std::make_unsigned<T>::type;
712 #if FMT_SAFE_DURATION_CAST 714 template <
typename To,
typename FromRep,
typename FromPeriod>
715 To fmt_safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from) {
717 To to = safe_duration_cast::safe_duration_cast<To>(from, ec);
718 if (ec) FMT_THROW(
format_error(
"cannot format duration"));
723 template <
typename Rep,
typename Period,
724 FMT_ENABLE_IF(std::is_integral<Rep>::value)>
725 inline std::chrono::duration<Rep, std::milli> get_milliseconds(
726 std::chrono::duration<Rep, Period> d) {
729 #if FMT_SAFE_DURATION_CAST 730 using CommonSecondsType =
731 typename std::common_type<decltype(d), std::chrono::seconds>::type;
732 const auto d_as_common = fmt_safe_duration_cast<CommonSecondsType>(d);
733 const auto d_as_whole_seconds =
734 fmt_safe_duration_cast<std::chrono::seconds>(d_as_common);
736 const auto diff = d_as_common - d_as_whole_seconds;
738 fmt_safe_duration_cast<std::chrono::duration<Rep, std::milli>>(diff);
741 auto s = std::chrono::duration_cast<std::chrono::seconds>(d);
742 return std::chrono::duration_cast<std::chrono::milliseconds>(d -
s);
746 template <
typename Rep,
typename Period,
747 FMT_ENABLE_IF(std::is_floating_point<Rep>::value)>
748 inline std::chrono::duration<Rep, std::milli> get_milliseconds(
749 std::chrono::duration<Rep, Period> d) {
750 using common_type =
typename std::common_type<Rep, std::intmax_t>::type;
751 auto ms = mod(d.count() *
static_cast<common_type
>(Period::num) /
752 static_cast<common_type>(Period::den) * 1000,
754 return std::chrono::duration<Rep, std::milli>(
static_cast<Rep
>(ms));
757 template <
typename Char,
typename Rep,
typename OutputIt>
758 OutputIt format_duration_value(OutputIt out, Rep val,
int precision) {
759 const Char pr_f[] = {
'{',
':',
'.',
'{',
'}',
'f',
'}', 0};
760 if (precision >= 0)
return format_to(out, pr_f, val, precision);
761 const Char fp_f[] = {
'{',
':',
'g',
'}', 0};
762 const Char format[] = {
'{',
'}', 0};
763 return format_to(out, std::is_floating_point<Rep>::value ? fp_f : format,
766 template <
typename Char,
typename OutputIt>
767 OutputIt copy_unit(
string_view unit, OutputIt out, Char) {
768 return std::copy(unit.begin(), unit.end(), out);
771 template <
typename OutputIt>
772 OutputIt copy_unit(
string_view unit, OutputIt out,
wchar_t) {
776 return std::copy(u.c_str(), u.c_str() + u.size(), out);
779 template <
typename Char,
typename Period,
typename OutputIt>
780 OutputIt format_duration_unit(OutputIt out) {
781 if (
const char* unit = get_units<Period>())
783 const Char num_f[] = {
'[',
'{',
'}',
']',
's', 0};
784 if (const_check(Period::den == 1))
return format_to(out, num_f, Period::num);
785 const Char num_def_f[] = {
'[',
'{',
'}',
'/',
'{',
'}',
']',
's', 0};
786 return format_to(out, num_def_f, Period::num, Period::den);
789 template <
typename FormatContext,
typename OutputIt,
typename Rep,
792 FormatContext& context;
797 conditional_t<std::is_integral<Rep>::value &&
sizeof(Rep) <
sizeof(
int),
798 unsigned,
typename make_unsigned_or_unchanged<Rep>::type>;
800 using seconds = std::chrono::duration<rep>;
802 using milliseconds = std::chrono::duration<rep, std::milli>;
805 using char_type =
typename FormatContext::char_type;
808 std::chrono::duration<Rep, Period> d)
811 val(static_cast<rep>(d.count())),
820 #if FMT_SAFE_DURATION_CAST 822 auto tmpval = std::chrono::duration<rep, Period>(val);
823 s = fmt_safe_duration_cast<seconds>(tmpval);
825 s = std::chrono::duration_cast<seconds>(
826 std::chrono::duration<rep, Period>(val));
831 bool handle_nan_inf() {
848 Rep hour()
const {
return static_cast<Rep
>(mod((s.count() / 3600), 24)); }
851 Rep hour =
static_cast<Rep
>(mod((s.count() / 3600), 12));
852 return hour <= 0 ? 12 : hour;
855 Rep minute()
const {
return static_cast<Rep
>(mod((s.count() / 60), 60)); }
856 Rep second()
const {
return static_cast<Rep
>(mod(s.count(), 60)); }
858 std::tm time()
const {
859 auto time = std::tm();
860 time.tm_hour = to_nonnegative_int(hour(), 24);
861 time.tm_min = to_nonnegative_int(minute(), 60);
862 time.tm_sec = to_nonnegative_int(second(), 60);
873 void write(Rep value,
int width) {
875 if (isnan(value))
return write_nan();
876 uint32_or_64_or_128_t<int> n =
877 to_unsigned(to_nonnegative_int(value, max_value<int>()));
878 int num_digits = detail::count_digits(n);
879 if (width > num_digits) out = std::fill_n(out, width - num_digits,
'0');
880 out = format_decimal<char_type>(out, n, num_digits).end;
883 void write_nan() { std::copy_n(
"nan", 3, out); }
884 void write_pinf() { std::copy_n(
"inf", 3, out); }
885 void write_ninf() { std::copy_n(
"-inf", 4, out); }
887 void format_localized(
const tm& time,
char format,
char modifier = 0) {
888 if (isnan(val))
return write_nan();
889 auto locale = context.locale().template get<std::locale>();
890 auto& facet = std::use_facet<std::time_put<char_type>>(locale);
891 std::basic_ostringstream<char_type> os;
893 facet.put(os, os,
' ', &time, format, modifier);
895 std::copy(str.begin(), str.end(), out);
898 void on_text(
const char_type* begin,
const char_type* end) {
899 std::copy(begin, end, out);
903 void on_abbr_weekday() {}
904 void on_full_weekday() {}
905 void on_dec0_weekday(numeric_system) {}
906 void on_dec1_weekday(numeric_system) {}
907 void on_abbr_month() {}
908 void on_full_month() {}
909 void on_datetime(numeric_system) {}
910 void on_loc_date(numeric_system) {}
911 void on_loc_time(numeric_system) {}
913 void on_iso_date() {}
914 void on_utc_offset() {}
917 void on_24_hour(numeric_system ns) {
918 if (handle_nan_inf())
return;
920 if (ns == numeric_system::standard)
return write(hour(), 2);
922 time.tm_hour = to_nonnegative_int(hour(), 24);
923 format_localized(time,
'H',
'O');
926 void on_12_hour(numeric_system ns) {
927 if (handle_nan_inf())
return;
929 if (ns == numeric_system::standard)
return write(hour12(), 2);
931 time.tm_hour = to_nonnegative_int(hour12(), 12);
932 format_localized(time,
'I',
'O');
935 void on_minute(numeric_system ns) {
936 if (handle_nan_inf())
return;
938 if (ns == numeric_system::standard)
return write(minute(), 2);
940 time.tm_min = to_nonnegative_int(minute(), 60);
941 format_localized(time,
'M',
'O');
944 void on_second(numeric_system ns) {
945 if (handle_nan_inf())
return;
947 if (ns == numeric_system::standard) {
949 #if FMT_SAFE_DURATION_CAST 951 using duration_rep = std::chrono::duration<rep, Period>;
952 using duration_Rep = std::chrono::duration<Rep, Period>;
953 auto tmpval = fmt_safe_duration_cast<duration_Rep>(duration_rep{val});
955 auto tmpval = std::chrono::duration<Rep, Period>(val);
957 auto ms = get_milliseconds(tmpval);
958 if (ms != std::chrono::milliseconds(0)) {
960 write(ms.count(), 3);
965 time.tm_sec = to_nonnegative_int(second(), 60);
966 format_localized(time,
'S',
'O');
969 void on_12_hour_time() {
970 if (handle_nan_inf())
return;
971 format_localized(time(),
'r');
974 void on_24_hour_time() {
975 if (handle_nan_inf()) {
989 if (handle_nan_inf())
return;
994 if (handle_nan_inf())
return;
995 format_localized(time(),
'p');
998 void on_duration_value() {
999 if (handle_nan_inf())
return;
1001 out = format_duration_value<char_type>(out, val, precision);
1004 void on_duration_unit() {
1005 out = format_duration_unit<char_type, Period>(out);
1010 template <
typename Rep,
typename Period,
typename Char>
1019 using duration = std::chrono::duration<Rep, Period>;
1021 struct spec_handler {
1026 template <
typename Id> FMT_CONSTEXPR
arg_ref_type make_arg_ref(Id arg_id) {
1040 void on_error(
const char* msg) { FMT_THROW(
format_error(msg)); }
1042 void on_align(align_t
align) { f.specs.align = align; }
1043 void on_width(
int width) { f.specs.width = width; }
1044 void on_precision(
int _precision) { f.precision = _precision; }
1045 void end_precision() {}
1047 template <
typename Id>
void on_dynamic_width(Id arg_id) {
1048 f.width_ref = make_arg_ref(arg_id);
1051 template <
typename Id>
void on_dynamic_precision(Id arg_id) {
1052 f.precision_ref = make_arg_ref(arg_id);
1057 struct parse_range {
1063 auto begin = ctx.
begin(), end = ctx.
end();
1064 if (begin == end || *begin ==
'}')
return {begin, begin};
1065 spec_handler handler{*
this, ctx, format_str};
1066 begin = detail::parse_align(begin, end, handler);
1067 if (begin == end)
return {begin, begin};
1068 begin = detail::parse_width(begin, end, handler);
1069 if (begin == end)
return {begin, begin};
1070 if (*begin ==
'.') {
1071 if (std::is_floating_point<Rep>::value)
1072 begin = detail::parse_precision(begin, end, handler);
1074 handler.on_error(
"precision not allowed for this argument type");
1077 return {begin, end};
1084 -> decltype(ctx.
begin()) {
1085 auto range = do_parse(ctx);
1087 &*range.begin, detail::to_unsigned(range.end - range.begin));
1091 template <
typename FormatContext>
1092 auto format(
const duration& d, FormatContext& ctx) -> decltype(ctx.out()) {
1093 auto begin = format_str.begin(), end = format_str.end();
1097 auto out = std::back_inserter(buf);
1098 detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref,
1100 detail::handle_dynamic_spec<detail::precision_checker>(precision,
1101 precision_ref, ctx);
1102 if (begin == end || *begin ==
'}') {
1103 out = detail::format_duration_value<Char>(out, d.count(), precision);
1104 detail::format_duration_unit<Char, Period>(out);
1108 f.precision = precision;
1109 parse_chrono_format(begin, end, f);
1118 #endif // FMT_CHRONO_H_ Definition: format.h:1174
void reserve(size_t new_capacity)
Increases the buffer capacity to new_capacity.
Definition: format.h:730
Definition: blocking.hpp:208
constexpr iterator end() const FMT_NOEXCEPT
Returns an iterator past the end of the format string range being parsed.
Definition: core.h:582
size_t size() const FMT_NOEXCEPT
Returns the size of this buffer.
Definition: core.h:706
Definition: awaitable.hpp:421
Definition: format.h:1142
constexpr iterator begin() const FMT_NOEXCEPT
Returns an iterator to the beginning of the format string range being parsed.
Definition: core.h:577
std::size_t write(SyncWriteStream &s, const ConstBufferSequence &buffers, CompletionCondition completion_condition, asio::error_code &ec, typename enable_if< is_const_buffer_sequence< ConstBufferSequence >::value >::type *)
Write a certain amount of data to a stream before returning.
Definition: write.hpp:64
FMT_CONSTEXPR int next_arg_id()
Reports an error if using the manual argument indexing; otherwise returns the next argument index and...
Definition: core.h:593
Definition: format.h:2614
Definition: format.h:1130
Definition: format.h:2556
void resize(size_t count)
Resizes the buffer to contain count elements.
Definition: format.h:727
FMT_CONSTEXPR void check_arg_id(int)
Reports an error if using the automatic argument indexing; otherwise switches to the manual indexing...
Definition: core.h:605
T * data() FMT_NOEXCEPT
Returns a pointer to the buffer data.
Definition: core.h:712
size_t capacity() const FMT_NOEXCEPT
Returns the capacity of this buffer.
Definition: core.h:709