From d15491103bc288fc8d6a3a6138a41656f1c900a5 Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Thu, 13 Apr 2017 21:01:47 -0400 Subject: [PATCH] Move chrono_io.h functionality into date.h. --- README.md | 8 +- chrono_io.h | 647 +------------------------------------------------- date.h | 672 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 677 insertions(+), 650 deletions(-) diff --git a/README.md b/README.md index a37b1fb..2fd3ebe 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,11 @@ This is actually several separate C++11/C++14 libraries: Here are the Cppcon 2016 slides on tz.h: http://schd.ws/hosted_files/cppcon2016/0f/Welcome%20To%20The%20Time%20Zone%20-%20Howard%20Hinnant%20-%20CppCon%202016.pdf -3. `"chrono_io.h"` is a header-only library for streaming out chrono durations. See http://howardhinnant.github.io/date/chrono_io.html for more details. +3. `"iso_week.h"` is a header-only library built on top of the `"date.h"` library which implements the ISO week date calendar. See http://howardhinnant.github.io/date/iso_week.html for more details. -4. `"iso_week.h"` is a header-only library built on top of the `"date.h"` library which implements the ISO week date calendar. See http://howardhinnant.github.io/date/iso_week.html for more details. +4. `"julian.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Julian calendar which is fully interoperable with everything above. See http://howardhinnant.github.io/date/julian.html for more details. -5. `"julian.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Julian calendar which is fully interoperable with everything above. See http://howardhinnant.github.io/date/julian.html for more details. - -6. `"islamic.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Islamic calendar which is fully interoperable with everything above. See http://howardhinnant.github.io/date/islamic.html for more details. +5. `"islamic.h"` is a header-only library built on top of the `"date.h"` library which implements a proleptic Islamic calendar which is fully interoperable with everything above. See http://howardhinnant.github.io/date/islamic.html for more details. There has been a recent change in the library design. If you are trying to migrate from the previous design, rename `day_point` to `sys_days` everywhere, and that ought to bring the number of errors down to a small roar. diff --git a/chrono_io.h b/chrono_io.h index 15ab051..21be404 100644 --- a/chrono_io.h +++ b/chrono_io.h @@ -27,651 +27,8 @@ // been invented (that would involve another several millennia of evolution). // We did not mean to shout. -#include -#include -#include -#include -#include -#include -#include +// This functionality has moved to "date.h" -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 -inline -std::basic_string -operator+(std::basic_string x, - const string_literal& y) noexcept -{ - x.append(y.data(), y.size()); - return x; -} - -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(Period p) -{ - return msl(p) + string_literal{"s"}; -} - -template -constexpr -auto -get_units(std::ratio<1>) -{ - return string_literal{"s"}; -} - -template -constexpr -auto -get_units(std::ratio<60>) -{ - return string_literal{"min"}; -} - -template -constexpr -auto -get_units(std::ratio<3600>) -{ - 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(Period p) -{ - return msl(p) + CharT{'s'}; -} - -template -std::basic_string -get_units(std::ratio<1>) -{ - return {'s'}; -} - -template -std::basic_string -get_units(std::ratio<60>) -{ - return {'m', 'i', 'n'}; -} - -template -std::basic_string -get_units(std::ratio<3600>) -{ - 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; - return os << to_string(d.count()) + detail::get_units(typename Period::type{}); -} - -} // namespace date +#include "date.h" #endif // CHRONO_IO_H diff --git a/date.h b/date.h index e0ded06..d3f700c 100644 --- a/date.h +++ b/date.h @@ -35,6 +35,7 @@ #if !(__cplusplus >= 201402) # include #endif +#include #include #include #include @@ -6654,6 +6655,677 @@ parse(const CharT* format, Parsable& tp, return {format, tp, &abbrev, &offset}; } +// duration streaming + +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 > + CONSTCD14 string_literal(CharT c) NOEXCEPT + : p_{c} + { + } + + CONSTCD14 string_literal(const CharT(&a)[N]) NOEXCEPT + : p_{} + { + for (std::size_t i = 0; i < N; ++i) + p_[i] = a[i]; + } + + template > + CONSTCD14 string_literal(const char(&a)[N]) NOEXCEPT + : p_{} + { + for (std::size_t i = 0; i < N; ++i) + p_[i] = a[i]; + } + + template {}>> + CONSTCD14 string_literal(string_literal const& a) NOEXCEPT + : p_{} + { + for (std::size_t i = 0; i < N; ++i) + p_[i] = a[i]; + } + + template > + CONSTCD14 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]; + } + + CONSTCD14 const CharT* data() const NOEXCEPT {return p_;} + CONSTCD14 std::size_t size() const NOEXCEPT {return N-1;} + + CONSTCD14 const_iterator begin() const NOEXCEPT {return p_;} + CONSTCD14 const_iterator end() const NOEXCEPT {return p_ + N-1;} + + CONSTCD14 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 +CONSTCD14 +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 +inline +std::basic_string +operator+(std::basic_string x, + const string_literal& y) NOEXCEPT +{ + x.append(y.data(), y.size()); + return x; +} + +template +CONSTCD14 +inline +string_literal +msl(const CharT(&a)[N]) NOEXCEPT +{ + return string_literal{a}; +} + +template {} || + std::is_same{} || + std::is_same{} || + std::is_same{}>> +CONSTCD14 +inline +string_literal +msl(CharT c) NOEXCEPT +{ + return string_literal{c}; +} + +CONSTCD14 +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{']'}); +} + +template +CONSTCD14 +inline +auto +msl(std::atto) NOEXCEPT +{ + return msl(CharT{'a'}); +} + +template +CONSTCD14 +inline +auto +msl(std::femto) NOEXCEPT +{ + return msl(CharT{'f'}); +} + +template +CONSTCD14 +inline +auto +msl(std::pico) NOEXCEPT +{ + return msl(CharT{'p'}); +} + +template +CONSTCD14 +inline +auto +msl(std::nano) NOEXCEPT +{ + return msl(CharT{'n'}); +} + +template +CONSTCD14 +inline +std::enable_if_t +< + std::is_same{}, + string_literal +> +msl(std::micro) NOEXCEPT +{ + return string_literal{"\xC2\xB5"}; +} + +template +CONSTCD14 +inline +std::enable_if_t +< + !std::is_same{}, + string_literal +> +msl(std::micro) NOEXCEPT +{ + return string_literal{CharT{static_cast('\xB5')}}; +} + +template +CONSTCD14 +inline +auto +msl(std::milli) NOEXCEPT +{ + return msl(CharT{'m'}); +} + +template +CONSTCD14 +inline +auto +msl(std::centi) NOEXCEPT +{ + return msl(CharT{'c'}); +} + +template +CONSTCD14 +inline +auto +msl(std::deci) NOEXCEPT +{ + return msl(CharT{'d'}); +} + +template +CONSTCD14 +inline +auto +msl(std::deca) NOEXCEPT +{ + return string_literal{"da"}; +} + +template +CONSTCD14 +inline +auto +msl(std::hecto) NOEXCEPT +{ + return msl(CharT{'h'}); +} + +template +CONSTCD14 +inline +auto +msl(std::kilo) NOEXCEPT +{ + return msl(CharT{'k'}); +} + +template +CONSTCD14 +inline +auto +msl(std::mega) NOEXCEPT +{ + return msl(CharT{'M'}); +} + +template +CONSTCD14 +inline +auto +msl(std::giga) NOEXCEPT +{ + return msl(CharT{'G'}); +} + +template +CONSTCD14 +inline +auto +msl(std::tera) NOEXCEPT +{ + return msl(CharT{'T'}); +} + +template +CONSTCD14 +inline +auto +msl(std::peta) NOEXCEPT +{ + return msl(CharT{'P'}); +} + +template +CONSTCD14 +inline +auto +msl(std::exa) NOEXCEPT +{ + return msl(CharT{'E'}); +} + +template +CONSTCD14 +auto +get_units(Period p) +{ + return msl(p) + string_literal{"s"}; +} + +template +CONSTCD14 +auto +get_units(std::ratio<1>) +{ + return string_literal{"s"}; +} + +template +CONSTCD14 +auto +get_units(std::ratio<60>) +{ + return string_literal{"min"}; +} + +template +CONSTCD14 +auto +get_units(std::ratio<3600>) +{ + 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 +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{']'}; +} + +template +inline +std::basic_string +msl(std::atto) +{ + return {'a'}; +} + +template +inline +std::basic_string +msl(std::femto) +{ + return {'f'}; +} + +template +inline +std::basic_string +msl(std::pico) +{ + return {'p'}; +} + +template +inline +std::basic_string +msl(std::nano) +{ + return {'n'}; +} + +template +inline +typename std::enable_if +< + std::is_same::value, + std::string +>::type +msl(std::micro) +{ + return "\xC2\xB5"; +} + +template +inline +typename std::enable_if +< + !std::is_same::value, + std::basic_string +>::type +msl(std::micro) +{ + return {CharT(static_cast('\xB5'))}; +} + +template +inline +std::basic_string +msl(std::milli) +{ + return {'m'}; +} + +template +inline +std::basic_string +msl(std::centi) +{ + return {'c'}; +} + +template +inline +std::basic_string +msl(std::deci) +{ + return {'d'}; +} + +template +inline +std::basic_string +msl(std::deca) +{ + return {'d', 'a'}; +} + +template +inline +std::basic_string +msl(std::hecto) +{ + return {'h'}; +} + +template +inline +std::basic_string +msl(std::kilo) +{ + return {'k'}; +} + +template +inline +std::basic_string +msl(std::mega) +{ + return {'M'}; +} + +template +inline +std::basic_string +msl(std::giga) +{ + return {'G'}; +} + +template +inline +std::basic_string +msl(std::tera) +{ + return {'T'}; +} + +template +inline +std::basic_string +msl(std::peta) +{ + return {'P'}; +} + +template +inline +std::basic_string +msl(std::exa) +{ + return {'E'}; +} + +template +std::basic_string +get_units(Period p) +{ + return msl(p) + CharT{'s'}; +} + +template +std::basic_string +get_units(std::ratio<1>) +{ + return {'s'}; +} + +template +std::basic_string +get_units(std::ratio<60>) +{ + return {'m', 'i', 'n'}; +} + +template +std::basic_string +get_units(std::ratio<3600>) +{ + return {'h'}; +} + +#endif // __cplusplus >= 201402 + +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::wstring + from(Rep n) + { + auto s = std::to_wstring(n); + return std::basic_string(s.begin(), s.end()); + } +}; + +} // namespace detail + +template +inline +std::basic_ostream& +operator<<(std::basic_ostream& os, + const std::chrono::duration& d) +{ + using namespace detail; + return os << make_string::from(d.count()) + + get_units(typename Period::type{}); +} + } // namespace date