diff --git a/include/date/date.h b/include/date/date.h index 6d1ff7c..4bc5b9f 100644 --- a/include/date/date.h +++ b/include/date/date.h @@ -4408,6 +4408,550 @@ operator<<(std::basic_ostream& os, const local_time& ut return (os << sys_time{ut.time_since_epoch()}); } +namespace detail +{ + +template +class string_literal; + +template +inline +CONSTCD14 +string_literal::type, + N1 + N2 - 1> +operator+(const string_literal& x, const string_literal& y) NOEXCEPT; + +template +class string_literal +{ + CharT p_[N]; + + CONSTCD11 string_literal() NOEXCEPT + : p_{} + {} + +public: + using const_iterator = const CharT*; + + string_literal(string_literal const&) = default; + string_literal& operator=(string_literal const&) = delete; + + template ::type> + CONSTCD11 string_literal(CharT c) NOEXCEPT + : p_{c} + { + } + + template ::type> + CONSTCD11 string_literal(CharT c1, CharT c2) NOEXCEPT + : p_{c1, c2} + { + } + + template ::type> + CONSTCD11 string_literal(CharT c1, CharT c2, CharT c3) NOEXCEPT + : p_{c1, c2, c3} + { + } + + CONSTCD14 string_literal(const CharT(&a)[N]) NOEXCEPT + : p_{} + { + for (std::size_t i = 0; i < N; ++i) + p_[i] = a[i]; + } + + template ::type> + CONSTCD14 string_literal(const char(&a)[N]) NOEXCEPT + : p_{} + { + for (std::size_t i = 0; i < N; ++i) + p_[i] = a[i]; + } + + template ::value>::type> + CONSTCD14 string_literal(string_literal const& a) NOEXCEPT + : p_{} + { + for (std::size_t i = 0; i < N; ++i) + p_[i] = a[i]; + } + + CONSTCD11 const CharT* data() const NOEXCEPT {return p_;} + CONSTCD11 std::size_t size() const NOEXCEPT {return N-1;} + + CONSTCD11 const_iterator begin() const NOEXCEPT {return p_;} + CONSTCD11 const_iterator end() const NOEXCEPT {return p_ + N-1;} + + CONSTCD11 CharT const& operator[](std::size_t n) const NOEXCEPT + { + return p_[n]; + } + + template + friend + std::basic_ostream& + operator<<(std::basic_ostream& os, const string_literal& s) + { + return os << s.p_; + } + + template + friend + CONSTCD14 + string_literal::type, + N1 + N2 - 1> + operator+(const string_literal& x, const string_literal& y) NOEXCEPT; +}; + +template +CONSTCD11 +inline +string_literal +operator+(const string_literal& x, const string_literal& y) NOEXCEPT +{ + return string_literal(x[0], y[0]); +} + +template +CONSTCD11 +inline +string_literal +operator+(const string_literal& x, const string_literal& y) NOEXCEPT +{ + return string_literal(x[0], x[1], y[0]); +} + +template +CONSTCD14 +inline +string_literal::type, + N1 + N2 - 1> +operator+(const string_literal& x, const string_literal& y) NOEXCEPT +{ + using CT = typename std::conditional::type; + + string_literal r; + std::size_t i = 0; + for (; i < N1-1; ++i) + r.p_[i] = CT(x.p_[i]); + for (std::size_t j = 0; j < N2; ++j, ++i) + r.p_[i] = CT(y.p_[j]); + + return r; +} + + +template +inline +std::basic_string +operator+(std::basic_string x, const string_literal& y) +{ + x.append(y.data(), y.size()); + return x; +} + +#if __cplusplus >= 201402 && (!defined(__EDG_VERSION__) || __EDG_VERSION__ > 411) \ + && (!defined(__SUNPRO_CC) || __SUNPRO_CC > 0x5150) + +template {} || + std::is_same{} || + std::is_same{} || + std::is_same{}>> +CONSTCD14 +inline +string_literal +msl(CharT c) NOEXCEPT +{ + return string_literal{c}; +} + +CONSTCD14 +inline +std::size_t +to_string_len(std::intmax_t i) +{ + std::size_t r = 0; + do + { + i /= 10; + ++r; + } while (i > 0); + return r; +} + +template +CONSTCD14 +inline +std::enable_if_t +< + N < 10, + string_literal +> +msl() NOEXCEPT +{ + return msl(char(N % 10 + '0')); +} + +template +CONSTCD14 +inline +std::enable_if_t +< + 10 <= N, + string_literal +> +msl() NOEXCEPT +{ + return msl() + msl(char(N % 10 + '0')); +} + +template +CONSTCD14 +inline +std::enable_if_t +< + std::ratio::type::den != 1, + string_literal::type::num) + + to_string_len(std::ratio::type::den) + 4> +> +msl(std::ratio) NOEXCEPT +{ + using R = typename std::ratio::type; + return msl(CharT{'['}) + msl() + msl(CharT{'/'}) + + msl() + msl(CharT{']'}); +} + +template +CONSTCD14 +inline +std::enable_if_t +< + std::ratio::type::den == 1, + string_literal::type::num) + 3> +> +msl(std::ratio) NOEXCEPT +{ + using R = typename std::ratio::type; + return msl(CharT{'['}) + msl() + msl(CharT{']'}); +} + + +#else // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411) + +inline +std::string +to_string(std::uint64_t x) +{ + return std::to_string(x); +} + +template +inline +std::basic_string +to_string(std::uint64_t x) +{ + auto y = std::to_string(x); + return std::basic_string(y.begin(), y.end()); +} + +template +inline +typename std::enable_if +< + std::ratio::type::den != 1, + std::basic_string +>::type +msl(std::ratio) +{ + using R = typename std::ratio::type; + return std::basic_string(1, '[') + to_string(R::num) + CharT{'/'} + + to_string(R::den) + CharT{']'}; +} + +template +inline +typename std::enable_if +< + std::ratio::type::den == 1, + std::basic_string +>::type +msl(std::ratio) +{ + using R = typename std::ratio::type; + return std::basic_string(1, '[') + to_string(R::num) + CharT{']'}; +} + +#endif // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411) + +template +CONSTCD11 +inline +string_literal +msl(std::atto) NOEXCEPT +{ + return string_literal{'a'}; +} + +template +CONSTCD11 +inline +string_literal +msl(std::femto) NOEXCEPT +{ + return string_literal{'f'}; +} + +template +CONSTCD11 +inline +string_literal +msl(std::pico) NOEXCEPT +{ + return string_literal{'p'}; +} + +template +CONSTCD11 +inline +string_literal +msl(std::nano) NOEXCEPT +{ + return string_literal{'n'}; +} + +template +CONSTCD11 +inline +typename std::enable_if +< + std::is_same::value, + string_literal +>::type +msl(std::micro) NOEXCEPT +{ + return string_literal{'\xC2', '\xB5'}; +} + +template +CONSTCD11 +inline +typename std::enable_if +< + !std::is_same::value, + string_literal +>::type +msl(std::micro) NOEXCEPT +{ + return string_literal{CharT{static_cast('\xB5')}}; +} + +template +CONSTCD11 +inline +string_literal +msl(std::milli) NOEXCEPT +{ + return string_literal{'m'}; +} + +template +CONSTCD11 +inline +string_literal +msl(std::centi) NOEXCEPT +{ + return string_literal{'c'}; +} + +template +CONSTCD11 +inline +string_literal +msl(std::deca) NOEXCEPT +{ + return string_literal{'d', 'a'}; +} + +template +CONSTCD11 +inline +string_literal +msl(std::deci) NOEXCEPT +{ + return string_literal{'d'}; +} + +template +CONSTCD11 +inline +string_literal +msl(std::hecto) NOEXCEPT +{ + return string_literal{'h'}; +} + +template +CONSTCD11 +inline +string_literal +msl(std::kilo) NOEXCEPT +{ + return string_literal{'k'}; +} + +template +CONSTCD11 +inline +string_literal +msl(std::mega) NOEXCEPT +{ + return string_literal{'M'}; +} + +template +CONSTCD11 +inline +string_literal +msl(std::giga) NOEXCEPT +{ + return string_literal{'G'}; +} + +template +CONSTCD11 +inline +string_literal +msl(std::tera) NOEXCEPT +{ + return string_literal{'T'}; +} + +template +CONSTCD11 +inline +string_literal +msl(std::peta) NOEXCEPT +{ + return string_literal{'P'}; +} + +template +CONSTCD11 +inline +string_literal +msl(std::exa) NOEXCEPT +{ + return string_literal{'E'}; +} + +template +CONSTCD11 +inline +auto +get_units(Period p) + -> decltype(msl(p) + string_literal{'s'}) +{ + return msl(p) + string_literal{'s'}; +} + +template +CONSTCD11 +inline +string_literal +get_units(std::ratio<1>) +{ + return string_literal{'s'}; +} + +template +CONSTCD11 +inline +string_literal +get_units(std::ratio<3600>) +{ + return string_literal{'h'}; +} + +template +CONSTCD11 +inline +string_literal +get_units(std::ratio<60>) +{ + return string_literal{'m', 'i', 'n'}; +} + +template +CONSTCD11 +inline +string_literal +get_units(std::ratio<86400>) +{ + return string_literal{'d'}; +} + +template > +struct make_string; + +template <> +struct make_string +{ + template + static + std::string + from(Rep n) + { + return std::to_string(n); + } +}; + +template +struct make_string +{ + template + static + std::basic_string + from(Rep n) + { + auto s = std::to_string(n); + return std::basic_string(s.begin(), s.end()); + } +}; + +template <> +struct make_string +{ + template + static + std::wstring + from(Rep n) + { + return std::to_wstring(n); + } +}; + +template +struct make_string +{ + template + static + std::basic_string + from(Rep n) + { + auto s = std::to_wstring(n); + return std::basic_string(s.begin(), s.end()); + } +}; + +} // namespace detail + // to_stream CONSTDATA year nanyear{-32768}; @@ -5181,6 +5725,30 @@ to_stream(std::basic_ostream& os, const CharT* fmt, else os << *fmt; break; + case 'Q': + case 'q': + if (command) + { + if (modified == CharT{}) + { + if (!fds.has_tod) + os.setstate(std::ios::failbit); + auto d = fds.tod.to_duration(); + if (*fmt == 'q') + os << get_units(typename decltype(d)::period::type{}); + else + os << d.count(); + } + else + { + os << CharT{'%'} << modified << *fmt; + } + modified = CharT{}; + command = nullptr; + } + else + os << *fmt; + break; case 'r': if (command) { @@ -7771,550 +8339,6 @@ parse(const CharT* format, Parsable& tp, // duration streaming -namespace detail -{ - -template -class string_literal; - -template -inline -CONSTCD14 -string_literal::type, - N1 + N2 - 1> -operator+(const string_literal& x, const string_literal& y) NOEXCEPT; - -template -class string_literal -{ - CharT p_[N]; - - CONSTCD11 string_literal() NOEXCEPT - : p_{} - {} - -public: - using const_iterator = const CharT*; - - string_literal(string_literal const&) = default; - string_literal& operator=(string_literal const&) = delete; - - template ::type> - CONSTCD11 string_literal(CharT c) NOEXCEPT - : p_{c} - { - } - - template ::type> - CONSTCD11 string_literal(CharT c1, CharT c2) NOEXCEPT - : p_{c1, c2} - { - } - - template ::type> - CONSTCD11 string_literal(CharT c1, CharT c2, CharT c3) NOEXCEPT - : p_{c1, c2, c3} - { - } - - CONSTCD14 string_literal(const CharT(&a)[N]) NOEXCEPT - : p_{} - { - for (std::size_t i = 0; i < N; ++i) - p_[i] = a[i]; - } - - template ::type> - CONSTCD14 string_literal(const char(&a)[N]) NOEXCEPT - : p_{} - { - for (std::size_t i = 0; i < N; ++i) - p_[i] = a[i]; - } - - template ::value>::type> - CONSTCD14 string_literal(string_literal const& a) NOEXCEPT - : p_{} - { - for (std::size_t i = 0; i < N; ++i) - p_[i] = a[i]; - } - - CONSTCD11 const CharT* data() const NOEXCEPT {return p_;} - CONSTCD11 std::size_t size() const NOEXCEPT {return N-1;} - - CONSTCD11 const_iterator begin() const NOEXCEPT {return p_;} - CONSTCD11 const_iterator end() const NOEXCEPT {return p_ + N-1;} - - CONSTCD11 CharT const& operator[](std::size_t n) const NOEXCEPT - { - return p_[n]; - } - - template - friend - std::basic_ostream& - operator<<(std::basic_ostream& os, const string_literal& s) - { - return os << s.p_; - } - - template - friend - CONSTCD14 - string_literal::type, - N1 + N2 - 1> - operator+(const string_literal& x, const string_literal& y) NOEXCEPT; -}; - -template -CONSTCD11 -inline -string_literal -operator+(const string_literal& x, const string_literal& y) NOEXCEPT -{ - return string_literal(x[0], y[0]); -} - -template -CONSTCD11 -inline -string_literal -operator+(const string_literal& x, const string_literal& y) NOEXCEPT -{ - return string_literal(x[0], x[1], y[0]); -} - -template -CONSTCD14 -inline -string_literal::type, - N1 + N2 - 1> -operator+(const string_literal& x, const string_literal& y) NOEXCEPT -{ - using CT = typename std::conditional::type; - - string_literal r; - std::size_t i = 0; - for (; i < N1-1; ++i) - r.p_[i] = CT(x.p_[i]); - for (std::size_t j = 0; j < N2; ++j, ++i) - r.p_[i] = CT(y.p_[j]); - - return r; -} - - -template -inline -std::basic_string -operator+(std::basic_string x, const string_literal& y) -{ - x.append(y.data(), y.size()); - return x; -} - -#if __cplusplus >= 201402 && (!defined(__EDG_VERSION__) || __EDG_VERSION__ > 411) \ - && (!defined(__SUNPRO_CC) || __SUNPRO_CC > 0x5150) - -template {} || - std::is_same{} || - std::is_same{} || - std::is_same{}>> -CONSTCD14 -inline -string_literal -msl(CharT c) NOEXCEPT -{ - return string_literal{c}; -} - -CONSTCD14 -inline -std::size_t -to_string_len(std::intmax_t i) -{ - std::size_t r = 0; - do - { - i /= 10; - ++r; - } while (i > 0); - return r; -} - -template -CONSTCD14 -inline -std::enable_if_t -< - N < 10, - string_literal -> -msl() NOEXCEPT -{ - return msl(char(N % 10 + '0')); -} - -template -CONSTCD14 -inline -std::enable_if_t -< - 10 <= N, - string_literal -> -msl() NOEXCEPT -{ - return msl() + msl(char(N % 10 + '0')); -} - -template -CONSTCD14 -inline -std::enable_if_t -< - std::ratio::type::den != 1, - string_literal::type::num) + - to_string_len(std::ratio::type::den) + 4> -> -msl(std::ratio) NOEXCEPT -{ - using R = typename std::ratio::type; - return msl(CharT{'['}) + msl() + msl(CharT{'/'}) + - msl() + msl(CharT{']'}); -} - -template -CONSTCD14 -inline -std::enable_if_t -< - std::ratio::type::den == 1, - string_literal::type::num) + 3> -> -msl(std::ratio) NOEXCEPT -{ - using R = typename std::ratio::type; - return msl(CharT{'['}) + msl() + msl(CharT{']'}); -} - - -#else // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411) - -inline -std::string -to_string(std::uint64_t x) -{ - return std::to_string(x); -} - -template -inline -std::basic_string -to_string(std::uint64_t x) -{ - auto y = std::to_string(x); - return std::basic_string(y.begin(), y.end()); -} - -template -inline -typename std::enable_if -< - std::ratio::type::den != 1, - std::basic_string ->::type -msl(std::ratio) -{ - using R = typename std::ratio::type; - return std::basic_string(1, '[') + to_string(R::num) + CharT{'/'} + - to_string(R::den) + CharT{']'}; -} - -template -inline -typename std::enable_if -< - std::ratio::type::den == 1, - std::basic_string ->::type -msl(std::ratio) -{ - using R = typename std::ratio::type; - return std::basic_string(1, '[') + to_string(R::num) + CharT{']'}; -} - -#endif // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411) - -template -CONSTCD11 -inline -string_literal -msl(std::atto) NOEXCEPT -{ - return string_literal{'a'}; -} - -template -CONSTCD11 -inline -string_literal -msl(std::femto) NOEXCEPT -{ - return string_literal{'f'}; -} - -template -CONSTCD11 -inline -string_literal -msl(std::pico) NOEXCEPT -{ - return string_literal{'p'}; -} - -template -CONSTCD11 -inline -string_literal -msl(std::nano) NOEXCEPT -{ - return string_literal{'n'}; -} - -template -CONSTCD11 -inline -typename std::enable_if -< - std::is_same::value, - string_literal ->::type -msl(std::micro) NOEXCEPT -{ - return string_literal{'\xC2', '\xB5'}; -} - -template -CONSTCD11 -inline -typename std::enable_if -< - !std::is_same::value, - string_literal ->::type -msl(std::micro) NOEXCEPT -{ - return string_literal{CharT{static_cast('\xB5')}}; -} - -template -CONSTCD11 -inline -string_literal -msl(std::milli) NOEXCEPT -{ - return string_literal{'m'}; -} - -template -CONSTCD11 -inline -string_literal -msl(std::centi) NOEXCEPT -{ - return string_literal{'c'}; -} - -template -CONSTCD11 -inline -string_literal -msl(std::deca) NOEXCEPT -{ - return string_literal{'d', 'a'}; -} - -template -CONSTCD11 -inline -string_literal -msl(std::deci) NOEXCEPT -{ - return string_literal{'d'}; -} - -template -CONSTCD11 -inline -string_literal -msl(std::hecto) NOEXCEPT -{ - return string_literal{'h'}; -} - -template -CONSTCD11 -inline -string_literal -msl(std::kilo) NOEXCEPT -{ - return string_literal{'k'}; -} - -template -CONSTCD11 -inline -string_literal -msl(std::mega) NOEXCEPT -{ - return string_literal{'M'}; -} - -template -CONSTCD11 -inline -string_literal -msl(std::giga) NOEXCEPT -{ - return string_literal{'G'}; -} - -template -CONSTCD11 -inline -string_literal -msl(std::tera) NOEXCEPT -{ - return string_literal{'T'}; -} - -template -CONSTCD11 -inline -string_literal -msl(std::peta) NOEXCEPT -{ - return string_literal{'P'}; -} - -template -CONSTCD11 -inline -string_literal -msl(std::exa) NOEXCEPT -{ - return string_literal{'E'}; -} - -template -CONSTCD11 -inline -auto -get_units(Period p) - -> decltype(msl(p) + string_literal{'s'}) -{ - return msl(p) + string_literal{'s'}; -} - -template -CONSTCD11 -inline -string_literal -get_units(std::ratio<1>) -{ - return string_literal{'s'}; -} - -template -CONSTCD11 -inline -string_literal -get_units(std::ratio<3600>) -{ - return string_literal{'h'}; -} - -template -CONSTCD11 -inline -string_literal -get_units(std::ratio<60>) -{ - return string_literal{'m', 'i', 'n'}; -} - -template -CONSTCD11 -inline -string_literal -get_units(std::ratio<86400>) -{ - return string_literal{'d'}; -} - -template > -struct make_string; - -template <> -struct make_string -{ - template - static - std::string - from(Rep n) - { - return std::to_string(n); - } -}; - -template -struct make_string -{ - template - static - std::basic_string - from(Rep n) - { - auto s = std::to_string(n); - return std::basic_string(s.begin(), s.end()); - } -}; - -template <> -struct make_string -{ - template - static - std::wstring - from(Rep n) - { - return std::to_wstring(n); - } -}; - -template -struct make_string -{ - template - static - std::basic_string - from(Rep n) - { - auto s = std::to_wstring(n); - return std::basic_string(s.begin(), s.end()); - } -}; - -} // namespace detail - template inline std::basic_ostream&