diff --git a/src/beast/Builds/VisualStudio2012/beast.vcxproj b/src/beast/Builds/VisualStudio2012/beast.vcxproj index e8a152c30..07698e5e0 100644 --- a/src/beast/Builds/VisualStudio2012/beast.vcxproj +++ b/src/beast/Builds/VisualStudio2012/beast.vcxproj @@ -88,7 +88,11 @@ + + + + @@ -402,12 +406,24 @@ + + true + true + true + true + true true true true + + true + true + true + true + true true diff --git a/src/beast/Builds/VisualStudio2012/beast.vcxproj.filters b/src/beast/Builds/VisualStudio2012/beast.vcxproj.filters index 0b081079a..723f102f8 100644 --- a/src/beast/Builds/VisualStudio2012/beast.vcxproj.filters +++ b/src/beast/Builds/VisualStudio2012/beast.vcxproj.filters @@ -1227,6 +1227,18 @@ beast\crypto + + beast\chrono + + + beast\chrono + + + beast\chrono + + + beast\chrono + @@ -1778,6 +1790,12 @@ beast\insight\impl + + beast\chrono\impl + + + beast\chrono\impl + beast\crypto\impl diff --git a/src/beast/beast/Chrono.h b/src/beast/beast/Chrono.h index 027b1f5f3..c0ea88da4 100644 --- a/src/beast/beast/Chrono.h +++ b/src/beast/beast/Chrono.h @@ -20,6 +20,11 @@ #ifndef BEAST_CHRONO_H_INCLUDED #define BEAST_CHRONO_H_INCLUDED +#include "chrono/abstract_clock.h" +#include "chrono/chrono_io.h" +#include "chrono/manual_clock.h" +#include "chrono/ratio_io.h" + #include "chrono/CPUMeter.h" #include "chrono/RelativeTime.h" #include "chrono/ScopedTimeInterval.h" diff --git a/src/beast/beast/chrono/Chrono.cpp b/src/beast/beast/chrono/Chrono.cpp index 5ce5772e6..dc50936e0 100644 --- a/src/beast/beast/chrono/Chrono.cpp +++ b/src/beast/beast/chrono/Chrono.cpp @@ -19,5 +19,11 @@ #include "BeastConfig.h" +#include "../Config.h" +#include "../../modules/beast_core/beast_core.h" // for UnitTest + +#include "impl/abstract_clock.cpp" +#include "impl/chrono_io.cpp" + #include "impl/CPUMeter.cpp" #include "impl/RelativeTime.cpp" diff --git a/src/beast/beast/chrono/abstract_clock.h b/src/beast/beast/chrono/abstract_clock.h new file mode 100644 index 000000000..c47c1bd1f --- /dev/null +++ b/src/beast/beast/chrono/abstract_clock.h @@ -0,0 +1,166 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_CHRONO_ABSTRACT_CLOCK_H_INCLUDED +#define BEAST_CHRONO_ABSTRACT_CLOCK_H_INCLUDED + +#include + +#include "chrono_io.h" + +namespace beast { + +/** Abstract interface to a clock. + + The abstract clock interface allows a dependency injection to take + place so that the choice of implementation can be made at run-time + instead of compile time. The trade-off is that the Duration used to + represent the clock must be chosen at compile time and cannot be + changed. This includes both the choice of representation (integers + for example) and the period in ticks corresponding to one second. + + Example: + + @code + + struct Implementation + { + abstract_clock & m_clock; + + // Dependency injection + // + explicit Implementation ( + abstract_clock & clock) + : m_clock (clock) + { + } + }; + + @endcode + + @tparam The length of time, in seconds, corresponding to one tick. +*/ +template +class abstract_clock +{ +public: + typedef typename Duration::rep rep; + typedef typename Duration::period period; + typedef Duration duration; + typedef std::chrono::time_point < + abstract_clock, duration> time_point; + + virtual ~abstract_clock () { } + + /** Returns `true` if this is a steady clock. */ + virtual bool is_steady () const = 0; + + /** Returns the current time. */ + virtual time_point now () = 0; + + /** Convert the specified time point to a string. */ + /** @{ */ + virtual std::string to_string (time_point const& tp) = 0; + + template + std::string to_string ( + std::chrono::time_point const& tp) + { + return to_string ( + std::chrono::time_point_cast (tp)); + } + /** @} */ + + /** Returning elapsed ticks since the epoch. */ + rep elapsed () + { + return now().time_since_epoch().count(); + } +}; + +//------------------------------------------------------------------------------ + +namespace detail { + +template +struct basic_abstract_clock_wrapper : public abstract_clock +{ + using typename abstract_clock ::duration; + using typename abstract_clock ::time_point; + + bool is_steady () const + { + return TrivialClock::is_steady; + } + + time_point now () + { + return time_point (duration ( + std::chrono::duration_cast ( + TrivialClock::now().time_since_epoch ()).count ())); + } +}; + +template +struct abstract_clock_wrapper + : public basic_abstract_clock_wrapper +{ + // generic conversion displays the duration + std::string to_string (typename basic_abstract_clock_wrapper < + TrivialClock, Duration>::time_point const& tp) + { + std::stringstream ss; + ss << tp.time_since_epoch(); + return ss.str (); + } +}; + +/* +template +struct abstract_clock_wrapper + : public basic_abstract_clock_wrapper +{ + typedef std::chrono::system_clock clock_type; + std::string to_string (time_point const& tp) + { + std::stringstream ss; + ss << clock_type::time_point (tp.time_since_epoch ()); + return ss.str (); + } +}; +*/ + +} + +//------------------------------------------------------------------------------ + +/** Retrieve a discrete clock for a type implementing the Clock concept. + The interface is created as an object with static storage duration. +*/ +template +abstract_clock & get_abstract_clock () +{ + static detail::abstract_clock_wrapper < + TrivialClock, Duration> clock; + return clock; +} + +} + +#endif diff --git a/src/beast/beast/chrono/chrono_io.h b/src/beast/beast/chrono/chrono_io.h new file mode 100644 index 000000000..fdcf47555 --- /dev/null +++ b/src/beast/beast/chrono/chrono_io.h @@ -0,0 +1,1087 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +// chrono_io +// +// (C) Copyright Howard Hinnant +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). + +#ifndef BEAST_CHRONO_CHRONO_IO_H_INCLUDED +#define BEAST_CHRONO_CHRONO_IO_H_INCLUDED + +#include "../Config.h" + +#include +#include + +#define BEAST_CHRONO_NO_TIMEPOINT_IO 1 + +/* + + chrono_io synopsis + +#include +#include + +namespace std +{ +namespace chrono +{ + +enum duration_style {prefix, symbol}; +enum timezone {utc, local}; + +// facets + +class durationpunct + : public locale::facet +{ +public: + static locale::id id; + + explicit durationpunct(size_t refs = 0); + explicit durationpunct(duration_style fmt, size_t refs = 0); + + bool is_symbol_name() const noexcept; + bool is_prefix_name() const noexcept; +}; + +template +class timepunct + : public locale::facet +{ +public: + typedef basic_string string_type; + + static locale::id id; + + explicit timepunct(size_t refs = 0); + timepunct(timezone tz, string_type fmt, size_t refs = 0); + + const string_type& fmt() const noexcept; + std::chrono::timezone timezone() const noexcept; +}; + +// manipulators + +class duration_fmt +{ +public: + explicit duration_fmt(duration_style f) noexcept; + explicit operator duration_style() const noexcept; +}; + +unspecified time_fmt(timezone tz); +template + unspecified time_fmt(timezone tz, basic_string fmt); +template + unspecified time_fmt(timezone tz, const charT* fmt); + +template +std::basic_ostream& +operator<<(std::basic_ostream& os, duration_fmt d); + +template +std::basic_istream& +operator>>(std::basic_istream& is, duration_fmt d); + +// duration I/O + +template + basic_ostream& + operator<<(basic_ostream& os, const duration& d); + +template + basic_istream& + operator>>(basic_istream& is, duration& d); + +// system_clock I/O + +template + basic_ostream& + operator<<(basic_ostream& os, + const time_point& tp); + +template + basic_istream& + operator>>(basic_istream& is, + time_point& tp); + +// steady_clock I/O + +template + basic_ostream& + operator<<(basic_ostream& os, + const time_point& tp); + +template + basic_istream& + operator>>(basic_istream& is, + time_point& tp); + +// high_resolution_clock I/O + +template + basic_ostream& + operator<<(basic_ostream& os, + const time_point& tp); + +template + basic_istream& + operator>>(basic_istream& is, + time_point& tp); + +} // chrono +} // std + +*/ + +#include +#include "ratio_io.h" + +//_LIBCPP_BEGIN_NAMESPACE_STD +namespace std { + +namespace chrono +{ + +template +To +round(const duration& d) +{ + To t0 = duration_cast(d); + To t1 = t0; + ++t1; + typedef typename common_type >::type _D; + _D diff0 = d - t0; + _D diff1 = t1 - d; + if (diff0 == diff1) + { + if (t0.count() & 1) + return t1; + return t0; + } + else if (diff0 < diff1) + return t0; + return t1; +} + +enum duration_style {prefix, symbol}; +enum timezone {utc, local}; + +class durationpunct + : public locale::facet +{ +private: + duration_style __style_; +public: + static locale::id id; + + explicit durationpunct(size_t refs = 0) + : locale::facet(refs), __style_(prefix) {} + + explicit durationpunct(duration_style fmt, size_t refs = 0) + : locale::facet(refs), __style_(fmt) {} + + bool is_symbol_name() const noexcept {return __style_ == symbol;} + bool is_prefix_name() const noexcept {return __style_ == prefix;} +}; + +class duration_fmt +{ + duration_style form_; +public: + explicit duration_fmt(duration_style f) noexcept : form_(f) {} + // VFALCO NOTE disabled this for MSVC + /*explicit*/ + operator duration_style() const noexcept {return form_;} +}; + +template +basic_ostream& +operator <<(basic_ostream& os, duration_fmt d) +{ + os.imbue(locale(os.getloc(), new durationpunct(static_cast(d)))); + return os; +} + +template +basic_istream& +operator >>(basic_istream& is, duration_fmt d) +{ + is.imbue(locale(is.getloc(), new durationpunct(static_cast(d)))); + return is; +} + +template +basic_string<_CharT> +__get_unit(bool __is_long, const duration<_Rep, _Period>& d) +{ + if (__is_long) + { + _CharT __p[] = {'s', 'e', 'c', 'o', 'n', 'd', 's', 0}; + basic_string<_CharT> s = ratio_string<_Period, _CharT>::prefix() + __p; + if (d.count() == 1 || d.count() == -1) + s.pop_back(); + return s; + } + return ratio_string<_Period, _CharT>::symbol() + 's'; +} + +template +basic_string<_CharT> +__get_unit(bool __is_long, const duration<_Rep, ratio<1> >& d) +{ + if (__is_long) + { + _CharT __p[] = {'s', 'e', 'c', 'o', 'n', 'd', 's'}; + basic_string<_CharT> s = basic_string<_CharT>(__p, __p + sizeof(__p) / sizeof(_CharT)); + if (d.count() == 1 || d.count() == -1) + s.pop_back(); + return s; + } + return basic_string<_CharT>(1, 's'); +} + +template +basic_string<_CharT> +__get_unit(bool __is_long, const duration<_Rep, ratio<60> >& d) +{ + if (__is_long) + { + _CharT __p[] = {'m', 'i', 'n', 'u', 't', 'e', 's'}; + basic_string<_CharT> s = basic_string<_CharT>(__p, __p + sizeof(__p) / sizeof(_CharT)); + if (d.count() == 1 || d.count() == -1) + s.pop_back(); + return s; + } + _CharT __p[] = {'m', 'i', 'n'}; + return basic_string<_CharT>(__p, __p + sizeof(__p) / sizeof(_CharT)); +} + +template +basic_string<_CharT> +__get_unit(bool __is_long, const duration<_Rep, ratio<3600> >& d) +{ + if (__is_long) + { + _CharT __p[] = {'h', 'o', 'u', 'r', 's'}; + basic_string<_CharT> s = basic_string<_CharT>(__p, __p + sizeof(__p) / sizeof(_CharT)); + if (d.count() == 1 || d.count() == -1) + s.pop_back(); + return s; + } + return basic_string<_CharT>(1, 'h'); +} + +template +basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, const duration<_Rep, _Period>& __d) +{ + typename basic_ostream<_CharT, _Traits>::sentry ok(__os); + if (ok) + { + typedef durationpunct _F; + typedef basic_string<_CharT> string_type; + bool failed = false; + try + { + bool __is_long = true; + locale __loc = __os.getloc(); + if (has_facet<_F>(__loc)) + { + const _F& f = use_facet<_F>(__loc); + __is_long = f.is_prefix_name(); + } + string_type __unit = __get_unit<_CharT>(__is_long, __d); + __os << __d.count() << ' ' << __unit; + } + catch (...) + { + failed = true; + } + if (failed) + __os.setstate(ios_base::failbit | ios_base::badbit); + } + return __os; +} + +template ::value> +struct __duration_io_intermediate +{ + typedef _Rep type; +}; + +template +struct __duration_io_intermediate<_Rep, true> +{ + typedef typename conditional + < + is_floating_point<_Rep>::value, + long double, + typename conditional + < + is_signed<_Rep>::value, + long long, + unsigned long long + >::type + >::type type; +}; + +template +T +__gcd(T x, T y) +{ + while (y != 0) + { + T old_x = x; + x = y; + y = old_x % y; + } + return x; +} + +template <> +long double +inline +__gcd(long double, long double) +{ + return 1; +} + +template +basic_istream<_CharT, _Traits>& +operator>>(basic_istream<_CharT, _Traits>& __is, duration<_Rep, _Period>& __d) +{ + typedef basic_string<_CharT> string_type; + typedef durationpunct _F; + typedef typename __duration_io_intermediate<_Rep>::type _IR; + _IR __r; + // read value into __r + __is >> __r; + if (__is.good()) + { + // now determine unit + typedef istreambuf_iterator<_CharT, _Traits> _I; + _I __i(__is); + _I __e; + if (__i != __e && *__i == ' ') // mandatory ' ' after value + { + ++__i; + if (__i != __e) + { + locale __loc = __is.getloc(); + // unit is num / den (yet to be determined) + unsigned long long num = 0; + unsigned long long den = 0; + ios_base::iostate __err = ios_base::goodbit; + if (*__i == '[') + { + // parse [N/D]s or [N/D]seconds format + ++__i; + _CharT __x; + __is >> num >> __x >> den; + if (!__is.good() || __x != '/') + { + __is.setstate(__is.failbit); + return __is; + } + __i = _I(__is); + if (*__i != ']') + { + __is.setstate(__is.failbit); + return __is; + } + ++__i; + const basic_string<_CharT> __units[] = + { + __get_unit<_CharT>(true, seconds(2)), + __get_unit<_CharT>(true, seconds(1)), + __get_unit<_CharT>(false, seconds(1)) + }; + const basic_string<_CharT>* __k = __scan_keyword(__i, __e, + __units, __units + sizeof(__units)/sizeof(__units[0]), + use_facet >(__loc), + __err); + switch ((__k - __units) / 3) + { + case 0: + break; + default: + __is.setstate(__err); + return __is; + } + } + else + { + // parse SI name, short or long + const basic_string<_CharT> __units[] = + { + __get_unit<_CharT>(true, duration<_Rep, atto>(2)), + __get_unit<_CharT>(true, duration<_Rep, atto>(1)), + __get_unit<_CharT>(false, duration<_Rep, atto>(1)), + __get_unit<_CharT>(true, duration<_Rep, femto>(2)), + __get_unit<_CharT>(true, duration<_Rep, femto>(1)), + __get_unit<_CharT>(false, duration<_Rep, femto>(1)), + __get_unit<_CharT>(true, duration<_Rep, pico>(2)), + __get_unit<_CharT>(true, duration<_Rep, pico>(1)), + __get_unit<_CharT>(false, duration<_Rep, pico>(1)), + __get_unit<_CharT>(true, duration<_Rep, nano>(2)), + __get_unit<_CharT>(true, duration<_Rep, nano>(1)), + __get_unit<_CharT>(false, duration<_Rep, nano>(1)), + __get_unit<_CharT>(true, duration<_Rep, micro>(2)), + __get_unit<_CharT>(true, duration<_Rep, micro>(1)), + __get_unit<_CharT>(false, duration<_Rep, micro>(1)), + __get_unit<_CharT>(true, duration<_Rep, milli>(2)), + __get_unit<_CharT>(true, duration<_Rep, milli>(1)), + __get_unit<_CharT>(false, duration<_Rep, milli>(1)), + __get_unit<_CharT>(true, duration<_Rep, centi>(2)), + __get_unit<_CharT>(true, duration<_Rep, centi>(1)), + __get_unit<_CharT>(false, duration<_Rep, centi>(1)), + __get_unit<_CharT>(true, duration<_Rep, deci>(2)), + __get_unit<_CharT>(true, duration<_Rep, deci>(1)), + __get_unit<_CharT>(false, duration<_Rep, deci>(1)), + __get_unit<_CharT>(true, duration<_Rep, deca>(2)), + __get_unit<_CharT>(true, duration<_Rep, deca>(1)), + __get_unit<_CharT>(false, duration<_Rep, deca>(1)), + __get_unit<_CharT>(true, duration<_Rep, hecto>(2)), + __get_unit<_CharT>(true, duration<_Rep, hecto>(1)), + __get_unit<_CharT>(false, duration<_Rep, hecto>(1)), + __get_unit<_CharT>(true, duration<_Rep, kilo>(2)), + __get_unit<_CharT>(true, duration<_Rep, kilo>(1)), + __get_unit<_CharT>(false, duration<_Rep, kilo>(1)), + __get_unit<_CharT>(true, duration<_Rep, mega>(2)), + __get_unit<_CharT>(true, duration<_Rep, mega>(1)), + __get_unit<_CharT>(false, duration<_Rep, mega>(1)), + __get_unit<_CharT>(true, duration<_Rep, giga>(2)), + __get_unit<_CharT>(true, duration<_Rep, giga>(1)), + __get_unit<_CharT>(false, duration<_Rep, giga>(1)), + __get_unit<_CharT>(true, duration<_Rep, tera>(2)), + __get_unit<_CharT>(true, duration<_Rep, tera>(1)), + __get_unit<_CharT>(false, duration<_Rep, tera>(1)), + __get_unit<_CharT>(true, duration<_Rep, peta>(2)), + __get_unit<_CharT>(true, duration<_Rep, peta>(1)), + __get_unit<_CharT>(false, duration<_Rep, peta>(1)), + __get_unit<_CharT>(true, duration<_Rep, exa>(2)), + __get_unit<_CharT>(true, duration<_Rep, exa>(1)), + __get_unit<_CharT>(false, duration<_Rep, exa>(1)), + __get_unit<_CharT>(true, duration<_Rep, ratio<1> >(2)), + __get_unit<_CharT>(true, duration<_Rep, ratio<1> >(1)), + __get_unit<_CharT>(false, duration<_Rep, ratio<1> >(1)), + __get_unit<_CharT>(true, duration<_Rep, ratio<60> >(2)), + __get_unit<_CharT>(true, duration<_Rep, ratio<60> >(1)), + __get_unit<_CharT>(false, duration<_Rep, ratio<60> >(1)), + __get_unit<_CharT>(true, duration<_Rep, ratio<3600> >(2)), + __get_unit<_CharT>(true, duration<_Rep, ratio<3600> >(1)), + __get_unit<_CharT>(false, duration<_Rep, ratio<3600> >(1)) + }; + const basic_string<_CharT>* __k = __scan_keyword(__i, __e, + __units, __units + sizeof(__units)/sizeof(__units[0]), + use_facet >(__loc), + __err); + switch (__k - __units) + { + case 0: + case 1: + case 2: + num = 1ULL; + den = 1000000000000000000ULL; + break; + case 3: + case 4: + case 5: + num = 1ULL; + den = 1000000000000000ULL; + break; + case 6: + case 7: + case 8: + num = 1ULL; + den = 1000000000000ULL; + break; + case 9: + case 10: + case 11: + num = 1ULL; + den = 1000000000ULL; + break; + case 12: + case 13: + case 14: + num = 1ULL; + den = 1000000ULL; + break; + case 15: + case 16: + case 17: + num = 1ULL; + den = 1000ULL; + break; + case 18: + case 19: + case 20: + num = 1ULL; + den = 100ULL; + break; + case 21: + case 22: + case 23: + num = 1ULL; + den = 10ULL; + break; + case 24: + case 25: + case 26: + num = 10ULL; + den = 1ULL; + break; + case 27: + case 28: + case 29: + num = 100ULL; + den = 1ULL; + break; + case 30: + case 31: + case 32: + num = 1000ULL; + den = 1ULL; + break; + case 33: + case 34: + case 35: + num = 1000000ULL; + den = 1ULL; + break; + case 36: + case 37: + case 38: + num = 1000000000ULL; + den = 1ULL; + break; + case 39: + case 40: + case 41: + num = 1000000000000ULL; + den = 1ULL; + break; + case 42: + case 43: + case 44: + num = 1000000000000000ULL; + den = 1ULL; + break; + case 45: + case 46: + case 47: + num = 1000000000000000000ULL; + den = 1ULL; + break; + case 48: + case 49: + case 50: + num = 1; + den = 1; + break; + case 51: + case 52: + case 53: + num = 60; + den = 1; + break; + case 54: + case 55: + case 56: + num = 3600; + den = 1; + break; + default: + __is.setstate(__err); + return __is; + } + } + // unit is num/den + // __r should be multiplied by (num/den) / _Period + // Reduce (num/den) / _Period to lowest terms + unsigned long long __gcd_n1_n2 = __gcd(num, _Period::num); + unsigned long long __gcd_d1_d2 = __gcd(den, _Period::den); + num /= __gcd_n1_n2; + den /= __gcd_d1_d2; + unsigned long long __n2 = _Period::num / __gcd_n1_n2; + unsigned long long __d2 = _Period::den / __gcd_d1_d2; + if (num > numeric_limits::max() / __d2 || + den > numeric_limits::max() / __n2) + { + // (num/den) / _Period overflows + __is.setstate(__is.failbit); + return __is; + } + num *= __d2; + den *= __n2; + // num / den is now factor to multiply by __r + typedef typename common_type<_IR, unsigned long long>::type _CT; + if (is_integral<_IR>::value) + { + // Reduce __r * num / den + _CT __t = __gcd<_CT>(__r, den); + __r /= __t; + den /= __t; + if (den != 1) + { + // Conversion to _Period is integral and not exact + __is.setstate(__is.failbit); + return __is; + } + } + if (__r > duration_values<_CT>::max() / num) + { + // Conversion to _Period overflowed + __is.setstate(__is.failbit); + return __is; + } + _CT __t = __r * num; + __t /= den; + if (duration_values<_Rep>::max() < __t) + { + // Conversion to _Period overflowed + __is.setstate(__is.failbit); + return __is; + } + // Success! Store it. + __r = _Rep(__t); + __d = duration<_Rep, _Period>(__r); + __is.setstate(__err); + } + else + __is.setstate(__is.failbit | __is.eofbit); + } + else + { + if (__i == __e) + __is.setstate(__is.eofbit); + __is.setstate(__is.failbit); + } + } + else + __is.setstate(__is.failbit); + return __is; +} + +template +class timepunct + : public locale::facet +{ +public: + typedef basic_string string_type; + +private: + string_type fmt_; + chrono::timezone tz_; + +public: + static locale::id id; + + explicit timepunct(size_t refs = 0) + : locale::facet(refs), tz_(utc) {} + timepunct(timezone tz, string_type fmt, size_t refs = 0) + : locale::facet(refs), fmt_(std::move(fmt)), tz_(tz) {} + + const string_type& fmt() const noexcept {return fmt_;} + chrono::timezone get_timezone() const noexcept {return tz_;} +}; + +template +locale::id +timepunct::id; + +template +basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, + const time_point& __tp) +{ + return __os << __tp.time_since_epoch() << " since boot"; +} + +template +struct __time_manip +{ + basic_string fmt_; + timezone tz_; + + __time_manip(timezone tz, basic_string fmt) + : fmt_(std::move(fmt)), + tz_(tz) {} +}; + +template +basic_ostream& +operator <<(basic_ostream& os, __time_manip m) +{ + os.imbue(locale(os.getloc(), new timepunct(m.tz_, std::move(m.fmt_)))); + return os; +} + +template +basic_istream& +operator >>(basic_istream& is, __time_manip m) +{ + is.imbue(locale(is.getloc(), new timepunct(m.tz_, std::move(m.fmt_)))); + return is; +} + +template +inline +__time_manip +time_fmt(timezone tz, const charT* fmt) +{ + return __time_manip(tz, fmt); +} + +template +inline +__time_manip +time_fmt(timezone tz, basic_string fmt) +{ + return __time_manip(tz, std::move(fmt)); +} + +class __time_man +{ + timezone form_; +public: + explicit __time_man(timezone f) : form_(f) {} + // explicit + operator timezone() const {return form_;} +}; + +template +basic_ostream& +operator <<(basic_ostream& os, __time_man m) +{ + os.imbue(locale(os.getloc(), new timepunct(static_cast(m), basic_string()))); + return os; +} + +template +basic_istream& +operator >>(basic_istream& is, __time_man m) +{ + is.imbue(locale(is.getloc(), new timepunct(static_cast(m), basic_string()))); + return is; +} + +inline +__time_man +time_fmt(timezone f) +{ + return __time_man(f); +} + +#if ! BEAST_CHRONO_NO_TIMEPOINT_IO + +template +basic_istream<_CharT, _Traits>& +operator>>(basic_istream<_CharT, _Traits>& __is, + time_point& __tp) +{ + _Duration __d; + __is >> __d; + if (__is.good()) + { + const _CharT __u[] = {' ', 's', 'i', 'n', 'c', 'e', ' ', 'b', 'o', 'o', 't'}; + const basic_string<_CharT> __units(__u, __u + sizeof(__u)/sizeof(__u[0])); + ios_base::iostate __err = ios_base::goodbit; + typedef istreambuf_iterator<_CharT, _Traits> _I; + _I __i(__is); + _I __e; + ptrdiff_t __k = __scan_keyword(__i, __e, + &__units, &__units + 1, + use_facet >(__is.getloc()), + __err) - &__units; + if (__k == 1) + { + // failed to read epoch string + __is.setstate(__err); + return __is; + } + __tp = time_point(__d); + } + else + __is.setstate(__is.failbit); + return __is; +} + +template +basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, + const time_point& __tp) +{ + typename basic_ostream<_CharT, _Traits>::sentry ok(__os); + if (ok) + { + bool failed = false; + try + { + const _CharT* pb = nullptr; + const _CharT* pe = pb; + timezone tz = utc; + typedef timepunct<_CharT> F; + locale loc = __os.getloc(); + if (has_facet(loc)) + { + const F& f = use_facet(loc); + pb = f.fmt().data(); + pe = pb + f.fmt().size(); + tz = f.get_timezone(); + } + time_t __t = system_clock::to_time_t(__tp); + tm __tm; + if (tz == local) + { + if (localtime_r(&__t, &__tm) == 0) + failed = true; + } + else + { + if (gmtime_r(&__t, &__tm) == 0) + failed = true; + } + if (!failed) + { + const time_put<_CharT>& tp = use_facet >(loc); + if (pb == pe) + { + _CharT pattern[] = {'%', 'F', 'T', '%', 'H', ':', '%', 'M', ':'}; + pb = pattern; + pe = pb + sizeof(pattern) / sizeof(_CharT); + failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed(); + if (!failed) + { + duration __d = __tp - system_clock::from_time_t(__t) + + seconds(__tm.tm_sec); + if (__d.count() < 10) + __os << _CharT('0'); + ios::fmtflags __flgs = __os.flags(); + __os.setf(ios::fixed, ios::floatfield); + __os << __d.count(); + __os.flags(__flgs); + if (tz == local) + { + _CharT sub_pattern[] = {' ', '%', 'z'}; + pb = sub_pattern; + pe = pb + + sizeof(sub_pattern) / sizeof(_CharT); + failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed(); + } + else + { + _CharT sub_pattern[] = {' ', '+', '0', '0', '0', '0', 0}; + __os << sub_pattern; + } + } + } + else + failed = tp.put(__os, __os, __os.fill(), &__tm, pb, pe).failed(); + } + } + catch (...) + { + failed = true; + } + if (failed) + __os.setstate(ios_base::failbit | ios_base::badbit); + } + return __os; +} + +template +minutes +__extract_z(_InputIterator& __b, _InputIterator __e, + ios_base::iostate& __err, const ctype<_CharT>& __ct) +{ + int __minn = 0; + if (__b != __e) + { + char __cn = __ct.narrow(*__b, 0); + if (__cn != '+' && __cn != '-') + { + __err |= ios_base::failbit; + return minutes(0); + } + int __sn = __cn == '-' ? -1 : 1; + int __hr = 0; + for (int i = 0; i < 2; ++i) + { + if (++__b == __e) + { + __err |= ios_base::eofbit | ios_base::failbit; + return minutes(0); + } + __cn = __ct.narrow(*__b, 0); + if (!('0' <= __cn && __cn <= '9')) + { + __err |= ios_base::failbit; + return minutes(0); + } + __hr = __hr * 10 + __cn - '0'; + } + for (int i = 0; i < 2; ++i) + { + if (++__b == __e) + { + __err |= ios_base::eofbit | ios_base::failbit; + return minutes(0); + } + __cn = __ct.narrow(*__b, 0); + if (!('0' <= __cn && __cn <= '9')) + { + __err |= ios_base::failbit; + return minutes(0); + } + __minn = __minn * 10 + __cn - '0'; + } + if (++__b == __e) + __err |= ios_base::eofbit; + __minn += __hr * 60; + __minn *= __sn; + } + else + __err |= ios_base::eofbit | ios_base::failbit; + return minutes(__minn); +} + +template +basic_istream<_CharT, _Traits>& +operator>>(basic_istream<_CharT, _Traits>& __is, + time_point& __tp) +{ + typename basic_istream<_CharT,_Traits>::sentry ok(__is); + if (ok) + { + ios_base::iostate err = ios_base::goodbit; + try + { + const _CharT* pb = nullptr; + const _CharT* pe = pb; + typedef timepunct<_CharT> F; + locale loc = __is.getloc(); + timezone tz = utc; + if (has_facet(loc)) + { + const F& f = use_facet(loc); + pb = f.fmt().data(); + pe = pb + f.fmt().size(); + tz = f.get_timezone(); + } + const time_get<_CharT>& tg = use_facet >(loc); + const ctype<_CharT>& __ct = use_facet >(loc); + tm __tm = {0}; + typedef istreambuf_iterator<_CharT, _Traits> _I; + if (pb == pe) + { + _CharT pattern[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd', + 'T', '%', 'H', ':', '%', 'M', ':'}; + pb = pattern; + pe = pb + sizeof(pattern) / sizeof(_CharT); + tg.get(__is, 0, __is, err, &__tm, pb, pe); + if (err & ios_base::failbit) + goto __exit; + double __sec; + _CharT __c = _CharT(); + __is >> __sec; + if (__is.fail()) + { + err |= ios_base::failbit; + goto __exit; + } + _I __i(__is); + _I __eof; + __c = *__i; + if (++__i == __eof || __c != ' ') + { + err |= ios_base::failbit; + goto __exit; + } + minutes __minn = __extract_z(__i, __eof, err, __ct); + if (err & ios_base::failbit) + goto __exit; + time_t __t; + __t = timegm(&__tm); + __tp = system_clock::from_time_t(__t) - __minn + + round(duration(__sec)); + } + else + { + const _CharT __z[2] = {'%', 'z'}; + const _CharT* __fz = std::search(pb, pe, __z, __z+2); + tg.get(__is, 0, __is, err, &__tm, pb, __fz); + minutes __minn(0); + if (__fz != pe) + { + if (err != ios_base::goodbit) + { + err |= ios_base::failbit; + goto __exit; + } + _I __i(__is); + _I __eof; + __minn = __extract_z(__i, __eof, err, __ct); + if (err & ios_base::failbit) + goto __exit; + if (__fz+2 != pe) + { + if (err != ios_base::goodbit) + { + err |= ios_base::failbit; + goto __exit; + } + tg.get(__is, 0, __is, err, &__tm, __fz+2, pe); + if (err & ios_base::failbit) + goto __exit; + } + } + __tm.tm_isdst = -1; + time_t __t; + if (tz == utc || __fz != pe) + __t = timegm(&__tm); + else + __t = mktime(&__tm); + __tp = system_clock::from_time_t(__t) - __minn; + } + } + catch (...) + { + err |= ios_base::badbit | ios_base::failbit; + } + __exit: + __is.setstate(err); + } + return __is; +} + +#endif + +} // chrono + +//_LIBCPP_END_NAMESPACE_STD +} + +#endif + diff --git a/src/beast/beast/chrono/impl/abstract_clock.cpp b/src/beast/beast/chrono/impl/abstract_clock.cpp new file mode 100644 index 000000000..af9892b31 --- /dev/null +++ b/src/beast/beast/chrono/impl/abstract_clock.cpp @@ -0,0 +1,106 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../abstract_clock.h" +#include "../manual_clock.h" + +#include + +#include +#include + +namespace beast { + +template +std::basic_ostream & operator<< ( + std::basic_ostream& os, std::chrono::time_point < + abstract_clock , Duration2> const& tp) +{ + return os; +} + +class abstract_clock_tests : public UnitTest +{ +public: + void test (abstract_clock & c) + { + { + auto const t1 (c.now ()); + std::this_thread::sleep_for ( + std::chrono::milliseconds (1500)); + auto const t2 (c.now ()); + + std::stringstream ss; + ss << + "t1= " << c.to_string (t1) << + ", t2= " << c.to_string (t2) << + ", elapsed= " << (t2 - t1); + logMessage (ss.str()); + } + } + + void test_manual () + { + typedef manual_clock clock_type; + clock_type c; + + std::stringstream ss; + + ss << "now() = " << c.to_string (c.now ()) << std::endl; + + c.set (clock_type::time_point (std::chrono::seconds (1))); + ss << "now() = " << c.to_string (c.now ()) << std::endl; + + c.set (clock_type::time_point (std::chrono::seconds (2))); + ss << "now() = " << c.to_string (c.now ()) << std::endl; + + logMessage (ss.str()); + } + + void runTest () + { + beginTestCase ("Syntax"); + + logMessage ("steady_clock"); + test (get_abstract_clock ()); + + logMessage ("system_clock"); + test (get_abstract_clock ()); + + logMessage ("high_resolution_clock"); + test (get_abstract_clock ()); + + logMessage ("manual_clock"); + test_manual (); + + pass (); + } + + abstract_clock_tests () + : UnitTest ("abstract_clock", "beast", runManual) + { + } +}; + +static abstract_clock_tests abstract_clock_tests_; + +} diff --git a/src/beast/beast/chrono/impl/chrono_io.cpp b/src/beast/beast/chrono/impl/chrono_io.cpp new file mode 100644 index 000000000..b6004bb6e --- /dev/null +++ b/src/beast/beast/chrono/impl/chrono_io.cpp @@ -0,0 +1,41 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +// chrono_io +// +// (C) Copyright Howard Hinnant +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). + +#include "../chrono_io.h" + +//_LIBCPP_BEGIN_NAMESPACE_STD +namespace std { + +namespace chrono +{ + +locale::id +durationpunct::id; + +} // chrono + +//_LIBCPP_END_NAMESPACE_STD +} diff --git a/src/beast/beast/chrono/manual_clock.h b/src/beast/beast/chrono/manual_clock.h new file mode 100644 index 000000000..032be6130 --- /dev/null +++ b/src/beast/beast/chrono/manual_clock.h @@ -0,0 +1,92 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_CHRONO_MANUAL_CLOCK_H_INCLUDED +#define BEAST_CHRONO_MANUAL_CLOCK_H_INCLUDED + +#include "abstract_clock.h" + +namespace beast { + +/** Manual clock implementation. + This concrete class implements the @ref abstract_clock interface and + allows the time to be advanced manually, mainly for the purpose of + providing a clock in unit tests. + @tparam The length of time, in seconds, corresponding to one tick. +*/ +template +class manual_clock : public abstract_clock +{ +public: + using typename abstract_clock ::rep; + using typename abstract_clock ::duration; + using typename abstract_clock ::time_point; + + explicit manual_clock (time_point const& t = time_point (Duration (0))) + : m_now (t) + { + } + + bool is_steady () const + { + return IsSteady; + } + + time_point now () + { + return m_now; + } + + std::string to_string (time_point const& tp) + { + std::stringstream ss; + ss << tp.time_since_epoch() << " from start"; + return ss.str (); + } + + /** Set the current time of the manual clock. + Precondition: + ! IsSteady || t > now() + */ + void set (time_point const& t) + { + //if (IsSteady) + m_now = t; + } + + /** Convenience for setting the time using a duration in @ref rep units. */ + void set (rep v) + { + set (time_point (duration (v))); + } + + /** Convenience for advancing the clock by one. */ + manual_clock& operator++ () + { + m_now += duration (1); + return *this; + } + +private: + time_point m_now; +}; + +} + +#endif diff --git a/src/beast/beast/chrono/ratio_io.h b/src/beast/beast/chrono/ratio_io.h new file mode 100644 index 000000000..1a86e4fe8 --- /dev/null +++ b/src/beast/beast/chrono/ratio_io.h @@ -0,0 +1,622 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +// ratio_io +// +// (C) Copyright Howard Hinnant +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). + +#ifndef BEAST_CHRONO_RATIO_IO_H_INCLUDED +#define BEAST_CHRONO_RATIO_IO_H_INCLUDED + +/* + + ratio_io synopsis + +#include +#include + +namespace std +{ + +template +struct ratio_string +{ + static basic_string symbol(); + static basic_string prefix(); +}; + +} // std + +*/ + +#include +#include +#include + +//_LIBCPP_BEGIN_NAMESPACE_STD +namespace std { + +template +struct ratio_string +{ + static basic_string<_CharT> symbol() {return prefix();} + static basic_string<_CharT> prefix(); +}; + +template +basic_string<_CharT> +ratio_string<_Ratio, _CharT>::prefix() +{ + basic_ostringstream<_CharT> __os; + __os << _CharT('[') << _Ratio::num << _CharT('/') + << _Ratio::den << _CharT(']'); + return __os.str(); +} + +// atto + +template <> +struct ratio_string +{ + static string symbol() {return string(1, 'a');} + static string prefix() {return string("atto");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'a');} + static u16string prefix() {return u16string(u"atto");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'a');} + static u32string prefix() {return u32string(U"atto");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'a');} + static wstring prefix() {return wstring(L"atto");} +}; + +// femto + +template <> +struct ratio_string +{ + static string symbol() {return string(1, 'f');} + static string prefix() {return string("femto");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'f');} + static u16string prefix() {return u16string(u"femto");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'f');} + static u32string prefix() {return u32string(U"femto");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'f');} + static wstring prefix() {return wstring(L"femto");} +}; + +// pico + +template <> +struct ratio_string +{ + static string symbol() {return string(1, 'p');} + static string prefix() {return string("pico");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'p');} + static u16string prefix() {return u16string(u"pico");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'p');} + static u32string prefix() {return u32string(U"pico");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'p');} + static wstring prefix() {return wstring(L"pico");} +}; + +// nano + +template <> +struct ratio_string +{ + static string symbol() {return string(1, 'n');} + static string prefix() {return string("nano");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'n');} + static u16string prefix() {return u16string(u"nano");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'n');} + static u32string prefix() {return u32string(U"nano");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'n');} + static wstring prefix() {return wstring(L"nano");} +}; + +// micro + +template <> +struct ratio_string +{ + static string symbol() {return string("\xC2\xB5");} + static string prefix() {return string("micro");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'\xB5');} + static u16string prefix() {return u16string(u"micro");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'\xB5');} + static u32string prefix() {return u32string(U"micro");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'\xB5');} + static wstring prefix() {return wstring(L"micro");} +}; + +// milli + +template <> +struct ratio_string +{ + static string symbol() {return string(1, 'm');} + static string prefix() {return string("milli");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'm');} + static u16string prefix() {return u16string(u"milli");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'm');} + static u32string prefix() {return u32string(U"milli");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'm');} + static wstring prefix() {return wstring(L"milli");} +}; + +// centi + +template <> +struct ratio_string +{ + static string symbol() {return string(1, 'c');} + static string prefix() {return string("centi");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'c');} + static u16string prefix() {return u16string(u"centi");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'c');} + static u32string prefix() {return u32string(U"centi");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'c');} + static wstring prefix() {return wstring(L"centi");} +}; + +// deci + +template <> +struct ratio_string +{ + static string symbol() {return string(1, 'd');} + static string prefix() {return string("deci");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'd');} + static u16string prefix() {return u16string(u"deci");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'd');} + static u32string prefix() {return u32string(U"deci");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'd');} + static wstring prefix() {return wstring(L"deci");} +}; + +// deca + +template <> +struct ratio_string +{ + static string symbol() {return string("da");} + static string prefix() {return string("deca");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(u"da");} + static u16string prefix() {return u16string(u"deca");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(U"da");} + static u32string prefix() {return u32string(U"deca");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(L"da");} + static wstring prefix() {return wstring(L"deca");} +}; + +// hecto + +template <> +struct ratio_string +{ + static string symbol() {return string(1, 'h');} + static string prefix() {return string("hecto");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'h');} + static u16string prefix() {return u16string(u"hecto");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'h');} + static u32string prefix() {return u32string(U"hecto");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'h');} + static wstring prefix() {return wstring(L"hecto");} +}; + +// kilo + +template <> +struct ratio_string +{ + static string symbol() {return string(1, 'k');} + static string prefix() {return string("kilo");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'k');} + static u16string prefix() {return u16string(u"kilo");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'k');} + static u32string prefix() {return u32string(U"kilo");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'k');} + static wstring prefix() {return wstring(L"kilo");} +}; + +// mega + +template <> +struct ratio_string +{ + static string symbol() {return string(1, 'M');} + static string prefix() {return string("mega");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'M');} + static u16string prefix() {return u16string(u"mega");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'M');} + static u32string prefix() {return u32string(U"mega");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'M');} + static wstring prefix() {return wstring(L"mega");} +}; + +// giga + +template <> +struct ratio_string +{ + static string symbol() {return string(1, 'G');} + static string prefix() {return string("giga");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'G');} + static u16string prefix() {return u16string(u"giga");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'G');} + static u32string prefix() {return u32string(U"giga");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'G');} + static wstring prefix() {return wstring(L"giga");} +}; + +// tera + +template <> +struct ratio_string +{ + static string symbol() {return string(1, 'T');} + static string prefix() {return string("tera");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'T');} + static u16string prefix() {return u16string(u"tera");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'T');} + static u32string prefix() {return u32string(U"tera");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'T');} + static wstring prefix() {return wstring(L"tera");} +}; + +// peta + +template <> +struct ratio_string +{ + static string symbol() {return string(1, 'P');} + static string prefix() {return string("peta");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'P');} + static u16string prefix() {return u16string(u"peta");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'P');} + static u32string prefix() {return u32string(U"peta");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'P');} + static wstring prefix() {return wstring(L"peta");} +}; + +// exa + +template <> +struct ratio_string +{ + static string symbol() {return string(1, 'E');} + static string prefix() {return string("exa");} +}; + +#if HAS_UNICODE_SUPPORT + +template <> +struct ratio_string +{ + static u16string symbol() {return u16string(1, u'E');} + static u16string prefix() {return u16string(u"exa");} +}; + +template <> +struct ratio_string +{ + static u32string symbol() {return u32string(1, U'E');} + static u32string prefix() {return u32string(U"exa");} +}; + +#endif + +template <> +struct ratio_string +{ + static wstring symbol() {return wstring(1, L'E');} + static wstring prefix() {return wstring(L"exa");} +}; + +//_LIBCPP_END_NAMESPACE_STD +} + +#endif // _RATIO_IO