|
Loading...
Searching...
No Matches
Go to the documentation of this file.
22#ifndef FMT_SAFE_DURATION_CAST
23# define FMT_SAFE_DURATION_CAST 1
25#if FMT_SAFE_DURATION_CAST
33namespace safe_duration_cast {
35template < typename To, typename From,
37 std::numeric_limits<From>::is_signed ==
38 std::numeric_limits<To>::is_signed)>
39FMT_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);
64template < typename To, typename From,
66 std::numeric_limits<From>::is_signed !=
67 std::numeric_limits<To>::is_signed)>
68FMT_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");
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);
97template < typename To, typename From,
99FMT_CONSTEXPR To lossless_integral_conversion( const From from, int& ec) {
118template < typename To, typename From,
120FMT_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);
140template < typename To, typename From,
142FMT_CONSTEXPR To safe_float_conversion( const From from, int& ec) {
144 static_assert(std::is_floating_point<From>::value, "From must be floating");
151template < typename To, typename FromRep, typename FromPeriod,
154To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
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);
180 const auto max1 = detail::max_value<IntermediateRep>() / Factor::num;
186 (std::numeric_limits<IntermediateRep>::min)() / Factor::num;
191 count *= Factor::num;
195 auto tocount = lossless_integral_conversion<typename To::rep>(count, ec);
196 return ec ? To() : To(tocount);
202template < typename To, typename FromRep, typename FromPeriod,
204 FMT_ENABLE_IF(std::is_floating_point<typename To::rep>::value)>
205To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
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);
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;
329 std::chrono::time_point<std::chrono::system_clock> time_point) {
330 return localtime(std::chrono::system_clock::to_time_t(time_point));
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;
370 std::chrono::time_point<std::chrono::system_clock> time_point) {
371 return gmtime(std::chrono::system_clock::to_time_t(time_point));
376 const std::tm* time) {
381 const std::tm* time) {
386template < typename Char>
387struct 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()) {
397template < typename Char> struct formatter<std::tm, Char> {
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;
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;
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());
449template <> FMT_CONSTEXPR const char* get_units<std::ratio<1>>() { return "s"; }
472template < typename Char, typename Handler>
484 if (begin != ptr) handler.on_text(begin, ptr);
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();
517 handler.on_abbr_month();
520 handler.on_full_month();
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();
625 if (begin != ptr) handler.on_text(begin, ptr);
632 template < typename Char> void on_text( const Char*, const Char*) {}
658template < typename T, FMT_ENABLE_IF(std::is_ integral<T>::value)>
662template < typename T, FMT_ENABLE_IF(std::is_ floating_po int<T>::value)>
663inline bool isnan(T value) {
664 return std::isnan(value);
667template < typename T, FMT_ENABLE_IF(std::is_ integral<T>::value)>
671template < typename T, FMT_ENABLE_IF(std::is_ floating_po int<T>::value)>
673 return std::isfinite(value);
677template < typename T, FMT_ENABLE_IF(std::is_ integral<T>::value)>
681 return static_cast<int>( value);
683template < typename T, FMT_ENABLE_IF(!std::is_ integral<T>::value)>
686 std::isnan(value) || (value >= 0 && value <= static_cast<T >(upper)),
689 return static_cast<int>(value);
692template < typename T, FMT_ENABLE_IF(std::is_ integral<T>::value)>
694 return x % static_cast<T >(y);
696template < typename T, FMT_ENABLE_IF(std::is_ floating_po int<T>::value)>
697inline T mod(T x, int y) {
698 return std::fmod(x, static_cast<T >(y));
703template <typename T, bool INTEGRAL = std::is_integral<T>::value>
709 using type = typename std::make_unsigned<T>::type;
712#if FMT_SAFE_DURATION_CAST
714template < typename To, typename FromRep, typename FromPeriod>
715To fmt_safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from) {
717 To to = safe_duration_cast::safe_duration_cast<To>(from, ec);
723template < typename Rep, typename Period,
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);
746template < typename Rep, typename Period,
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));
757template < typename Char, typename Rep, typename OutputIt>
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,
766template < typename Char, typename OutputIt>
768 return std::copy(unit. begin(), unit. end(), out);
771template < typename OutputIt>
779template < typename Char, typename Period, typename OutputIt>
781 if ( const char* unit = get_units<Period>())
783 const Char num_f[] = { '[', '{', '}', ']', 's', 0};
785 const Char num_def_f[] = { '[', '{', '}', '/', '{', '}', ']', 's', 0};
786 return format_to(out, num_def_f, Period::num, Period::den);
789template < typename FormatContext, typename OutputIt, typename Rep,
808 std::chrono::duration<Rep, Period> d)
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));
848 Rep hour() const { return static_cast<Rep >( mod(( s.count() / 3600), 24)); }
851 Rep hour = static_cast<Rep >( mod(( s.count() / 3600), 12));
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)); }
859 auto time = std::tm();
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;
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);
899 std::copy(begin, end, out);
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);
958 if (ms != std::chrono::milliseconds(0)) {
960 write(ms.count(), 3);
1005 out = format_duration_unit<char_type, Period>( out);
1010template < typename Rep, typename Period, typename Char>
1021 struct spec_handler {
1048 f.width_ref = make_arg_ref(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};
1067 if (begin == end) return {begin, begin};
1069 if (begin == end) return {begin, begin};
1070 if (*begin == '.') {
1071 if (std::is_floating_point<Rep>::value)
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);
1091 template < typename FormatContext>
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);
1109 parse_chrono_format(begin, end, f);
std::tm localtime(std::time_t time)
std::tm gmtime(std::time_t time)
constexpr iterator end() const FMT_NOEXCEPT
FMT_CONSTEXPR void check_arg_id(int)
constexpr iterator begin() const FMT_NOEXCEPT
typename basic_string_view< Char >::iterator iterator
FMT_CONSTEXPR int next_arg_id()
void resize(size_t count)
void reserve(size_t new_capacity)
constexpr iterator end() const
constexpr iterator begin() const
size_t size() const FMT_NOEXCEPT
size_t capacity() const FMT_NOEXCEPT
const wchar_t * c_str() const
auto format_to(OutputIt out, const text_style &ts, const S &format_str, Args &&... args) -> typename std::enable_if< enable, OutputIt >::type
std::basic_string< Char > format(const text_style &ts, const S &format_str, const Args &... args)
#define FMT_ASSERT(condition, message)
basic_string_view< char > string_view
#define FMT_BEGIN_NAMESPACE
#define FMT_ENABLE_IF(...)
typename std::conditional< B, T, F >::type conditional_t
#define FMT_END_NAMESPACE
FMT_CONSTEXPR const char * get_units< std::femto >()
FMT_CONSTEXPR const Char * parse_align(const Char *begin, const Char *end, Handler &&handler)
FMT_CONSTEXPR const char * get_units< std::tera >()
FMT_CONSTEXPR const char * get_units< std::kilo >()
FMT_CONSTEXPR const Char * parse_precision(const Char *begin, const Char *end, Handler &&handler)
FMT_CONSTEXPR const char * get_units< std::peta >()
FMT_CONSTEXPR const char * get_units< std::exa >()
OutputIt format_duration_value(OutputIt out, Rep val, int precision)
FMT_CONSTEXPR const Char * parse_chrono_format(const Char *begin, const Char *end, Handler &&handler)
FMT_CONSTEXPR const char * get_units< std::giga >()
FMT_CONSTEXPR std::make_unsigned< Int >::type to_unsigned(Int value)
OutputIt copy_unit(string_view unit, OutputIt out, Char)
conditional_t< num_bits< T >()<=32 &&!FMT_REDUCE_INT_INSTANTIATIONS, uint32_t, conditional_t< num_bits< T >()<=64, uint64_t, uint128_t > > uint32_or_64_or_128_t
FMT_CONSTEXPR const char * get_units< std::milli >()
size_t strftime(char *str, size_t count, const char *format, const std::tm *time)
FMT_CONSTEXPR const char * get_units< std::nano >()
int count_digits(uint64_t n)
FMT_CONSTEXPR const char * get_units< std::mega >()
FMT_CONSTEXPR const Char * parse_width(const Char *begin, const Char *end, Handler &&handler)
OutputIt write(OutputIt out, basic_string_view< StrChar > s, const basic_format_specs< Char > &specs)
FMT_CONSTEXPR const char * get_units< std::hecto >()
FMT_CONSTEXPR const char * get_units< std::pico >()
FMT_CONSTEXPR const char * get_units< std::deci >()
std::chrono::duration< Rep, std::milli > get_milliseconds(std::chrono::duration< Rep, Period > d)
OutputIt format_duration_unit(OutputIt out)
FMT_CONSTEXPR const char * get_units< std::atto >()
FMT_CONSTEXPR const char * get_units< std::deca >()
constexpr T const_check(T value)
int to_nonnegative_int(T value, int upper)
FMT_CONSTEXPR const char * get_units()
FMT_CONSTEXPR const char * get_units< std::micro >()
FMT_CONSTEXPR const char * get_units< std::centi >()
typename std::make_unsigned< T >::type type
|