|
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");
75 if (F::is_signed && !T::is_signed) {
77 if (fmt::internal::is_negative(from)) {
83 if (F::digits <= T::digits) {
87 if (from > static_cast<From >(T::max())) {
94 if (!F::is_signed && T::is_signed) {
96 if (F::digits < T::digits) {
100 if (from > static_cast<From >(T::max())) {
109 return static_cast<To >(from);
113template < typename To, typename From,
115FMT_CONSTEXPR To lossless_integral_conversion( const From from, int& ec) {
134template < typename To, typename From,
136FMT_CONSTEXPR To safe_float_conversion( const From from, int& ec) {
138 using T = std::numeric_limits<To>;
139 static_assert(std::is_floating_point<From>::value, "From must be floating");
140 static_assert(std::is_floating_point<To>::value, "To must be floating");
143 if (std::isfinite(from)) {
144 if (from >= T::lowest() && from <= T::max()) {
145 return static_cast<To >(from);
153 return static_cast<To >(from);
156template < typename To, typename From,
158FMT_CONSTEXPR To safe_float_conversion( const From from, int& ec) {
160 static_assert(std::is_floating_point<From>::value, "From must be floating");
167template < typename To, typename FromRep, typename FromPeriod,
170To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
172 using From = std::chrono::duration<FromRep, FromPeriod>;
177 : std::ratio_divide<typename From::period, typename To::period> {};
179 static_assert(Factor::num > 0, "num must be positive");
180 static_assert(Factor::den > 0, "den must be positive");
186 using IntermediateRep =
187 typename std::common_type< typename From::rep, typename To::rep,
188 decltype(Factor::num)>::type;
191 IntermediateRep count =
192 lossless_integral_conversion<IntermediateRep>(from.count(), ec);
197 if (Factor::num != 1) {
198 const auto max1 = internal::max_value<IntermediateRep>() / Factor::num;
203 const auto min1 = std::numeric_limits<IntermediateRep>::min() / Factor::num;
208 count *= Factor::num;
212 if (Factor::den != 1) {
213 count /= Factor::den;
216 using ToRep = typename To::rep;
217 const ToRep tocount = lossless_integral_conversion<ToRep>(count, ec);
227template < typename To, typename FromRep, typename FromPeriod,
229 FMT_ENABLE_IF(std::is_floating_point<typename To::rep>::value)>
230To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
232 using From = std::chrono::duration<FromRep, FromPeriod>;
234 if (std::isnan(from.count())) {
236 return To{std::numeric_limits<typename To::rep>::quiet_NaN()};
242 if (std::isinf(from.count())) {
243 return To{from.count()};
249 : std::ratio_divide<typename From::period, typename To::period> {};
251 static_assert(Factor::num > 0, "num must be positive");
252 static_assert(Factor::den > 0, "den must be positive");
258 using IntermediateRep =
259 typename std::common_type< typename From::rep, typename To::rep,
260 decltype(Factor::num)>::type;
264 IntermediateRep count =
265 safe_float_conversion<IntermediateRep>(from.count(), ec);
271 if (Factor::num != 1) {
272 constexpr auto max1 = internal::max_value<IntermediateRep>() /
273 static_cast<IntermediateRep >(Factor::num);
278 constexpr auto min1 = std::numeric_limits<IntermediateRep>::lowest() /
279 static_cast<IntermediateRep >(Factor::num);
284 count *= static_cast<IntermediateRep >(Factor::num);
288 if (Factor::den != 1) {
289 using common_t = typename std::common_type<IntermediateRep, intmax_t>::type;
290 count /= static_cast<common_t >(Factor::den);
294 using ToRep = typename To::rep;
296 const ToRep tocount = safe_float_conversion<ToRep>(count, ec);
322 dispatcher(std::time_t t) : time_(t) {}
325 using namespace fmt::internal;
326 return handle(localtime_r(&time_, &tm_));
329 bool handle(std::tm* tm) { return tm != nullptr; }
332 using namespace fmt::internal;
333 return fallback(localtime_s(&tm_, &time_));
336 bool fallback( int res) { return res == 0; }
340 using namespace fmt::internal;
341 std::tm* tm = std::localtime(&time_);
343 return tm != nullptr;
359 dispatcher(std::time_t t) : time_(t) {}
362 using namespace fmt::internal;
363 return handle(gmtime_r(&time_, &tm_));
366 bool handle(std::tm* tm) { return tm != nullptr; }
369 using namespace fmt::internal;
370 return fallback(gmtime_s(&tm_, &time_));
373 bool fallback( int res) { return res == 0; }
377 std::tm* tm = std::gmtime(&time_);
379 return tm != nullptr;
391 const std::tm* time) {
392 return std::strftime(str, count, format, time);
395inline std::size_t strftime( wchar_t* str, std::size_t count,
396 const wchar_t* format, const std::tm* time) {
397 return std::wcsftime(str, count, format, time);
401template < typename Char> struct formatter<std::tm, Char> {
402 template < typename ParseContext>
403 auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
404 auto it = ctx.begin();
405 if (it != ctx.end() && *it == ':') ++it;
407 while (end != ctx.end() && *end != '}') ++end;
409 tm_format.append(it, end);
410 tm_format.push_back( '\0');
414 template < typename FormatContext>
415 auto format( const std::tm& tm, FormatContext& ctx) -> decltype(ctx.out()) {
417 std::size_t start = buf. size();
419 std::size_t size = buf. capacity() - start;
423 buf. resize(start + count);
426 if (size >= tm_format.size() * 256) {
433 const std::size_t MIN_GROWTH = 10;
436 return std::copy(buf. begin(), buf. end(), ctx.out());
454template <> FMT_CONSTEXPR const char* get_units<std::ratio<1>>() { return "s"; }
477template < typename Char, typename Handler>
489 if (begin != ptr) handler.on_text(begin, ptr);
495 handler.on_text( ptr - 1, ptr);
498 const char newline[] = "\n";
499 handler.on_text(newline, newline + 1);
503 const char tab[] = "\t";
504 handler.on_text(tab, tab + 1);
509 handler.on_abbr_weekday();
512 handler.on_full_weekday();
522 handler.on_abbr_month();
525 handler.on_full_month();
551 handler.on_us_date();
554 handler.on_iso_date();
557 handler.on_12_hour_time();
560 handler.on_24_hour_time();
563 handler.on_iso_time();
569 handler.on_duration_value();
572 handler.on_duration_unit();
575 handler.on_utc_offset();
578 handler.on_tz_name();
630 if (begin != ptr) handler.on_text(begin, ptr);
637 template < typename Char> void on_text( const Char*, const Char*) {}
663template < typename T, FMT_ENABLE_IF(std::is_ integral<T>::value)>
667template < typename T, FMT_ENABLE_IF(std::is_ floating_po int<T>::value)>
668inline bool isnan(T value) {
669 return std::isnan(value);
672template < typename T, FMT_ENABLE_IF(std::is_ integral<T>::value)>
676template < typename T, FMT_ENABLE_IF(std::is_ floating_po int<T>::value)>
678 return std::isfinite(value);
682template < typename T, FMT_ENABLE_IF(std::is_ integral<T>::value)>
686 return static_cast<int>( value);
688template < typename T, FMT_ENABLE_IF(!std::is_ integral<T>::value)>
691 std::isnan(value) || (value >= 0 && value <= static_cast<T >(upper)),
694 return static_cast<int>(value);
697template < typename T, FMT_ENABLE_IF(std::is_ integral<T>::value)>
699 return x % static_cast<T >(y);
701template < typename T, FMT_ENABLE_IF(std::is_ floating_po int<T>::value)>
702inline T mod(T x, int y) {
703 return std::fmod(x, static_cast<T >(y));
708template <typename T, bool INTEGRAL = std::is_integral<T>::value>
714 using type = typename std::make_unsigned<T>::type;
717#if FMT_SAFE_DURATION_CAST
719template < typename To, typename FromRep, typename FromPeriod>
720To fmt_safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from) {
722 To to = safe_duration_cast::safe_duration_cast<To>(from, ec);
728template < typename Rep, typename Period,
731 std::chrono::duration<Rep, Period> d) {
734#if FMT_SAFE_DURATION_CAST
735 using CommonSecondsType =
736 typename std::common_type< decltype(d), std::chrono::seconds> ::type;
737 const auto d_as_common = fmt_safe_duration_cast<CommonSecondsType>(d);
738 const auto d_as_whole_seconds =
739 fmt_safe_duration_cast<std::chrono::seconds>(d_as_common);
741 const auto diff = d_as_common - d_as_whole_seconds;
743 fmt_safe_duration_cast<std::chrono::duration<Rep, std::milli>>(diff);
746 auto s = std::chrono::duration_cast<std::chrono::seconds>(d);
747 return std::chrono::duration_cast<std::chrono::milliseconds>(d - s);
751template < typename Rep, typename Period,
754 std::chrono::duration<Rep, Period> d) {
755 using common_type = typename std::common_type<Rep, std::intmax_t>::type;
756 auto ms = mod(d.count() * static_cast<common_type >(Period::num) /
757 static_cast<common_type >(Period::den) * 1000,
759 return std::chrono::duration<Rep, std::milli>( static_cast<Rep >(ms));
762template < typename Rep, typename OutputIt>
764 if (precision >= 0) return format_to(out, "{:.{}f}", val, precision);
765 return format_to(out, std::is_floating_point<Rep>::value ? "{:g}" : "{}",
769template < typename Period, typename OutputIt>
771 if ( const char* unit = get_units<Period>()) return format_to(out, "{}", unit);
772 if (Period::den == 1) return format_to(out, "[{}]s", Period::num);
773 return format_to(out, "[{}/{}]s", Period::num, Period::den);
776template < typename FormatContext, typename OutputIt, typename Rep,
795 std::chrono::duration<Rep, Period> d)
798 val(static_cast< rep>(d.count())),
807#if FMT_SAFE_DURATION_CAST
809 auto tmpval = std::chrono::duration<rep, Period>( val);
810 s = fmt_safe_duration_cast<seconds>(tmpval);
812 s = std::chrono::duration_cast<seconds>(
813 std::chrono::duration<rep, Period>( val));
835 Rep hour() const { return static_cast<Rep >( mod(( s.count() / 3600), 24)); }
838 Rep hour = static_cast<Rep >( mod(( s.count() / 3600), 12));
842 Rep minute() const { return static_cast<Rep >( mod(( s.count() / 60), 60)); }
843 Rep second() const { return static_cast<Rep >( mod( s.count(), 60)); }
846 auto time = std::tm();
866 if (width > num_digits) out = std::fill_n( out, width - num_digits, '0');
867 out = format_decimal<char_type>( out, n, num_digits);
876 auto locale = context.locale().template get<std::locale>();
877 auto& facet = std::use_facet<std::time_put<char_type>>(locale);
878 std::basic_ostringstream<char_type> os;
882 std::copy(str.begin(), str.end(), out);
886 std::copy(begin, end, out);
936#if FMT_SAFE_DURATION_CAST
938 using duration_rep = std::chrono::duration<rep, Period>;
939 using duration_Rep = std::chrono::duration<Rep, Period>;
940 auto tmpval = fmt_safe_duration_cast<duration_Rep>(duration_rep{ val});
942 auto tmpval = std::chrono::duration<Rep, Period>( val);
945 if (ms != std::chrono::milliseconds(0)) {
947 write(ms.count(), 3);
996template < typename Rep, typename Period, typename Char>
997struct formatter<std::chrono::duration<Rep, Period>, Char> {
1007 struct spec_handler {
1027 void on_fill(Char fill) { f.specs.fill[0] = fill; }
1034 f.width_ref = make_arg_ref(arg_id);
1038 f.precision_ref = make_arg_ref(arg_id);
1043 struct parse_range {
1049 auto begin = ctx. begin(), end = ctx. end();
1050 if (begin == end || *begin == '}') return {begin, begin};
1051 spec_handler handler{* this, ctx, format_str};
1053 if (begin == end) return {begin, begin};
1055 if (begin == end) return {begin, begin};
1056 if (*begin == '.') {
1057 if (std::is_floating_point<Rep>::value)
1060 handler.on_error( "precision not allowed for this argument type");
1063 return {begin, end};
1070 -> decltype(ctx.begin()) {
1071 auto range = do_parse(ctx);
1077 template < typename FormatContext>
1079 auto begin = format_str. begin(), end = format_str. end();
1083 auto out = std::back_inserter(buf);
1086 internal::handle_dynamic_spec<internal::width_checker>(specs. width,
1088 internal::handle_dynamic_spec<internal::precision_checker>(
1089 precision, precision_ref, ctx);
1090 if (begin == end || *begin == '}') {
1092 internal::format_chrono_duration_unit<Period>(out);
1097 parse_chrono_format(begin, end, f);
1099 w.write(buf. data(), buf. size(), specs);
std::tm localtime(std::time_t time)
std::tm gmtime(std::time_t time)
FMT_CONSTEXPR iterator begin() const FMT_NOEXCEPT
FMT_CONSTEXPR void check_arg_id(int)
FMT_CONSTEXPR iterator end() const FMT_NOEXCEPT
typename basic_string_view< Char >::iterator iterator
FMT_CONSTEXPR int next_arg_id()
FMT_CONSTEXPR iterator end() const
FMT_CONSTEXPR iterator begin() const
void reserve(std::size_t new_capacity)
void resize(std::size_t new_size)
std::size_t size() const FMT_NOEXCEPT
std::size_t capacity() const FMT_NOEXCEPT
std::basic_string< Char > format(const text_style &ts, const S &format_str, const Args &... args)
OutputIt format_to(OutputIt out, const CompiledFormat &cf, const Args &... args)
#define FMT_ASSERT(condition, message)
#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 >()
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)
FMT_CONSTEXPR const char * get_units< std::milli >()
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)
FMT_CONSTEXPR const char * get_units< std::hecto >()
FMT_CONSTEXPR const char * get_units< std::pico >()
static OutputIt format_chrono_duration_unit(OutputIt out)
FMT_CONSTEXPR const char * get_units< std::deci >()
std::chrono::duration< Rep, std::milli > get_milliseconds(std::chrono::duration< Rep, Period > d)
FMT_CONSTEXPR const char * get_units< std::atto >()
FMT_CONSTEXPR const char * get_units< std::deca >()
conditional_t< std::numeric_limits< T >::digits<=32, uint32_t, conditional_t< std::numeric_limits< T >::digits<=64, uint64_t, uint128_t > > uint32_or_64_or_128_t
std::size_t strftime(char *str, std::size_t count, const char *format, const std::tm *time)
int to_nonnegative_int(T value, int upper)
OutputIt format_chrono_duration_value(OutputIt out, Rep val, int precision)
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
|