#ifndef CHRONO_IO_H #define CHRONO_IO_H // The MIT License (MIT) // // Copyright (c) 2016 Howard Hinnant // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // // Our apologies. When the previous paragraph was written, lowercase had not yet // been invented (that woud involve another several millennia of evolution). // We did not mean to shout. #include #include #include #include #include #include #include namespace date { namespace detail { #if __cplusplus >= 201402 template class string_literal { CharT p_[N]; public: using const_iterator = const CharT*; string_literal(string_literal const&) = default; string_literal& operator=(string_literal const&) = delete; template > constexpr string_literal(CharT c) noexcept : p_{c} { } constexpr string_literal(const CharT(&a)[N]) noexcept : p_{} { for (std::size_t i = 0; i < N; ++i) p_[i] = a[i]; } template > constexpr string_literal(const char(&a)[N]) noexcept : p_{} { for (std::size_t i = 0; i < N; ++i) p_[i] = a[i]; } template {}>> constexpr string_literal(string_literal const& a) noexcept : p_{} { for (std::size_t i = 0; i < N; ++i) p_[i] = a[i]; } template > constexpr string_literal(const string_literal& x, const string_literal& y) noexcept : p_{} { std::size_t i = 0; for (; i < N1-1; ++i) p_[i] = x[i]; for (std::size_t j = 0; j < N2; ++j, ++i) p_[i] = y[j]; } constexpr const CharT* data() const noexcept {return p_;} constexpr std::size_t size() const noexcept {return N-1;} constexpr const_iterator begin() const noexcept {return p_;} constexpr const_iterator end() const noexcept {return p_ + N-1;} constexpr 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 constexpr inline string_literal, N1 + N2 - 1> operator+(const string_literal& x, const string_literal& y) noexcept { using CharT = std::conditional_t; return string_literal{string_literal{x}, string_literal{y}}; } template constexpr inline string_literal msl(const CharT(&a)[N]) noexcept { return string_literal{a}; } template {} || std::is_same{} || std::is_same{} || std::is_same{}>> constexpr inline string_literal msl(CharT c) noexcept { return string_literal{c}; } constexpr 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 constexpr inline std::enable_if_t < N < 10, string_literal > msl() noexcept { return msl(char(N % 10 + '0')); } template constexpr inline std::enable_if_t < 10 <= N, string_literal > msl() noexcept { return msl() + msl(char(N % 10 + '0')); } template constexpr 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 constexpr 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{']'}); } template constexpr inline auto msl(std::atto) noexcept { return msl(CharT{'a'}); } template constexpr inline auto msl(std::femto) noexcept { return msl(CharT{'f'}); } template constexpr inline auto msl(std::pico) noexcept { return msl(CharT{'p'}); } template constexpr inline auto msl(std::nano) noexcept { return msl(CharT{'n'}); } template constexpr inline std::enable_if_t < std::is_same{}, string_literal > msl(std::micro) noexcept { return string_literal{"\xC2\xB5"}; } template constexpr inline std::enable_if_t < !std::is_same{}, string_literal > msl(std::micro) noexcept { return string_literal{CharT{static_cast('\xB5')}}; } template constexpr inline auto msl(std::milli) noexcept { return msl(CharT{'m'}); } template constexpr inline auto msl(std::centi) noexcept { return msl(CharT{'c'}); } template constexpr inline auto msl(std::deci) noexcept { return msl(CharT{'d'}); } template constexpr inline auto msl(std::deca) noexcept { return string_literal{"da"}; } template constexpr inline auto msl(std::hecto) noexcept { return msl(CharT{'h'}); } template constexpr inline auto msl(std::kilo) noexcept { return msl(CharT{'k'}); } template constexpr inline auto msl(std::mega) noexcept { return msl(CharT{'M'}); } template constexpr inline auto msl(std::giga) noexcept { return msl(CharT{'G'}); } template constexpr inline auto msl(std::tera) noexcept { return msl(CharT{'T'}); } template constexpr inline auto msl(std::peta) noexcept { return msl(CharT{'P'}); } template constexpr inline auto msl(std::exa) noexcept { return msl(CharT{'E'}); } template constexpr auto get_units(const std::chrono::duration&) { return msl(Period{}) + string_literal{"s"}; } template constexpr auto get_units(const std::chrono::duration>&) { return string_literal{"s"}; } template constexpr auto get_units(const std::chrono::duration>&) { return string_literal{"min"}; } template constexpr auto get_units(const std::chrono::duration>&) { return string_literal{"h"}; } #else // __cplusplus < 201402 inline std::string to_string(std::uint64_t x) { return std::to_string(x); } template std::basic_string to_string(std::uint64_t x) { auto y = std::to_string(x); return std::basic_string(y.begin(), y.end()); } template constexpr inline typename std::enable_if < std::ratio::type::den != 1, std::basic_string >::type msl(std::ratio) noexcept { using R = typename std::ratio::type; return std::basic_string(1, '[') + to_string(R::num) + CharT{'/'} + to_string(R::den) + CharT{']'}; } template constexpr inline typename std::enable_if < std::ratio::type::den == 1, std::basic_string >::type msl(std::ratio) noexcept { using R = typename std::ratio::type; return std::basic_string(1, '[') + to_string(R::num) + CharT{']'}; } template constexpr inline std::basic_string msl(std::atto) noexcept { return {'a'}; } template constexpr inline std::basic_string msl(std::femto) noexcept { return {'f'}; } template constexpr inline std::basic_string msl(std::pico) noexcept { return {'p'}; } template constexpr inline std::basic_string msl(std::nano) noexcept { return {'n'}; } template constexpr inline typename std::enable_if < std::is_same::value, std::string >::type msl(std::micro) noexcept { return "\xC2\xB5"; } template constexpr inline typename std::enable_if < !std::is_same::value, std::basic_string >::type msl(std::micro) noexcept { return {CharT(static_cast('\xB5'))}; } template constexpr inline std::basic_string msl(std::milli) noexcept { return {'m'}; } template constexpr inline std::basic_string msl(std::centi) noexcept { return {'c'}; } template constexpr inline std::basic_string msl(std::deci) noexcept { return {'d'}; } template constexpr inline std::basic_string msl(std::deca) noexcept { return {'d', 'a'}; } template constexpr inline std::basic_string msl(std::hecto) noexcept { return {'h'}; } template constexpr inline std::basic_string msl(std::kilo) noexcept { return {'k'}; } template constexpr inline std::basic_string msl(std::mega) noexcept { return {'M'}; } template constexpr inline std::basic_string msl(std::giga) noexcept { return {'G'}; } template constexpr inline std::basic_string msl(std::tera) noexcept { return {'T'}; } template constexpr inline std::basic_string msl(std::peta) noexcept { return {'P'}; } template constexpr inline std::basic_string msl(std::exa) noexcept { return {'E'}; } template std::basic_string get_units(const std::chrono::duration&) { return msl(Period{}) + CharT{'s'}; } template std::basic_string get_units(const std::chrono::duration>&) { return {'s'}; } template std::basic_string get_units(const std::chrono::duration>&) { return {'m', 'i', 'n'}; } template std::basic_string get_units(const std::chrono::duration>&) { return {'h'}; } #endif // __cplusplus >= 201402 } // namespace detail template inline std::basic_ostream& operator<<(std::basic_ostream& os, const std::chrono::duration& d) { using namespace std::chrono; return os << d.count() << detail::get_units(duration{}); } } // namespace date #endif // CHRONO_IO_H