diff options
Diffstat (limited to 'boost/chrono')
35 files changed, 5386 insertions, 200 deletions
diff --git a/boost/chrono/chrono_io.hpp b/boost/chrono/chrono_io.hpp index 29a8d3493e..ebd18a3dab 100644 --- a/boost/chrono/chrono_io.hpp +++ b/boost/chrono/chrono_io.hpp @@ -14,6 +14,21 @@ #define BOOST_CHRONO_CHRONO_IO_HPP #include <boost/chrono/config.hpp> + +//#if BOOST_CHRONO_VERSION == 2 +//#include <boost/chrono/io/time_point_io.hpp> +//#include <boost/chrono/io/duration_io.hpp> +//#elif BOOST_CHRONO_VERSION == 1 +//#include <boost/chrono/io_v1/chrono_io.hpp> +//#endif + +#if defined BOOST_CHRONO_DONT_PROVIDES_DEPRECATED_IO_SINCE_V2_0_0 +#include <boost/chrono/io/time_point_io.hpp> +#include <boost/chrono/io/duration_io.hpp> +#else #include <boost/chrono/io_v1/chrono_io.hpp> +#endif + +#include <boost/chrono/io/utility/to_string.hpp> #endif // BOOST_CHRONO_CHRONO_IO_HPP diff --git a/boost/chrono/config.hpp b/boost/chrono/config.hpp index b7d0c0d198..1045ba3a79 100644 --- a/boost/chrono/config.hpp +++ b/boost/chrono/config.hpp @@ -2,6 +2,7 @@ // Copyright Beman Dawes 2003, 2006, 2008 // Copyright 2009-2011 Vicente J. Botet Escriba +// Copyright (c) Microsoft Corporation 2014 // Distributed under 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) @@ -12,6 +13,7 @@ #define BOOST_CHRONO_CONFIG_HPP #include <boost/config.hpp> +#include <boost/predef.h> #if !defined BOOST_CHRONO_VERSION #define BOOST_CHRONO_VERSION 1 @@ -25,6 +27,13 @@ #define BOOST_USE_WINDOWS_H #endif +#if ! defined BOOST_CHRONO_PROVIDES_DATE_IO_FOR_SYSTEM_CLOCK_TIME_POINT \ + && ! defined BOOST_CHRONO_DONT_PROVIDE_DATE_IO_FOR_SYSTEM_CLOCK_TIME_POINT + +# define BOOST_CHRONO_PROVIDES_DATE_IO_FOR_SYSTEM_CLOCK_TIME_POINT + +#endif + // BOOST_CHRONO_POSIX_API, BOOST_CHRONO_MAC_API, or BOOST_CHRONO_WINDOWS_API // can be defined by the user to specify which API should be used @@ -57,13 +66,16 @@ # define BOOST_CHRONO_HAS_PROCESS_CLOCKS # endif # define BOOST_CHRONO_HAS_CLOCK_STEADY -# define BOOST_CHRONO_HAS_THREAD_CLOCK +# if BOOST_PLAT_WINDOWS_DESKTOP +# define BOOST_CHRONO_HAS_THREAD_CLOCK +# endif # define BOOST_CHRONO_THREAD_CLOCK_IS_STEADY true # endif # if defined( BOOST_CHRONO_MAC_API ) # define BOOST_CHRONO_HAS_PROCESS_CLOCKS # define BOOST_CHRONO_HAS_CLOCK_STEADY +# define BOOST_CHRONO_HAS_THREAD_CLOCK # define BOOST_CHRONO_THREAD_CLOCK_IS_STEADY true # endif @@ -85,10 +97,13 @@ # undef BOOST_CHRONO_HAS_THREAD_CLOCK # undef BOOST_CHRONO_THREAD_CLOCK_IS_STEADY # endif -# if defined(__HP_aCC) && defined(__hpux) +# if (defined(__HP_aCC) || defined(__GNUC__)) && defined(__hpux) # undef BOOST_CHRONO_HAS_THREAD_CLOCK # undef BOOST_CHRONO_THREAD_CLOCK_IS_STEADY # endif +# if defined(__VXWORKS__) +# undef BOOST_CHRONO_HAS_PROCESS_CLOCKS +# endif # endif #if defined(BOOST_CHRONO_THREAD_DISABLED) && defined(BOOST_CHRONO_HAS_THREAD_CLOCK) @@ -96,21 +111,53 @@ #undef BOOST_CHRONO_THREAD_CLOCK_IS_STEADY #endif -//#undef BOOST_CHRONO_HAS_PROCESS_CLOCKS - // unicode support ------------------------------// -#if defined(BOOST_NO_UNICODE_LITERALS) || defined(BOOST_NO_CHAR16_T) || defined(BOOST_NO_CHAR32_T) +#if defined(BOOST_NO_CXX11_UNICODE_LITERALS) || defined(BOOST_NO_CXX11_CHAR16_T) || defined(BOOST_NO_CXX11_CHAR32_T) //~ #define BOOST_CHRONO_HAS_UNICODE_SUPPORT #else #define BOOST_CHRONO_HAS_UNICODE_SUPPORT 1 #endif -#if ! defined BOOST_NOEXCEPT -#if defined(BOOST_NO_NOEXCEPT) -#define BOOST_NOEXCEPT +#ifndef BOOST_CHRONO_LIB_CONSTEXPR +#if defined( BOOST_NO_CXX11_NUMERIC_LIMITS ) +#define BOOST_CHRONO_LIB_CONSTEXPR +#elif defined(_LIBCPP_VERSION) && !defined(_LIBCPP_CONSTEXPR) + #define BOOST_CHRONO_LIB_CONSTEXPR +#else + #define BOOST_CHRONO_LIB_CONSTEXPR BOOST_CONSTEXPR +#endif +#endif + +#if defined( BOOST_NO_CXX11_NUMERIC_LIMITS ) +# define BOOST_CHRONO_LIB_NOEXCEPT_OR_THROW throw() +#else +#ifdef BOOST_NO_CXX11_NOEXCEPT +# define BOOST_CHRONO_LIB_NOEXCEPT_OR_THROW throw() #else -#define BOOST_NOEXCEPT noexcept +# define BOOST_CHRONO_LIB_NOEXCEPT_OR_THROW noexcept +#endif +#endif + +#if defined BOOST_CHRONO_PROVIDE_HYBRID_ERROR_HANDLING \ + && defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING +#error "BOOST_CHRONO_PROVIDE_HYBRID_ERROR_HANDLING && BOOST_CHRONO_PROVIDE_HYBRID_ERROR_HANDLING defined" +#endif + +#if defined BOOST_CHRONO_PROVIDES_DEPRECATED_IO_SINCE_V2_0_0 \ + && defined BOOST_CHRONO_DONT_PROVIDES_DEPRECATED_IO_SINCE_V2_0_0 +#error "BOOST_CHRONO_PROVIDES_DEPRECATED_IO_SINCE_V2_0_0 && BOOST_CHRONO_DONT_PROVIDES_DEPRECATED_IO_SINCE_V2_0_0 defined" +#endif + +#if ! defined BOOST_CHRONO_PROVIDE_HYBRID_ERROR_HANDLING \ + && ! defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING +#define BOOST_CHRONO_PROVIDE_HYBRID_ERROR_HANDLING +#endif + +#if (BOOST_CHRONO_VERSION == 2) +#if ! defined BOOST_CHRONO_PROVIDES_DEPRECATED_IO_SINCE_V2_0_0 \ + && ! defined BOOST_CHRONO_DONT_PROVIDES_DEPRECATED_IO_SINCE_V2_0_0 +#define BOOST_CHRONO_DONT_PROVIDES_DEPRECATED_IO_SINCE_V2_0_0 #endif #endif @@ -143,7 +190,7 @@ #define BOOST_CHRONO_DECL #endif -//#define BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING + // enable automatic library variant selection ------------------------------// @@ -166,3 +213,4 @@ #endif // auto-linking disabled #endif // BOOST_CHRONO_HEADER_ONLY #endif // BOOST_CHRONO_CONFIG_HPP + diff --git a/boost/chrono/detail/inlined/mac/process_cpu_clocks.hpp b/boost/chrono/detail/inlined/mac/process_cpu_clocks.hpp index 48753bdfc7..6d09e2cb3a 100644 --- a/boost/chrono/detail/inlined/mac/process_cpu_clocks.hpp +++ b/boost/chrono/detail/inlined/mac/process_cpu_clocks.hpp @@ -48,7 +48,7 @@ namespace boost process_real_cpu_clock::time_point process_real_cpu_clock::now() BOOST_NOEXCEPT { -#if 0 +#if 1 tms tm; clock_t c = ::times(&tm); if (c == clock_t(-1)) // error @@ -71,10 +71,18 @@ namespace boost if (c == clock_t(-1)) // error { BOOST_ASSERT(0 && "Boost::Chrono - Internal Error"); + } else + { + long factor = chrono_detail::tick_factor(); + if (factor != -1) + { + return time_point(nanoseconds(c * factor)); + } else + { + BOOST_ASSERT(0 && "Boost::Chrono - Internal Error"); + } } - return time_point( - duration(c*(1000000000l/CLOCKS_PER_SEC)) - ); + return time_point(); #endif } @@ -82,7 +90,7 @@ namespace boost process_real_cpu_clock::time_point process_real_cpu_clock::now(system::error_code & ec) { -#if 0 +#if 1 tms tm; clock_t c = ::times(&tm); if (c == clock_t(-1)) // error @@ -129,11 +137,28 @@ namespace boost ec.assign(errno, BOOST_CHRONO_SYSTEM_CATEGORY); return time_point(); } + } else + { + long factor = chrono_detail::tick_factor(); + if (factor != -1) + { + if (!BOOST_CHRONO_IS_THROWS(ec)) + { + ec.clear(); + } + return time_point(nanoseconds(c * factor)); + } else + { + if (BOOST_CHRONO_IS_THROWS(ec)) + { + boost::throw_exception(system::system_error(errno, BOOST_CHRONO_SYSTEM_CATEGORY, "chrono::process_real_cpu_clock")); + } else + { + ec.assign(errno, BOOST_CHRONO_SYSTEM_CATEGORY); + return time_point(); + } + } } - return time_point( - duration(c*(1000000000l/CLOCKS_PER_SEC)) - ); - #endif } diff --git a/boost/chrono/detail/inlined/mac/thread_clock.hpp b/boost/chrono/detail/inlined/mac/thread_clock.hpp index dad806e4e2..1a4406b83d 100644 --- a/boost/chrono/detail/inlined/mac/thread_clock.hpp +++ b/boost/chrono/detail/inlined/mac/thread_clock.hpp @@ -1,6 +1,8 @@ // boost thread_clock.cpp -----------------------------------------------------------// -// Copyright Vicente J. Botet Escriba 2010 +// Copyright Beman Dawes 1994, 2006, 2008 +// Copyright Vicente J. Botet Escriba 2009-2011 +// Copyright Christopher Brown 2013 // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt @@ -10,6 +12,80 @@ //--------------------------------------------------------------------------------------// #include <boost/chrono/config.hpp> -#include <boost/chrono/detail/inlined/posix/thread_clock.hpp> +#include <boost/chrono/thread_clock.hpp> #include <cassert> +# include <pthread.h> +# include <mach/thread_act.h> + +namespace boost { namespace chrono { + + thread_clock::time_point thread_clock::now( ) BOOST_NOEXCEPT + { + // get the thread port (borrowing pthread's reference) + mach_port_t port = pthread_mach_thread_np(pthread_self()); + + // get the thread info + thread_basic_info_data_t info; + mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT; + if ( thread_info(port, THREAD_BASIC_INFO, (thread_info_t)&info, &count) != KERN_SUCCESS ) + { + BOOST_ASSERT(0 && "Boost::Chrono - Internal Error"); + return time_point(); + } + + // convert to nanoseconds + duration user = duration( + static_cast<thread_clock::rep>( info.user_time.seconds ) * 1000000000 + + static_cast<thread_clock::rep>(info.user_time.microseconds ) * 1000); + + duration system = duration( + static_cast<thread_clock::rep>( info.system_time.seconds ) * 1000000000 + + static_cast<thread_clock::rep>( info.system_time.microseconds ) * 1000); + + return time_point( user + system ); + } + +#if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING + thread_clock::time_point thread_clock::now( system::error_code & ec ) + { + // get the thread port (borrowing pthread's reference) + mach_port_t port = pthread_mach_thread_np(pthread_self()); + + // get the thread info + thread_basic_info_data_t info; + mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT; + if ( thread_info(port, THREAD_BASIC_INFO, (thread_info_t)&info, &count) != KERN_SUCCESS ) + { + if (BOOST_CHRONO_IS_THROWS(ec)) + { + boost::throw_exception( + system::system_error( + EINVAL, + BOOST_CHRONO_SYSTEM_CATEGORY, + "chrono::thread_clock" )); + } + else + { + ec.assign( errno, BOOST_CHRONO_SYSTEM_CATEGORY ); + return time_point(); + } + } + if (!BOOST_CHRONO_IS_THROWS(ec)) + { + ec.clear(); + } + + // convert to nanoseconds + duration user = duration( + static_cast<thread_clock::rep>( info.user_time.seconds ) * 1000000000 + + static_cast<thread_clock::rep>(info.user_time.microseconds ) * 1000); + + duration system = duration( + static_cast<thread_clock::rep>( info.system_time.seconds ) * 1000000000 + + static_cast<thread_clock::rep>( info.system_time.microseconds ) * 1000); + + return time_point( user + system ); + } +#endif +} } diff --git a/boost/chrono/detail/inlined/posix/process_cpu_clocks.hpp b/boost/chrono/detail/inlined/posix/process_cpu_clocks.hpp index 5d5c4f4806..0476f590c9 100644 --- a/boost/chrono/detail/inlined/posix/process_cpu_clocks.hpp +++ b/boost/chrono/detail/inlined/posix/process_cpu_clocks.hpp @@ -22,7 +22,7 @@ namespace boost { namespace chrono { namespace chrono_detail { - inline long tick_factor() // multiplier to convert ticks + inline nanoseconds::rep tick_factor() // multiplier to convert ticks // to nanoseconds; -1 if unknown { static long factor = 0; @@ -281,12 +281,13 @@ process_cpu_clock::time_point process_cpu_clock::now() BOOST_NOEXCEPT } else { - if ( chrono_detail::tick_factor() != -1 ) + nanoseconds::rep factor = chrono_detail::tick_factor(); + if ( factor != -1 ) { time_point::rep r( - 1000*c*chrono_detail::tick_factor(), - 1000*(tm.tms_utime + tm.tms_cutime)*chrono_detail::tick_factor(), - 1000*(tm.tms_stime + tm.tms_cstime)*chrono_detail::tick_factor()); + c*factor, + (tm.tms_utime + tm.tms_cutime)*factor, + (tm.tms_stime + tm.tms_cstime)*factor); return time_point(duration(r)); } else @@ -324,9 +325,9 @@ process_cpu_clock::time_point process_cpu_clock::now( if ( chrono_detail::tick_factor() != -1 ) { time_point::rep r( - 1000*c*chrono_detail::tick_factor(), - 1000*(tm.tms_utime + tm.tms_cutime)*chrono_detail::tick_factor(), - 1000*(tm.tms_stime + tm.tms_cstime)*chrono_detail::tick_factor()); + c*chrono_detail::tick_factor(), + (tm.tms_utime + tm.tms_cutime)*chrono_detail::tick_factor(), + (tm.tms_stime + tm.tms_cstime)*chrono_detail::tick_factor()); return time_point(duration(r)); } else diff --git a/boost/chrono/detail/inlined/posix/thread_clock.hpp b/boost/chrono/detail/inlined/posix/thread_clock.hpp index 42a544a0d6..a1012240ec 100644 --- a/boost/chrono/detail/inlined/posix/thread_clock.hpp +++ b/boost/chrono/detail/inlined/posix/thread_clock.hpp @@ -14,7 +14,9 @@ #include <boost/chrono/thread_clock.hpp> #include <cassert> +#if !defined(__VXWORKS__) # include <sys/times.h> +#endif # include <pthread.h> # include <unistd.h> diff --git a/boost/chrono/detail/inlined/win/chrono.hpp b/boost/chrono/detail/inlined/win/chrono.hpp index 75160dba97..16e8c51426 100644 --- a/boost/chrono/detail/inlined/win/chrono.hpp +++ b/boost/chrono/detail/inlined/win/chrono.hpp @@ -12,9 +12,9 @@ #ifndef BOOST_CHRONO_DETAIL_INLINED_WIN_CHRONO_HPP #define BOOST_CHRONO_DETAIL_INLINED_WIN_CHRONO_HPP -#include <boost/detail/win/time.hpp> -#include <boost/detail/win/timers.hpp> -#include <boost/detail/win/GetLastError.hpp> +#include <boost/detail/winapi/time.hpp> +#include <boost/detail/winapi/timers.hpp> +#include <boost/detail/winapi/GetLastError.hpp> namespace boost { @@ -25,8 +25,8 @@ namespace chrono_detail BOOST_CHRONO_INLINE double get_nanosecs_per_tic() BOOST_NOEXCEPT { - boost::detail::win32::LARGE_INTEGER_ freq; - if ( !boost::detail::win32::QueryPerformanceFrequency( &freq ) ) + boost::detail::winapi::LARGE_INTEGER_ freq; + if ( !boost::detail::winapi::QueryPerformanceFrequency( &freq ) ) return 0.0L; return double(1000000000.0L / freq.QuadPart); } @@ -35,15 +35,23 @@ namespace chrono_detail steady_clock::time_point steady_clock::now() BOOST_NOEXCEPT { - static double nanosecs_per_tic = chrono_detail::get_nanosecs_per_tic(); + double nanosecs_per_tic = chrono_detail::get_nanosecs_per_tic(); - boost::detail::win32::LARGE_INTEGER_ pcount; - if ( (nanosecs_per_tic <= 0.0L) || - (!boost::detail::win32::QueryPerformanceCounter( &pcount )) ) + boost::detail::winapi::LARGE_INTEGER_ pcount; + if ( nanosecs_per_tic <= 0.0L ) { - BOOST_ASSERT(0 && "Boost::Chrono - Internal Error"); + BOOST_ASSERT(0 && "Boost::Chrono - get_nanosecs_per_tic Internal Error"); return steady_clock::time_point(); } + unsigned times=0; + while ( ! boost::detail::winapi::QueryPerformanceCounter( &pcount ) ) + { + if ( ++times > 3 ) + { + BOOST_ASSERT(0 && "Boost::Chrono - QueryPerformanceCounter Internal Error"); + return steady_clock::time_point(); + } + } return steady_clock::time_point(steady_clock::duration( static_cast<steady_clock::rep>((nanosecs_per_tic) * pcount.QuadPart))); @@ -53,16 +61,16 @@ namespace chrono_detail #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING steady_clock::time_point steady_clock::now( system::error_code & ec ) { - static double nanosecs_per_tic = chrono_detail::get_nanosecs_per_tic(); + double nanosecs_per_tic = chrono_detail::get_nanosecs_per_tic(); - boost::detail::win32::LARGE_INTEGER_ pcount; + boost::detail::winapi::LARGE_INTEGER_ pcount; if ( (nanosecs_per_tic <= 0.0L) - || (!boost::detail::win32::QueryPerformanceCounter( &pcount )) ) + || (!boost::detail::winapi::QueryPerformanceCounter( &pcount )) ) { - boost::detail::win32::DWORD_ cause = + boost::detail::winapi::DWORD_ cause = ((nanosecs_per_tic <= 0.0L) ? ERROR_NOT_SUPPORTED - : boost::detail::win32::GetLastError()); + : boost::detail::winapi::GetLastError()); if (BOOST_CHRONO_IS_THROWS(ec)) { boost::throw_exception( system::system_error( @@ -89,38 +97,33 @@ namespace chrono_detail BOOST_CHRONO_INLINE system_clock::time_point system_clock::now() BOOST_NOEXCEPT { - boost::detail::win32::FILETIME_ ft; - #if defined(UNDER_CE) - // Windows CE does not define GetSystemTimeAsFileTime so we do it in two steps. - boost::detail::win32::SYSTEMTIME_ st; - boost::detail::win32::GetSystemTime( &st ); - boost::detail::win32::SystemTimeToFileTime( &st, &ft ); - #else - boost::detail::win32::GetSystemTimeAsFileTime( &ft ); // never fails - #endif - return system_clock::time_point(system_clock::duration( - (static_cast<__int64>( ft.dwHighDateTime ) << 32) | ft.dwLowDateTime)); + boost::detail::winapi::FILETIME_ ft; + boost::detail::winapi::GetSystemTimeAsFileTime( &ft ); // never fails + return system_clock::time_point( + system_clock::duration( + ((static_cast<__int64>( ft.dwHighDateTime ) << 32) | ft.dwLowDateTime) + - 116444736000000000LL + //- (134775LL*864000000000LL) + ) + ); } #if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING BOOST_CHRONO_INLINE system_clock::time_point system_clock::now( system::error_code & ec ) { - boost::detail::win32::FILETIME_ ft; - #if defined(UNDER_CE) - // Windows CE does not define GetSystemTimeAsFileTime so we do it in two steps. - boost::detail::win32::SYSTEMTIME_ st; - boost::detail::win32::GetSystemTime( &st ); - boost::detail::win32::SystemTimeToFileTime( &st, &ft ); - #else - boost::detail::win32::GetSystemTimeAsFileTime( &ft ); // never fails - #endif + boost::detail::winapi::FILETIME_ ft; + boost::detail::winapi::GetSystemTimeAsFileTime( &ft ); // never fails if (!BOOST_CHRONO_IS_THROWS(ec)) { ec.clear(); } - return time_point(duration( - (static_cast<__int64>( ft.dwHighDateTime ) << 32) | ft.dwLowDateTime)); + return system_clock::time_point( + system_clock::duration( + ((static_cast<__int64>( ft.dwHighDateTime ) << 32) | ft.dwLowDateTime) + - 116444736000000000LL + //- (134775LL*864000000000LL) + )); } #endif @@ -128,13 +131,6 @@ namespace chrono_detail std::time_t system_clock::to_time_t(const system_clock::time_point& t) BOOST_NOEXCEPT { __int64 temp = t.time_since_epoch().count(); - - # if (!defined( BOOST_MSVC )) || (BOOST_MSVC > 1300) // > VC++ 7.0 - temp -= 116444736000000000LL; // delta from epoch in microseconds - # else - temp -= 116444736000000000; - # endif - temp /= 10000000; return static_cast<std::time_t>( temp ); } @@ -144,13 +140,6 @@ namespace chrono_detail { __int64 temp = t; temp *= 10000000; - - # if (!defined( BOOST_MSVC )) || (BOOST_MSVC > 1300) // > VC++ 7.0 - temp += 116444736000000000LL; - # else - temp += 116444736000000000; - # endif - return time_point(duration(temp)); } diff --git a/boost/chrono/detail/inlined/win/process_cpu_clocks.hpp b/boost/chrono/detail/inlined/win/process_cpu_clocks.hpp index 1b7e67a120..e97bfe590c 100644 --- a/boost/chrono/detail/inlined/win/process_cpu_clocks.hpp +++ b/boost/chrono/detail/inlined/win/process_cpu_clocks.hpp @@ -2,6 +2,7 @@ // Copyright Beman Dawes 1994, 2006, 2008 // Copyright 2009-2010 Vicente J. Botet Escriba +// Copyright (c) Microsoft Corporation 2014 // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt @@ -18,9 +19,11 @@ #include <cassert> #include <time.h> -#include <boost/detail/win/GetLastError.hpp> -#include <boost/detail/win/GetCurrentProcess.hpp> -#include <boost/detail/win/GetProcessTimes.hpp> +#include <boost/detail/winapi/GetLastError.hpp> +#include <boost/detail/winapi/GetCurrentProcess.hpp> +#if BOOST_PLAT_WINDOWS_DESKTOP +#include <boost/detail/winapi/GetProcessTimes.hpp> +#endif namespace boost { @@ -64,14 +67,15 @@ process_real_cpu_clock::time_point process_real_cpu_clock::now( } #endif +#if BOOST_PLAT_WINDOWS_DESKTOP process_user_cpu_clock::time_point process_user_cpu_clock::now() BOOST_NOEXCEPT { // note that Windows uses 100 nanosecond ticks for FILETIME - boost::detail::win32::FILETIME_ creation, exit, user_time, system_time; + boost::detail::winapi::FILETIME_ creation, exit, user_time, system_time; - if ( boost::detail::win32::GetProcessTimes( - boost::detail::win32::GetCurrentProcess(), &creation, &exit, + if ( boost::detail::winapi::GetProcessTimes( + boost::detail::winapi::GetCurrentProcess(), &creation, &exit, &system_time, &user_time ) ) { return time_point(duration( @@ -93,10 +97,10 @@ process_user_cpu_clock::time_point process_user_cpu_clock::now( { // note that Windows uses 100 nanosecond ticks for FILETIME - boost::detail::win32::FILETIME_ creation, exit, user_time, system_time; + boost::detail::winapi::FILETIME_ creation, exit, user_time, system_time; - if ( boost::detail::win32::GetProcessTimes( - boost::detail::win32::GetCurrentProcess(), &creation, &exit, + if ( boost::detail::winapi::GetProcessTimes( + boost::detail::winapi::GetCurrentProcess(), &creation, &exit, &system_time, &user_time ) ) { if (!BOOST_CHRONO_IS_THROWS(ec)) @@ -110,7 +114,7 @@ process_user_cpu_clock::time_point process_user_cpu_clock::now( } else { - boost::detail::win32::DWORD_ cause = boost::detail::win32::GetLastError(); + boost::detail::winapi::DWORD_ cause = boost::detail::winapi::GetLastError(); if (BOOST_CHRONO_IS_THROWS(ec)) { boost::throw_exception( @@ -133,10 +137,10 @@ process_system_cpu_clock::time_point process_system_cpu_clock::now() BOOST_NOEXC { // note that Windows uses 100 nanosecond ticks for FILETIME - boost::detail::win32::FILETIME_ creation, exit, user_time, system_time; + boost::detail::winapi::FILETIME_ creation, exit, user_time, system_time; - if ( boost::detail::win32::GetProcessTimes( - boost::detail::win32::GetCurrentProcess(), &creation, &exit, + if ( boost::detail::winapi::GetProcessTimes( + boost::detail::winapi::GetCurrentProcess(), &creation, &exit, &system_time, &user_time ) ) { return time_point(duration( @@ -158,10 +162,10 @@ process_system_cpu_clock::time_point process_system_cpu_clock::now( { // note that Windows uses 100 nanosecond ticks for FILETIME - boost::detail::win32::FILETIME_ creation, exit, user_time, system_time; + boost::detail::winapi::FILETIME_ creation, exit, user_time, system_time; - if ( boost::detail::win32::GetProcessTimes( - boost::detail::win32::GetCurrentProcess(), &creation, &exit, + if ( boost::detail::winapi::GetProcessTimes( + boost::detail::winapi::GetCurrentProcess(), &creation, &exit, &system_time, &user_time ) ) { if (!BOOST_CHRONO_IS_THROWS(ec)) @@ -175,7 +179,7 @@ process_system_cpu_clock::time_point process_system_cpu_clock::now( } else { - boost::detail::win32::DWORD_ cause = boost::detail::win32::GetLastError(); + boost::detail::winapi::DWORD_ cause = boost::detail::winapi::GetLastError(); if (BOOST_CHRONO_IS_THROWS(ec)) { boost::throw_exception( @@ -198,10 +202,10 @@ process_cpu_clock::time_point process_cpu_clock::now() BOOST_NOEXCEPT { // note that Windows uses 100 nanosecond ticks for FILETIME - boost::detail::win32::FILETIME_ creation, exit, user_time, system_time; + boost::detail::winapi::FILETIME_ creation, exit, user_time, system_time; - if ( boost::detail::win32::GetProcessTimes( - boost::detail::win32::GetCurrentProcess(), &creation, &exit, + if ( boost::detail::winapi::GetProcessTimes( + boost::detail::winapi::GetCurrentProcess(), &creation, &exit, &system_time, &user_time ) ) { time_point::rep r(process_real_cpu_clock::now().time_since_epoch().count() @@ -229,10 +233,10 @@ process_cpu_clock::time_point process_cpu_clock::now( { // note that Windows uses 100 nanosecond ticks for FILETIME - boost::detail::win32::FILETIME_ creation, exit, user_time, system_time; + boost::detail::winapi::FILETIME_ creation, exit, user_time, system_time; - if ( boost::detail::win32::GetProcessTimes( - boost::detail::win32::GetCurrentProcess(), &creation, &exit, + if ( boost::detail::winapi::GetProcessTimes( + boost::detail::winapi::GetCurrentProcess(), &creation, &exit, &system_time, &user_time ) ) { if (!BOOST_CHRONO_IS_THROWS(ec)) @@ -252,7 +256,7 @@ process_cpu_clock::time_point process_cpu_clock::now( } else { - boost::detail::win32::DWORD_ cause = boost::detail::win32::GetLastError(); + boost::detail::winapi::DWORD_ cause = boost::detail::winapi::GetLastError(); if (BOOST_CHRONO_IS_THROWS(ec)) { boost::throw_exception( @@ -270,6 +274,7 @@ process_cpu_clock::time_point process_cpu_clock::now( } #endif +#endif } // namespace chrono } // namespace boost diff --git a/boost/chrono/detail/inlined/win/thread_clock.hpp b/boost/chrono/detail/inlined/win/thread_clock.hpp index 8ca1506ce5..e47c481473 100644 --- a/boost/chrono/detail/inlined/win/thread_clock.hpp +++ b/boost/chrono/detail/inlined/win/thread_clock.hpp @@ -15,9 +15,9 @@ #include <boost/chrono/thread_clock.hpp> #include <cassert> -#include <boost/detail/win/GetLastError.hpp> -#include <boost/detail/win/GetCurrentThread.hpp> -#include <boost/detail/win/GetThreadTimes.hpp> +#include <boost/detail/winapi/GetLastError.hpp> +#include <boost/detail/winapi/GetCurrentThread.hpp> +#include <boost/detail/winapi/GetThreadTimes.hpp> namespace boost { @@ -28,10 +28,10 @@ namespace chrono thread_clock::time_point thread_clock::now( system::error_code & ec ) { // note that Windows uses 100 nanosecond ticks for FILETIME - boost::detail::win32::FILETIME_ creation, exit, user_time, system_time; + boost::detail::winapi::FILETIME_ creation, exit, user_time, system_time; - if ( boost::detail::win32::GetThreadTimes( - boost::detail::win32::GetCurrentThread (), &creation, &exit, + if ( boost::detail::winapi::GetThreadTimes( + boost::detail::winapi::GetCurrentThread (), &creation, &exit, &system_time, &user_time ) ) { duration user = duration( @@ -55,13 +55,13 @@ thread_clock::time_point thread_clock::now( system::error_code & ec ) { boost::throw_exception( system::system_error( - boost::detail::win32::GetLastError(), + boost::detail::winapi::GetLastError(), BOOST_CHRONO_SYSTEM_CATEGORY, "chrono::thread_clock" )); } else { - ec.assign( boost::detail::win32::GetLastError(), BOOST_CHRONO_SYSTEM_CATEGORY ); + ec.assign( boost::detail::winapi::GetLastError(), BOOST_CHRONO_SYSTEM_CATEGORY ); return thread_clock::time_point(duration(0)); } } @@ -72,10 +72,10 @@ thread_clock::time_point thread_clock::now() BOOST_NOEXCEPT { // note that Windows uses 100 nanosecond ticks for FILETIME - boost::detail::win32::FILETIME_ creation, exit, user_time, system_time; + boost::detail::winapi::FILETIME_ creation, exit, user_time, system_time; - if ( boost::detail::win32::GetThreadTimes( - boost::detail::win32::GetCurrentThread (), &creation, &exit, + if ( boost::detail::winapi::GetThreadTimes( + boost::detail::winapi::GetCurrentThread (), &creation, &exit, &system_time, &user_time ) ) { duration user = duration( diff --git a/boost/chrono/detail/no_warning/signed_unsigned_cmp.hpp b/boost/chrono/detail/no_warning/signed_unsigned_cmp.hpp index 491c1d64a0..94936c8baf 100644 --- a/boost/chrono/detail/no_warning/signed_unsigned_cmp.hpp +++ b/boost/chrono/detail/no_warning/signed_unsigned_cmp.hpp @@ -19,6 +19,10 @@ #if defined(__GNUC__) && (__GNUC__ >= 4) #pragma GCC system_header +#elif defined __SUNPRO_CC +#pragma disable_warn +#elif defined _MSC_VER +#pragma warning(push, 1) #endif namespace boost { @@ -41,4 +45,10 @@ namespace detail { } // namespace detail } // namespace chrono +#if defined __SUNPRO_CC +#pragma enable_warn +#elif defined _MSC_VER +#pragma warning(pop) +#endif + #endif // BOOST_CHRONO_DETAIL_NO_WARNING_SIGNED_UNSIGNED_CMP_HPP diff --git a/boost/chrono/detail/scan_keyword.hpp b/boost/chrono/detail/scan_keyword.hpp index 7c3ba6e2af..aa4e2e87b9 100644 --- a/boost/chrono/detail/scan_keyword.hpp +++ b/boost/chrono/detail/scan_keyword.hpp @@ -19,14 +19,14 @@ #include <boost/chrono/config.hpp> -#include <boost/interprocess/smart_ptr/unique_ptr.hpp> +#include <boost/move/unique_ptr.hpp> #include <ios> #include <exception> #include <stdlib.h> #include <boost/throw_exception.hpp> namespace boost { - using interprocess::unique_ptr; + using movelib::unique_ptr; namespace chrono { namespace chrono_detail { diff --git a/boost/chrono/detail/static_assert.hpp b/boost/chrono/detail/static_assert.hpp index 1ad21a56ba..8615194754 100644 --- a/boost/chrono/detail/static_assert.hpp +++ b/boost/chrono/detail/static_assert.hpp @@ -11,7 +11,7 @@ #include <boost/chrono/config.hpp> -#ifndef BOOST_NO_STATIC_ASSERT +#ifndef BOOST_NO_CXX11_STATIC_ASSERT #define BOOST_CHRONO_STATIC_ASSERT(CND, MSG, TYPES) static_assert(CND,MSG) #elif defined(BOOST_CHRONO_USES_STATIC_ASSERT) #include <boost/static_assert.hpp> diff --git a/boost/chrono/duration.hpp b/boost/chrono/duration.hpp index e32357cc72..814adb0e91 100644 --- a/boost/chrono/duration.hpp +++ b/boost/chrono/duration.hpp @@ -51,7 +51,7 @@ time2_demo contained this comment: #include <boost/detail/workaround.hpp> #include <boost/integer_traits.hpp> -#if !defined(BOOST_NO_STATIC_ASSERT) || !defined(BOOST_CHRONO_USES_MPL_ASSERT) +#if !defined(BOOST_NO_CXX11_STATIC_ASSERT) || !defined(BOOST_CHRONO_USES_MPL_ASSERT) #define BOOST_CHRONO_A_DURATION_REPRESENTATION_CAN_NOT_BE_A_DURATION "A duration representation can not be a duration" #define BOOST_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_DURATION_MUST_BE_A_STD_RATIO "Second template parameter of duration must be a boost::ratio" #define BOOST_CHRONO_DURATION_PERIOD_MUST_BE_POSITIVE "duration period must be positive" @@ -340,17 +340,17 @@ namespace detail namespace detail { template <class T, bool = is_arithmetic<T>::value> struct chrono_numeric_limits { - static T lowest() throw() {return (std::numeric_limits<T>::min) ();} + static BOOST_CHRONO_LIB_CONSTEXPR T lowest() BOOST_CHRONO_LIB_NOEXCEPT_OR_THROW {return (std::numeric_limits<T>::min) ();} }; template <class T> struct chrono_numeric_limits<T,true> { - static T lowest() throw() {return (std::numeric_limits<T>::min) ();} + static BOOST_CHRONO_LIB_CONSTEXPR T lowest() BOOST_CHRONO_LIB_NOEXCEPT_OR_THROW {return (std::numeric_limits<T>::min) ();} }; template <> struct chrono_numeric_limits<float,true> { - static float lowest() throw() + static BOOST_CHRONO_LIB_CONSTEXPR float lowest() BOOST_CHRONO_LIB_NOEXCEPT_OR_THROW { return -(std::numeric_limits<float>::max) (); } @@ -358,7 +358,7 @@ namespace detail { template <> struct chrono_numeric_limits<double,true> { - static double lowest() throw() + static BOOST_CHRONO_LIB_CONSTEXPR double lowest() BOOST_CHRONO_LIB_NOEXCEPT_OR_THROW { return -(std::numeric_limits<double>::max) (); } @@ -366,7 +366,7 @@ namespace detail { template <> struct chrono_numeric_limits<long double,true> { - static long double lowest() throw() + static BOOST_CHRONO_LIB_CONSTEXPR long double lowest() BOOST_CHRONO_LIB_NOEXCEPT_OR_THROW { return -(std::numeric_limits<long double>::max)(); } @@ -381,12 +381,12 @@ template <class Rep> struct duration_values { static BOOST_CONSTEXPR Rep zero() {return Rep(0);} - static BOOST_CONSTEXPR Rep max BOOST_PREVENT_MACRO_SUBSTITUTION () + static BOOST_CHRONO_LIB_CONSTEXPR Rep max BOOST_PREVENT_MACRO_SUBSTITUTION () { return (std::numeric_limits<Rep>::max)(); } - static BOOST_CONSTEXPR Rep min BOOST_PREVENT_MACRO_SUBSTITUTION () + static BOOST_CHRONO_LIB_CONSTEXPR Rep min BOOST_PREVENT_MACRO_SUBSTITUTION () { return detail::numeric_limits<Rep>::lowest(); } @@ -417,7 +417,7 @@ struct common_type<chrono::duration<Rep1, Period1>, namespace chrono { template <class Rep, class Period> - class duration + class BOOST_SYMBOL_VISIBLE duration { //BOOST_CHRONO_STATIC_ASSERT(boost::is_integral<Rep>::value, BOOST_CHRONO_A_DURATION_REPRESENTATION_MUST_BE_INTEGRAL, ()); BOOST_CHRONO_STATIC_ASSERT(!boost::chrono::detail::is_duration<Rep>::value, @@ -433,10 +433,10 @@ namespace chrono { rep rep_; public: - BOOST_CONSTEXPR + BOOST_FORCEINLINE BOOST_CONSTEXPR duration() : rep_(duration_values<rep>::zero()) { } template <class Rep2> - BOOST_CONSTEXPR + BOOST_SYMBOL_VISIBLE BOOST_FORCEINLINE BOOST_CONSTEXPR explicit duration(const Rep2& r , typename boost::enable_if < mpl::and_ < @@ -452,8 +452,7 @@ namespace chrono { >::type* = 0 ) : rep_(r) { } //~duration() {} //= default; - BOOST_CONSTEXPR - duration(const duration& rhs) : rep_(rhs.rep_) {} // = default; +// BOOST_CONSTEXPR duration(const duration& rhs) : rep_(rhs.rep_) {} // = default; duration& operator=(const duration& rhs) // = default; { if (&rhs != this) rep_= rhs.rep_; @@ -462,7 +461,7 @@ namespace chrono { // conversions template <class Rep2, class Period2> - BOOST_CONSTEXPR + BOOST_FORCEINLINE BOOST_CONSTEXPR duration(const duration<Rep2, Period2>& d , typename boost::enable_if < mpl::or_ < @@ -484,7 +483,7 @@ namespace chrono { // arithmetic BOOST_CONSTEXPR - duration operator+() const {return *this;} + duration operator+() const {return duration(rep_);;} BOOST_CONSTEXPR duration operator-() const {return duration(-rep_);} duration& operator++() {++rep_; return *this;} @@ -514,11 +513,11 @@ namespace chrono { { return duration(duration_values<rep>::zero()); } - static BOOST_CONSTEXPR duration min BOOST_PREVENT_MACRO_SUBSTITUTION () + static BOOST_CHRONO_LIB_CONSTEXPR duration min BOOST_PREVENT_MACRO_SUBSTITUTION () { return duration((duration_values<rep>::min)()); } - static BOOST_CONSTEXPR duration max BOOST_PREVENT_MACRO_SUBSTITUTION () + static BOOST_CHRONO_LIB_CONSTEXPR duration max BOOST_PREVENT_MACRO_SUBSTITUTION () { return duration((duration_values<rep>::max)()); } @@ -664,7 +663,7 @@ namespace detail template <class LhsDuration, class RhsDuration> struct duration_eq { - BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) + BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) const { typedef typename common_type<LhsDuration, RhsDuration>::type CD; return CD(lhs).count() == CD(rhs).count(); @@ -674,7 +673,7 @@ namespace detail template <class LhsDuration> struct duration_eq<LhsDuration, LhsDuration> { - BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const LhsDuration& rhs) + BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const LhsDuration& rhs) const { return lhs.count() == rhs.count(); } @@ -683,7 +682,7 @@ namespace detail template <class LhsDuration, class RhsDuration> struct duration_lt { - BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) + BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) const { typedef typename common_type<LhsDuration, RhsDuration>::type CD; return CD(lhs).count() < CD(rhs).count(); @@ -693,7 +692,7 @@ namespace detail template <class LhsDuration> struct duration_lt<LhsDuration, LhsDuration> { - BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const LhsDuration& rhs) + BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const LhsDuration& rhs) const { return lhs.count() < rhs.count(); } @@ -761,7 +760,7 @@ namespace detail // Duration >= template <class Rep1, class Period1, class Rep2, class Period2> - inline + inline BOOST_CONSTEXPR bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) diff --git a/boost/chrono/floor.hpp b/boost/chrono/floor.hpp index e133e49c8a..eb85fa7446 100644 --- a/boost/chrono/floor.hpp +++ b/boost/chrono/floor.hpp @@ -24,7 +24,9 @@ namespace boost template <class To, class Rep, class Period> To floor(const duration<Rep, Period>& d) { - return duration_cast<To>(d); + To t = duration_cast<To>(d); + if (t>d) --t; + return t; } diff --git a/boost/chrono/io/duration_get.hpp b/boost/chrono/io/duration_get.hpp new file mode 100644 index 0000000000..ce3075b7b3 --- /dev/null +++ b/boost/chrono/io/duration_get.hpp @@ -0,0 +1,593 @@ +// (C) Copyright Howard Hinnant +// (C) Copyright 2011 Vicente J. Botet Escriba +// 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 BOOST_CHRONO_IO_DURATION_GET_HPP +#define BOOST_CHRONO_IO_DURATION_GET_HPP + +#include <boost/chrono/config.hpp> +#include <string> +#include <boost/type_traits/is_scalar.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits/is_signed.hpp> +#include <boost/mpl/if.hpp> +#include <boost/math/common_factor_rt.hpp> +#include <boost/chrono/detail/scan_keyword.hpp> +#include <boost/chrono/detail/no_warning/signed_unsigned_cmp.hpp> +#include <boost/chrono/process_cpu_clocks.hpp> + +#include <boost/assert.hpp> +#include <locale> + +/** + * Duration formatting facet for input. + */ +namespace boost +{ + namespace chrono + { + + namespace detail + { + template <class Rep, bool = is_scalar<Rep>::value> + struct duration_io_intermediate + { + typedef Rep type; + }; + + template <class Rep> + struct duration_io_intermediate<Rep, true> + { + typedef typename mpl::if_c<is_floating_point<Rep>::value, long double, typename mpl::if_c< + is_signed<Rep>::value, long long, unsigned long long>::type>::type type; + }; + + template <class Rep> + struct duration_io_intermediate<process_times<Rep>, false> + { + typedef process_times<typename duration_io_intermediate<Rep>::type> type; + }; + + template <typename intermediate_type> + typename enable_if<is_integral<intermediate_type> , bool>::type reduce(intermediate_type& r, + unsigned long long& den, std::ios_base::iostate& err) + { + typedef typename common_type<intermediate_type, unsigned long long>::type common_type_t; + + // Reduce r * num / den + common_type_t t = math::gcd<common_type_t>(common_type_t(r), common_type_t(den)); + r /= t; + den /= t; + if (den != 1) + { + // Conversion to Period is integral and not exact + err |= std::ios_base::failbit; + return false; + } + return true; + } + template <typename intermediate_type> + typename disable_if<is_integral<intermediate_type> , bool>::type reduce(intermediate_type&, unsigned long long&, + std::ios_base::iostate&) + { + return true; + } + + } + + /** + * @c duration_get is used to parse a character sequence, extracting + * components of a duration into a class duration. + * Each get member parses a format as produced by a corresponding format specifier to time_put<>::put. + * If the sequence being parsed matches the correct format, the + * corresponding member of the class duration argument are set to the + * value used to produce the sequence; + * otherwise either an error is reported or unspecified values are assigned. + * In other words, user confirmation is required for reliable parsing of + * user-entered durations, but machine-generated formats can be parsed + * reliably. This allows parsers to be aggressive about interpreting user + * variations on standard formats. + * + * If the end iterator is reached during parsing of the get() member + * function, the member sets std::ios_base::eofbit in err. + */ + template <class CharT, class InputIterator = std::istreambuf_iterator<CharT> > + class duration_get: public std::locale::facet + { + public: + /** + * Type of character the facet is instantiated on. + */ + typedef CharT char_type; + /** + * Type of character string passed to member functions. + */ + typedef std::basic_string<CharT> string_type; + /** + * Type of iterator used to scan the character buffer. + */ + typedef InputIterator iter_type; + + /** + * Construct a @c duration_get facet. + * @param refs + * @Effects Construct a @c duration_get facet. + * If the @c refs argument is @c 0 then destruction of the object is + * delegated to the @c locale, or locales, containing it. This allows + * the user to ignore lifetime management issues. On the other had, + * if @c refs is @c 1 then the object must be explicitly deleted; + * the @c locale will not do so. In this case, the object can be + * maintained across the lifetime of multiple locales. + */ + + explicit duration_get(size_t refs = 0) : + std::locale::facet(refs) + { + } + + /** + * @param s start input stream iterator + * @param end end input stream iterator + * @param ios a reference to a ios_base + * @param err the ios_base state + * @param d the duration + * @param pattern begin of the formatting pattern + * @param pat_end end of the formatting pattern + * + * Requires: [pattern,pat_end) shall be a valid range. + * + * Effects: The function starts by evaluating err = std::ios_base::goodbit. + * It then enters a loop, reading zero or more characters from s at + * each iteration. Unless otherwise specified below, the loop + * terminates when the first of the following conditions holds: + * - The expression pattern == pat_end evaluates to true. + * - The expression err == std::ios_base::goodbit evaluates to false. + * - The expression s == end evaluates to true, in which case the + * function evaluates err = std::ios_base::eofbit | std::ios_base::failbit. + * - The next element of pattern is equal to '%', followed by a conversion + * specifier character, format. + * If the number of elements in the range [pattern,pat_end) is not + * sufficient to unambiguously determine whether the conversion + * specification is complete and valid, the function evaluates + * err = std::ios_base::failbit. Otherwise, the function evaluates + * s = get_value(s, end, ios, err, r) when the conversion specification is 'v' and + * s = get_value(s, end, ios, err, rt) when the conversion specification is 'u'. + * If err == std::ios_base::goodbit holds after + * the evaluation of the expression, the function increments pattern to + * point just past the end of the conversion specification and continues + * looping. + * - The expression isspace(*pattern, ios.getloc()) evaluates to true, in + * which case the function first increments pattern until + * pattern == pat_end || !isspace(*pattern, ios.getloc()) evaluates to true, + * then advances s until s == end || !isspace(*s, ios.getloc()) is true, + * and finally resumes looping. + * - The next character read from s matches the element pointed to by + * pattern in a case-insensitive comparison, in which case the function + * evaluates ++pattern, ++s and continues looping. Otherwise, the function + * evaluates err = std::ios_base::failbit. + * + * Once r and rt are retrieved, + * Returns: s + */ + template <typename Rep, typename Period> + iter_type get(iter_type s, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, + duration<Rep, Period> &d, const char_type *pattern, const char_type *pat_end) const + { + if (std::has_facet<duration_units<CharT> >(ios.getloc())) + { + duration_units<CharT> const&facet = std::use_facet<duration_units<CharT> >(ios.getloc()); + return get(facet, s, end, ios, err, d, pattern, pat_end); + } + else + { + duration_units_default<CharT> facet; + return get(facet, s, end, ios, err, d, pattern, pat_end); + } + } + + template <typename Rep, typename Period> + iter_type get(duration_units<CharT> const&facet, iter_type s, iter_type end, std::ios_base& ios, + std::ios_base::iostate& err, duration<Rep, Period> &d, const char_type *pattern, const char_type *pat_end) const + { + + typedef typename detail::duration_io_intermediate<Rep>::type intermediate_type; + intermediate_type r; + rt_ratio rt; + bool value_found = false, unit_found = false; + + const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(ios.getloc()); + while (pattern != pat_end && err == std::ios_base::goodbit) + { + if (s == end) + { + err |= std::ios_base::eofbit; + break; + } + if (ct.narrow(*pattern, 0) == '%') + { + if (++pattern == pat_end) + { + err |= std::ios_base::failbit; + return s; + } + char cmd = ct.narrow(*pattern, 0); + switch (cmd) + { + case 'v': + { + if (value_found) + { + err |= std::ios_base::failbit; + return s; + } + value_found = true; + s = get_value(s, end, ios, err, r); + if (err & (std::ios_base::badbit | std::ios_base::failbit)) + { + return s; + } + break; + } + case 'u': + { + if (unit_found) + { + err |= std::ios_base::failbit; + return s; + } + unit_found = true; + s = get_unit(facet, s, end, ios, err, rt); + if (err & (std::ios_base::badbit | std::ios_base::failbit)) + { + return s; + } + break; + } + default: + BOOST_ASSERT(false && "Boost::Chrono internal error."); + break; + } + + ++pattern; + } + else if (ct.is(std::ctype_base::space, *pattern)) + { + for (++pattern; pattern != pat_end && ct.is(std::ctype_base::space, *pattern); ++pattern) + ; + for (; s != end && ct.is(std::ctype_base::space, *s); ++s) + ; + } + else if (ct.toupper(*s) == ct.toupper(*pattern)) + { + ++s; + ++pattern; + } + else + { + err |= std::ios_base::failbit; + return s; + } + + } + + unsigned long long num = rt.num; + unsigned long long den = rt.den; + + // r should be multiplied by (num/den) / Period + // Reduce (num/den) / Period to lowest terms + unsigned long long gcd_n1_n2 = math::gcd<unsigned long long>(num, Period::num); + unsigned long long gcd_d1_d2 = math::gcd<unsigned long long>(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 > (std::numeric_limits<unsigned long long>::max)() / d2 || den + > (std::numeric_limits<unsigned long long>::max)() / n2) + { + // (num/den) / Period overflows + err |= std::ios_base::failbit; + return s; + } + num *= d2; + den *= n2; + + typedef typename common_type<intermediate_type, unsigned long long>::type common_type_t; + + // num / den is now factor to multiply by r + if (!detail::reduce(r, den, err)) return s; + + if (chrono::detail::gt(r, ( (duration_values<common_type_t>::max)() / num))) + { + // Conversion to Period overflowed + err |= std::ios_base::failbit; + return s; + } + common_type_t t = r * num; + t /= den; + if (t > duration_values<common_type_t>::zero()) + { + Rep pt = t; + if ( (duration_values<Rep>::max)() < pt) + { + // Conversion to Period overflowed + err |= std::ios_base::failbit; + return s; + } + } + // Success! Store it. + r = Rep(t); + d = duration<Rep, Period> (r); + + return s; + } + + /** + * + * @param s start input stream iterator + * @param end end input stream iterator + * @param ios a reference to a ios_base + * @param err the ios_base state + * @param d the duration + * Stores the duration pattern from the @c duration_unit facet in let say @c str. Last as if + * @code + * return get(s, end, ios, err, ios, d, str.data(), str.data() + str.size()); + * @codeend + * @Returns An iterator pointing just beyond the last character that can be determined to be part of a valid name + */ + template <typename Rep, typename Period> + iter_type get(iter_type s, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, + duration<Rep, Period> & d) const + { + if (std::has_facet<duration_units<CharT> >(ios.getloc())) + { + duration_units<CharT> const&facet = std::use_facet<duration_units<CharT> >(ios.getloc()); + std::basic_string<CharT> str = facet.get_pattern(); + return get(facet, s, end, ios, err, d, str.data(), str.data() + str.size()); + } + else + { + duration_units_default<CharT> facet; + std::basic_string<CharT> str = facet.get_pattern(); + return get(facet, s, end, ios, err, d, str.data(), str.data() + str.size()); + } + } + + /** + * + * @param s start input stream iterator + * @param end end input stream iterator + * @param ios a reference to a ios_base + * @param err the ios_base state + * @param r a reference to the duration representation. + * @Effects As if + * @code + * return std::use_facet<std::num_get<cahr_type, iter_type> >(ios.getloc()).get(s, end, ios, err, r); + * @endcode + * + * @Returns An iterator pointing just beyond the last character that can be determined to be part of a valid name + */ + template <typename Rep> + iter_type get_value(iter_type s, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, Rep& r) const + { + return std::use_facet<std::num_get<CharT, iter_type> >(ios.getloc()).get(s, end, ios, err, r); + } + template <typename Rep> + iter_type get_value(iter_type s, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, process_times<Rep>& r) const + { + if (s == end) { + err |= std::ios_base::eofbit; + return s; + } else if (*s != '{') { // mandatory '{' + err |= std::ios_base::failbit; + return s; + } + ++s; + s = std::use_facet<std::num_get<CharT, iter_type> >(ios.getloc()).get(s, end, ios, err, r.real); + if (s == end) { + err |= std::ios_base::eofbit; + return s; + } else if (*s != ';') { // mandatory ';' + err |= std::ios_base::failbit; + return s; + } + ++s; + s = std::use_facet<std::num_get<CharT, iter_type> >(ios.getloc()).get(s, end, ios, err, r.user); + if (s == end) { + err |= std::ios_base::eofbit; + return s; + } else if (*s != ';') { // mandatory ';' + err |= std::ios_base::failbit; + return s; + } + ++s; + s = std::use_facet<std::num_get<CharT, iter_type> >(ios.getloc()).get(s, end, ios, err, r.system); + if (s == end) { + err |= std::ios_base::eofbit; + return s; + } else if (*s != '}') { // mandatory '}' + err |= std::ios_base::failbit; + return s; + } + return s; + } + + /** + * + * @param s start input stream iterator + * @param e end input stream iterator + * @param ios a reference to a ios_base + * @param err the ios_base state + * @param rt a reference to the duration run-time ratio. + * @Returns An iterator pointing just beyond the last character that can be determined to be part of a valid name + */ + iter_type get_unit(iter_type i, iter_type e, std::ios_base& is, std::ios_base::iostate& err, rt_ratio &rt) const + { + if (std::has_facet<duration_units<CharT> >(is.getloc())) + { + return get_unit(std::use_facet<duration_units<CharT> >(is.getloc()), i, e, is, err, rt); + } + else + { + duration_units_default<CharT> facet; + return get_unit(facet, i, e, is, err, rt); + } + } + + + iter_type get_unit(duration_units<CharT> const &facet, iter_type i, iter_type e, std::ios_base& is, + std::ios_base::iostate& err, rt_ratio &rt) const + { + + if (*i == '[') + { + // parse [N/D]s or [N/D]second or [N/D]seconds format + ++i; + i = std::use_facet<std::num_get<CharT, iter_type> >(is.getloc()).get(i, e, is, err, rt.num); + if ( (err & std::ios_base::failbit) != 0) + { + return i; + } + + if (i == e) + { + err |= std::ios_base::failbit; + return i; + } + CharT x = *i++; + if (x != '/') + { + err |= std::ios_base::failbit; + return i; + } + i = std::use_facet<std::num_get<CharT, iter_type> >(is.getloc()).get(i, e, is, err, rt.den); + if ( (err & std::ios_base::failbit) != 0) + { + return i; + } + if (i == e) + { + err |= std::ios_base::failbit; + return i; + } + if (*i != ']') + { + err |= std::ios_base::failbit; + return i; + } + ++i; + if (i == e) + { + err |= std::ios_base::failbit; + return i; + } + // parse s or second or seconds + return do_get_n_d_valid_unit(facet, i, e, is, err); + } + else + { + return do_get_valid_unit(facet, i, e, is, err, rt); + } + } + + /** + * Unique identifier for this type of facet. + */ + static std::locale::id id; + + /** + * @Effects Destroy the facet + */ + ~duration_get() + { + } + + protected: + + /** + * Extracts the run-time ratio associated to the duration when it is given in prefix form. + * + * This is an extension point of this facet so that we can take in account other periods that can have a useful + * translation in other contexts, as e.g. days and weeks. + * + * @param facet the duration_units facet + * @param i start input stream iterator. + * @param e end input stream iterator. + * @param ios a reference to a ios_base. + * @param err the ios_base state. + * @return @c s + */ + iter_type do_get_n_d_valid_unit(duration_units<CharT> const &facet, iter_type i, iter_type e, + std::ios_base&, std::ios_base::iostate& err) const + { + // parse SI name, short or long + + const string_type* units = facet.get_n_d_valid_units_start(); + const string_type* units_end = facet.get_n_d_valid_units_end(); + + const string_type* k = chrono_detail::scan_keyword(i, e, units, units_end, + //~ std::use_facet<std::ctype<CharT> >(loc), + err); + if (err & (std::ios_base::badbit | std::ios_base::failbit)) + { + return i; + } + if (!facet.match_n_d_valid_unit(k)) + { + err |= std::ios_base::failbit; + } + return i; + } + + /** + * Extracts the run-time ratio associated to the duration when it is given in prefix form. + * + * This is an extension point of this facet so that we can take in account other periods that can have a useful + * translation in other contexts, as e.g. days and weeks. + * + * @param facet the duration_units facet + * @param i start input stream iterator. + * @param e end input stream iterator. + * @param ios a reference to a ios_base. + * @param err the ios_base state. + * @param rt a reference to the duration run-time ratio. + * @Effects + * @Returns An iterator pointing just beyond the last character that can be determined to be part of a valid name. + */ + iter_type do_get_valid_unit(duration_units<CharT> const &facet, iter_type i, iter_type e, + std::ios_base&, std::ios_base::iostate& err, rt_ratio &rt) const + { + // parse SI name, short or long + + const string_type* units = facet.get_valid_units_start(); + const string_type* units_end = facet.get_valid_units_end(); + + err = std::ios_base::goodbit; + const string_type* k = chrono_detail::scan_keyword(i, e, units, units_end, + //~ std::use_facet<std::ctype<CharT> >(loc), + err); + if (err & (std::ios_base::badbit | std::ios_base::failbit)) + { + return i; + } + if (!facet.match_valid_unit(k, rt)) + { + err |= std::ios_base::failbit; + } + return i; + } + }; + + /** + * Unique identifier for this type of facet. + */ + template <class CharT, class InputIterator> + std::locale::id duration_get<CharT, InputIterator>::id; + + } // chrono +} +// boost + +#endif // header diff --git a/boost/chrono/io/duration_io.hpp b/boost/chrono/io/duration_io.hpp new file mode 100644 index 0000000000..438f7696db --- /dev/null +++ b/boost/chrono/io/duration_io.hpp @@ -0,0 +1,225 @@ +// (C) Copyright Howard Hinnant +// (C) Copyright 2011 Vicente J. Botet Escriba +// 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). +// +// This code was adapted by Vicente from Howard Hinnant's experimental work +// on chrono i/o to Boost + +#ifndef BOOST_CHRONO_IO_DURATION_IO_HPP +#define BOOST_CHRONO_IO_DURATION_IO_HPP + +#include <boost/chrono/duration.hpp> +#include <boost/ratio/ratio_io.hpp> +#include <boost/chrono/io/duration_style.hpp> +#include <boost/chrono/io/ios_base_state.hpp> +#include <boost/chrono/io/duration_put.hpp> +#include <boost/chrono/io/duration_get.hpp> +#include <boost/chrono/io/utility/manip_base.hpp> +#include <boost/detail/no_exceptions_support.hpp> +#include <locale> +#include <iostream> + +namespace boost +{ + namespace chrono + { + + /** + * duration parameterized manipulator. + */ + + class duration_fmt: public manip<duration_fmt> + { + duration_style style_; + public: + + /** + * explicit manipulator constructor from a @c duration_style + */ + explicit duration_fmt(duration_style style)BOOST_NOEXCEPT + : style_(style) + {} + + /** + * Change the duration_style ios state; + */ + void operator()(std::ios_base &ios) const + + { + set_duration_style(ios, style_); + } + }; + + /** + * duration_style i/o saver. + * + * See Boost.IO i/o state savers for a motivating compression. + */ + struct duration_style_io_saver + { + + //! the type of the state to restore + typedef std::ios_base state_type; + //! the type of aspect to save + typedef duration_style aspect_type; + + /** + * Explicit construction from an i/o stream. + * + * Store a reference to the i/o stream and the value of the associated @c duration_style. + */ + explicit duration_style_io_saver(state_type &s) : + s_save_(s) + { + a_save_ = get_duration_style(s_save_); + } + + /** + * Construction from an i/o stream and a @c duration_style to restore. + * + * Stores a reference to the i/o stream and the value @c duration_style to restore given as parameter. + */ + duration_style_io_saver(state_type &s, aspect_type new_value) : + s_save_(s), a_save_(new_value) + { + } + + /** + * Destructor. + * + * Restores the i/o stream with the duration_style to be restored. + */ + ~duration_style_io_saver() + { + this->restore(); + } + + /** + * Restores the i/o stream with the duration_style to be restored. + */ + void restore() + { + set_duration_style(s_save_, a_save_); + } + + private: + duration_style_io_saver& operator=(duration_style_io_saver const& rhs) ; + + state_type& s_save_; + aspect_type a_save_; + }; + + /** + * duration stream inserter + * @param os the output stream + * @param d to value to insert + * @return @c os + */ + template <class CharT, class Traits, class Rep, class Period> + std::basic_ostream<CharT, Traits>& + operator<<(std::basic_ostream<CharT, Traits>& os, const duration<Rep, Period>& d) + { + bool failed = false; + BOOST_TRY + { + std::ios_base::iostate err = std::ios_base::goodbit; + BOOST_TRY + { + typename std::basic_ostream<CharT, Traits>::sentry opfx(os); + if (bool(opfx)) + { + if (!std::has_facet<duration_put<CharT> >(os.getloc())) + { + if (duration_put<CharT> ().put(os, os, os.fill(), d) .failed()) + { + err = std::ios_base::badbit; + } + } + else if (std::use_facet<duration_put<CharT> >(os.getloc()) .put(os, os, os.fill(), d) .failed()) + { + err = std::ios_base::badbit; + } + os.width(0); + } + } + BOOST_CATCH(...) + { + bool flag = false; + BOOST_TRY + { + os.setstate(std::ios_base::failbit); + } + BOOST_CATCH (std::ios_base::failure ) + { + flag = true; + } + BOOST_CATCH_END + if (flag) throw; + } + BOOST_CATCH_END + if (err) os.setstate(err); + return os; + } + BOOST_CATCH(...) + { + failed = true; + } + BOOST_CATCH_END + if (failed) os.setstate(std::ios_base::failbit | std::ios_base::badbit); + return os; + } + + /** + * + * @param is the input stream + * @param d the duration + * @return @c is + */ + template <class CharT, class Traits, class Rep, class Period> + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, duration<Rep, Period>& d) + { + std::ios_base::iostate err = std::ios_base::goodbit; + + BOOST_TRY + { + typename std::basic_istream<CharT, Traits>::sentry ipfx(is); + if (bool(ipfx)) + { + if (!std::has_facet<duration_get<CharT> >(is.getloc())) + { + duration_get<CharT> ().get(is, std::istreambuf_iterator<CharT, Traits>(), is, err, d); + } + else + { + std::use_facet<duration_get<CharT> >(is.getloc()) .get(is, std::istreambuf_iterator<CharT, Traits>(), is, + err, d); + } + } + } + BOOST_CATCH (...) + { + bool flag = false; + BOOST_TRY + { + is.setstate(std::ios_base::failbit); + } + BOOST_CATCH (std::ios_base::failure ) + { + flag = true; + } + BOOST_CATCH_END + if (flag) { BOOST_RETHROW } + } + BOOST_CATCH_END + if (err) is.setstate(err); + return is; + } + + } // chrono + +} + +#endif // header diff --git a/boost/chrono/io/duration_put.hpp b/boost/chrono/io/duration_put.hpp new file mode 100644 index 0000000000..81c13cf40e --- /dev/null +++ b/boost/chrono/io/duration_put.hpp @@ -0,0 +1,297 @@ +// (C) Copyright Howard Hinnant +// (C) Copyright 2011 Vicente J. Botet Escriba +// 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). +// + +/** + * Duration formatting facet for output. + */ +#ifndef BOOST_CHRONO_IO_DURATION_PUT_HPP +#define BOOST_CHRONO_IO_DURATION_PUT_HPP + +#include <boost/chrono/config.hpp> +#include <boost/chrono/io/duration_units.hpp> +#include <boost/chrono/process_cpu_clocks.hpp> +#include <boost/assert.hpp> +#include <locale> + +namespace boost +{ + namespace chrono + { + + /** + * @tparam ChatT a character type + * @tparam OutputIterator a model of @c OutputIterator + * + * The @c duration_put facet provides facilities for formatted output of duration values. + * The member function of @c duration_put take a duration and format it into character string representation. + * + */ + template <class CharT, class OutputIterator = std::ostreambuf_iterator<CharT> > + class duration_put: public std::locale::facet + { + public: + /** + * Type of character the facet is instantiated on. + */ + typedef CharT char_type; + /** + * Type of character string passed to member functions. + */ + typedef std::basic_string<CharT> string_type; + /** + * Type of iterator used to write in the character buffer. + */ + typedef OutputIterator iter_type; + + /** + * Construct a duration_put facet. + * @param refs + * @Effects Construct a duration_put facet. + * If the @c refs argument is @c 0 then destruction of the object is + * delegated to the @c locale, or locales, containing it. This allows + * the user to ignore lifetime management issues. On the other had, + * if @c refs is @c 1 then the object must be explicitly deleted; + * the @c locale will not do so. In this case, the object can be + * maintained across the lifetime of multiple locales. + */ + explicit duration_put(size_t refs = 0) : + std::locale::facet(refs) + { + } + + /** + * + * @param s an output stream iterator + * @param ios a reference to a ios_base + * @param fill the character used as filler + * @param d the duration + * @param pattern begin of the formatting pattern + * @param pat_end end of the formatting pattern + * + * @Effects Steps through the sequence from @c pattern to @c pat_end, + * identifying characters that are part of a pattern sequence. Each character + * that is not part of a pattern sequence is written to @c s immediately, and + * each pattern sequence, as it is identified, results in a call to + * @c put_value or @c put_unit; + * thus, pattern elements and other characters are interleaved in the output + * in the order in which they appear in the pattern. Pattern sequences are + * identified by converting each character @c c to a @c char value as if by + * @c ct.narrow(c,0), where @c ct is a reference to @c ctype<charT> obtained from + * @c ios.getloc(). The first character of each sequence is equal to @c '%', + * followed by a pattern specifier character @c spec, which can be @c 'v' for + * the duration value or @c 'u' for the duration unit. . + * For each valid pattern sequence identified, calls + * <c>put_value(s, ios, fill, d)</c> or <c>put_unit(s, ios, fill, d)</c>. + * + * @Returns An iterator pointing immediately after the last character produced. + */ + template <typename Rep, typename Period> + iter_type put(iter_type s, std::ios_base& ios, char_type fill, duration<Rep, Period> const& d, const CharT* pattern, + const CharT* pat_end) const + { + if (std::has_facet<duration_units<CharT> >(ios.getloc())) + { + duration_units<CharT> const&facet = std::use_facet<duration_units<CharT> >( + ios.getloc()); + return put(facet, s, ios, fill, d, pattern, pat_end); + } + else + { + duration_units_default<CharT> facet; + return put(facet, s, ios, fill, d, pattern, pat_end); + } + } + + template <typename Rep, typename Period> + iter_type put(duration_units<CharT> const& units_facet, iter_type s, std::ios_base& ios, char_type fill, + duration<Rep, Period> const& d, const CharT* pattern, const CharT* pat_end) const + { + + const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(ios.getloc()); + for (; pattern != pat_end; ++pattern) + { + if (ct.narrow(*pattern, 0) == '%') + { + if (++pattern == pat_end) + { + *s++ = pattern[-1]; + break; + } + char fmt = ct.narrow(*pattern, 0); + switch (fmt) + { + case 'v': + { + s = put_value(s, ios, fill, d); + break; + } + case 'u': + { + s = put_unit(units_facet, s, ios, fill, d); + break; + } + default: + BOOST_ASSERT(false && "Boost::Chrono internal error."); + break; + } + } + else + *s++ = *pattern; + } + return s; + } + + /** + * + * @param s an output stream iterator + * @param ios a reference to a ios_base + * @param fill the character used as filler + * @param d the duration + * @Effects imbue in @c ios the @c duration_units_default facet if not already present. + * Retrieves Stores the duration pattern from the @c duration_unit facet in let say @c str. Last as if + * @code + * return put(s, ios, d, str.data(), str.data() + str.size()); + * @endcode + * @Returns An iterator pointing immediately after the last character produced. + */ + template <typename Rep, typename Period> + iter_type put(iter_type s, std::ios_base& ios, char_type fill, duration<Rep, Period> const& d) const + { + if (std::has_facet<duration_units<CharT> >(ios.getloc())) + { + duration_units<CharT> const&facet = std::use_facet<duration_units<CharT> >( + ios.getloc()); + std::basic_string<CharT> str = facet.get_pattern(); + return put(facet, s, ios, fill, d, str.data(), str.data() + str.size()); + } + else + { + duration_units_default<CharT> facet; + std::basic_string<CharT> str = facet.get_pattern(); + return put(facet, s, ios, fill, d, str.data(), str.data() + str.size()); + } + } + + /** + * + * @param s an output stream iterator + * @param ios a reference to a ios_base + * @param fill the character used as filler + * @param d the duration + * @Effects As if s=std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill, static_cast<long int> (d.count())). + * @Returns s, iterator pointing immediately after the last character produced. + */ + template <typename Rep, typename Period> + iter_type put_value(iter_type s, std::ios_base& ios, char_type fill, duration<Rep, Period> const& d) const + { + return std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill, + static_cast<long int> (d.count())); + } + + template <typename Rep, typename Period> + iter_type put_value(iter_type s, std::ios_base& ios, char_type fill, duration<process_times<Rep>, Period> const& d) const + { + *s++ = CharT('{'); + s = put_value(s, ios, fill, process_real_cpu_clock::duration(d.count().real)); + *s++ = CharT(';'); + s = put_value(s, ios, fill, process_user_cpu_clock::duration(d.count().user)); + *s++ = CharT(';'); + s = put_value(s, ios, fill, process_system_cpu_clock::duration(d.count().system)); + *s++ = CharT('}'); + return s; + } + + /** + * + * @param s an output stream iterator + * @param ios a reference to a ios_base + * @param fill the character used as filler + * @param d the duration + * @Effects Let facet be the duration_units<CharT> facet associated to ios. If the associated unit is named, + * as if + * @code + string_type str = facet.get_unit(get_duration_style(ios), d); + s=std::copy(str.begin(), str.end(), s); + * @endcode + * Otherwise, format the unit as "[Period::num/Period::den]" followed by the unit associated to [N/D] obtained using facet.get_n_d_unit(get_duration_style(ios), d) + * @Returns s, iterator pointing immediately after the last character produced. + */ + template <typename Rep, typename Period> + iter_type put_unit(iter_type s, std::ios_base& ios, char_type fill, duration<Rep, Period> const& d) const + { + if (std::has_facet<duration_units<CharT> >(ios.getloc())) + { + duration_units<CharT> const&facet = std::use_facet<duration_units<CharT> >( + ios.getloc()); + return put_unit(facet, s, ios, fill, d); + } + else + { + duration_units_default<CharT> facet; + return put_unit(facet, s, ios, fill, d); + } + } + + template <typename Rep, typename Period> + iter_type put_unit(duration_units<CharT> const& facet, iter_type s, std::ios_base& ios, char_type fill, + duration<Rep, Period> const& d) const + { + if (facet.template is_named_unit<Period>()) { + string_type str = facet.get_unit(get_duration_style(ios), d); + s=std::copy(str.begin(), str.end(), s); + } else { + *s++ = CharT('['); + std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill, Period::num); + *s++ = CharT('/'); + std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill, Period::den); + *s++ = CharT(']'); + string_type str = facet.get_n_d_unit(get_duration_style(ios), d); + s=std::copy(str.begin(), str.end(), s); + } + return s; + } + template <typename Rep, typename Period> + iter_type put_unit(duration_units<CharT> const& facet, iter_type s, std::ios_base& ios, char_type fill, + duration<process_times<Rep>, Period> const& d) const + { + duration<Rep,Period> real(d.count().real); + if (facet.template is_named_unit<Period>()) { + string_type str = facet.get_unit(get_duration_style(ios), real); + s=std::copy(str.begin(), str.end(), s); + } else { + *s++ = CharT('['); + std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill, Period::num); + *s++ = CharT('/'); + std::use_facet<std::num_put<CharT, iter_type> >(ios.getloc()).put(s, ios, fill, Period::den); + *s++ = CharT(']'); + string_type str = facet.get_n_d_unit(get_duration_style(ios), real); + s=std::copy(str.begin(), str.end(), s); + } + return s; + } + + /** + * Unique identifier for this type of facet. + */ + static std::locale::id id; + + /** + * @Effects Destroy the facet + */ + ~duration_put() + { + } + + }; + + template <class CharT, class OutputIterator> + std::locale::id duration_put<CharT, OutputIterator>::id; + + } // chrono +} // boost + +#endif // header diff --git a/boost/chrono/io/duration_style.hpp b/boost/chrono/io/duration_style.hpp new file mode 100644 index 0000000000..65b76a902c --- /dev/null +++ b/boost/chrono/io/duration_style.hpp @@ -0,0 +1,35 @@ +// (C) Copyright Howard Hinnant +// (C) Copyright 2011 Vicente J. Botet Escriba +// 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). +// +// This code was adapted by Vicente from Howard Hinnant's experimental work +// on chrono i/o to Boost + +#ifndef BOOST_CHRONO_IO_DURATION_STYLE_HPP +#define BOOST_CHRONO_IO_DURATION_STYLE_HPP + +#include <boost/detail/scoped_enum_emulation.hpp> + +namespace boost +{ + namespace chrono + { + /** + * Scoped enumeration emulation stating whether the duration I/O style is long or short. + * prefix means duration::rep with whatever stream/locale settings are set for it followed by a long name representing the unit + * symbol means duration::rep with whatever stream/locale settings are set for it followed by a SI unit abbreviation + */ + BOOST_SCOPED_ENUM_DECLARE_BEGIN(duration_style) + { + prefix, symbol + } + BOOST_SCOPED_ENUM_DECLARE_END(duration_style) + + + } // chrono + +} + +#endif // header diff --git a/boost/chrono/io/duration_units.hpp b/boost/chrono/io/duration_units.hpp new file mode 100644 index 0000000000..84faa819a9 --- /dev/null +++ b/boost/chrono/io/duration_units.hpp @@ -0,0 +1,1003 @@ +// (C) Copyright Howard Hinnant +// (C) Copyright 2011 Vicente J. Botet Escriba +// 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 BOOST_CHRONO_IO_DURATION_UNITS_HPP +#define BOOST_CHRONO_IO_DURATION_UNITS_HPP + +#include <boost/chrono/config.hpp> +#include <boost/ratio/ratio_io.hpp> +#include <boost/chrono/duration.hpp> +#include <boost/chrono/io/duration_style.hpp> +#include <boost/chrono/io/ios_base_state.hpp> +#include <boost/assert.hpp> +#include <string> +#include <ios> +#include <locale> +#include <algorithm> + +namespace boost +{ + namespace chrono + { + class rt_ratio + { + public: + template <typename Period> + rt_ratio(Period const&) : + num(Period::type::num), den(Period::type::den) + { + } + + rt_ratio(intmax_t n = 0, intmax_t d = 0) : + num(n), den(d) + { + } + + intmax_t num; + intmax_t den; + }; + + /** + * @c duration_units facet gives useful information about the duration units, + * as the number of plural forms, the plural form associated to a duration, + * the text associated to a plural form and a duration's period, + */ + template <typename CharT = char> + class duration_units: public std::locale::facet + { + public: + /** + * Type of character the facet is instantiated on. + */ + typedef CharT char_type; + /** + * Type of character string passed to member functions. + */ + typedef std::basic_string<CharT> string_type; + + /** + * Unique identifier for this type of facet. + */ + static std::locale::id id; + + /** + * Construct a @c duration_units facet. + * @param refs + * @Effects Construct a @c duration_units facet. + * If the @c refs argument is @c 0 then destruction of the object is + * delegated to the @c locale, or locales, containing it. This allows + * the user to ignore lifetime management issues. On the other had, + * if @c refs is @c 1 then the object must be explicitly deleted; + * the @c locale will not do so. In this case, the object can be + * maintained across the lifetime of multiple locales. + */ + explicit duration_units(size_t refs = 0) : + std::locale::facet(refs) + { + } + + /** + * @return pointer to the start of valid [N/D] units. + */ + virtual const string_type* get_n_d_valid_units_start() const =0; + /** + * @effect calls the do_... + * @return pointer to the end of valid [N/D] units. + */ + virtual const string_type* get_n_d_valid_units_end() const=0; + + /** + * @return pointer to the start of valid units, symbol or prefix with its different plural forms. + */ + virtual const string_type* get_valid_units_start() const=0; + /** + * @return pointer to the end of valid units. + */ + virtual const string_type* get_valid_units_end() const=0; + + /** + * @param k the found pointer to the [N/D] unit. + * @return true if @c k matches a valid unit. + */ + virtual bool match_n_d_valid_unit(const string_type* k) const = 0; + /** + * @param k the found pointer to the unit. + * @Effects @c rt is set to the valid Period when the @c k matches a valid unit. + * @return true if @c k matches a valid unit. + */ + virtual bool match_valid_unit(const string_type* k, rt_ratio& rt) const = 0; + + /** + * @effect calls the do_... + * @return the pattern to be used by default. + */ + virtual string_type get_pattern() const=0; + + /** + * @effect calls the do_... + * @return the unit associated to this duration. + */ + template <typename Rep, typename Period> + string_type get_unit(duration_style style, duration<Rep, Period> const& d) const + { + return do_get_unit(style, rt_ratio(Period()), static_cast<intmax_t>(d.count())); + } + /** + * @effect calls the do_... + * @return the [N/D] suffix unit associated to this duration. + */ + template <typename Rep, typename Period> + string_type get_n_d_unit(duration_style style, duration<Rep, Period> const& d) const + { + return do_get_n_d_unit(style, rt_ratio(Period()), static_cast<intmax_t>(d.count())); + } + + /** + * @effect calls the do_... + * @return true if the unit associated to the given Period is named, false otherwise. + */ + template <typename Period> + bool is_named_unit() const + { + return do_is_named_unit(rt_ratio(Period())); + } + + + protected: + + /** + * @Effects Destroys the facet + */ + virtual ~duration_units() + { + } + /** + * @return the [N/D] suffix unit associated to this duration. + */ + virtual string_type do_get_n_d_unit(duration_style style, rt_ratio rt, intmax_t v) const = 0; + /** + * @return the unit associated to this duration. + */ + virtual string_type do_get_unit(duration_style style,rt_ratio rt, intmax_t v) const = 0; + /** + * @return true if the unit associated to the given Period is named, false otherwise. + */ + virtual bool do_is_named_unit(rt_ratio rt) const =0; + + }; + + template <typename CharT> + std::locale::id duration_units<CharT>::id; + + namespace detail + { + template<typename CharT> + struct duration_units_default_holder + { + typedef std::basic_string<CharT> string_type; + static string_type* n_d_valid_units_; + static string_type* valid_units_; + static bool initialized_; + }; + template <typename CharT> + typename duration_units_default_holder<CharT>::string_type* duration_units_default_holder<CharT>::n_d_valid_units_=0; + template <typename CharT> + typename duration_units_default_holder<CharT>::string_type* duration_units_default_holder<CharT>::valid_units_=0; + template<typename CharT> + bool duration_units_default_holder<CharT>::initialized_ = false; + } + + /** + * This class is used to define the strings for the default English + */ + template <typename CharT = char> + class duration_units_default: public duration_units<CharT> + { + protected: + static const std::size_t pfs_ = 2; + + public: + /** + * Type of character the facet is instantiated on. + */ + typedef CharT char_type; + /** + * Type of character string passed to member functions. + */ + typedef std::basic_string<CharT> string_type; + + /** + * Construct a @c duration_units_default facet. + * @param refs + * @Effects Construct a @c duration_units_default facet. + * If the @c refs argument is @c 0 then destruction of the object is + * delegated to the @c locale, or locales, containing it. This allows + * the user to ignore lifetime management issues. On the other had, + * if @c refs is @c 1 then the object must be explicitly deleted; + * the @c locale will not do so. In this case, the object can be + * maintained across the lifetime of multiple locales. + */ + explicit duration_units_default(size_t refs = 0) : + duration_units<CharT> (refs) + { + } + + /** + * Destroys the facet. + */ + ~duration_units_default() + { + } + + public: + + /** + * @param k the found pointer to the [N/D] unit. + * @return true if @c k matches a valid unit. + */ + bool match_n_d_valid_unit(const string_type* k) const + { + std::size_t index = (k - get_n_d_valid_units_start()) / (pfs_ + 1); + switch (index) + { + case 0: + break; + default: + return false; + } + return true; + } + /** + * @param k the found pointer to the unit. + * @Effects @c rt is set to the valid Period when the @c k matches a valid unit. + * @return true if @c k matches a valid unit. + */ + bool match_valid_unit(const string_type* k, rt_ratio& rt) const + { + std::size_t index = (k - get_valid_units_start()) / (pfs_ + 1); + switch (index) + { + case 0: + rt = rt_ratio(atto()); + break; + case 1: + rt = rt_ratio(femto()); + break; + case 2: + rt = rt_ratio(pico()); + break; + case 3: + rt = rt_ratio(nano()); + break; + case 4: + rt = rt_ratio(micro()); + break; + case 5: + rt = rt_ratio(milli()); + break; + case 6: + rt = rt_ratio(centi()); + break; + case 7: + rt = rt_ratio(deci()); + break; + case 8: + rt = rt_ratio(deca()); + break; + case 9: + rt = rt_ratio(hecto()); + break; + case 10: + rt = rt_ratio(kilo()); + break; + case 11: + rt = rt_ratio(mega()); + break; + case 12: + rt = rt_ratio(giga()); + break; + case 13: + rt = rt_ratio(tera()); + break; + case 14: + rt = rt_ratio(peta()); + break; + case 15: + rt = rt_ratio(exa()); + break; + case 16: + rt = rt_ratio(ratio<1> ()); + break; + case 17: + rt = rt_ratio(ratio<60> ()); + break; + case 18: + rt = rt_ratio(ratio<3600> ()); + break; + default: + return false; + } + return true; + } + + /** + * @return pointer to the start of valid [N/D] units. + */ + virtual const string_type* get_n_d_valid_units_start()const + { + return detail::duration_units_default_holder<CharT>::n_d_valid_units_; + } + /** + * @return pointer to the end of valid [N/D] units. + */ + virtual const string_type* get_n_d_valid_units_end()const + { + return detail::duration_units_default_holder<CharT>::n_d_valid_units_ + (pfs_ + 1); + } + + /** + * @return pointer to the start of valid units. + */ + virtual const string_type* get_valid_units_start() const + { + return detail::duration_units_default_holder<CharT>::valid_units_; + } + /** + * @return pointer to the end of valid units. + */ + virtual const string_type* get_valid_units_end() const + { + return detail::duration_units_default_holder<CharT>::valid_units_ + 19 * (pfs_ + 1); + } + + string_type get_pattern() const + { + static const CharT t[] = + { '%', 'v', ' ', '%', 'u' }; + static const string_type pattern(t, t + sizeof (t) / sizeof (t[0])); + + return pattern; + } + + protected: + /** + * + * This facet names the units associated to the following periods: + * atto,femto,pico,nano,micro,milli,centi,deci,ratio<1>,deca,hecto,kilo,mega,giga,tera,peta,exa,ratio<60> and ratio<3600>. + * @return true if the unit associated to the given Period is named, false otherwise. + */ + bool do_is_named_unit(rt_ratio rt) const + { + if (rt.num==1) { + switch (rt.den) + { + case BOOST_RATIO_INTMAX_C(1): + case BOOST_RATIO_INTMAX_C(10): + case BOOST_RATIO_INTMAX_C(100): + case BOOST_RATIO_INTMAX_C(1000): + case BOOST_RATIO_INTMAX_C(1000000): + case BOOST_RATIO_INTMAX_C(1000000000): + case BOOST_RATIO_INTMAX_C(1000000000000): + case BOOST_RATIO_INTMAX_C(1000000000000000): + case BOOST_RATIO_INTMAX_C(1000000000000000000): + return true; + default: + return false; + } + } else if (rt.den==1) { + switch (rt.num) + { + case BOOST_RATIO_INTMAX_C(10): + case BOOST_RATIO_INTMAX_C(60): + case BOOST_RATIO_INTMAX_C(100): + case BOOST_RATIO_INTMAX_C(1000): + case BOOST_RATIO_INTMAX_C(3600): + case BOOST_RATIO_INTMAX_C(1000000): + case BOOST_RATIO_INTMAX_C(1000000000): + case BOOST_RATIO_INTMAX_C(1000000000000): + case BOOST_RATIO_INTMAX_C(1000000000000000): + case BOOST_RATIO_INTMAX_C(1000000000000000000): + return true; + default: + return false; + } + } + return false; + + } + + /** + * In English the suffix used after [N/D] is the one associated to the period ratio<1>. + * @return the [N/D] suffix unit associated to this duration. + */ + string_type do_get_n_d_unit(duration_style style, rt_ratio, intmax_t v) const + { + return do_get_unit(style, ratio<1>(), do_get_plural_form(v)); + } + + /** + * @return the unit associated to this duration if it is named, "" otherwise. + */ + string_type do_get_unit(duration_style style, rt_ratio rt, intmax_t v) const + { + if (rt.num==1) { + switch (rt.den) + { + case BOOST_RATIO_INTMAX_C(1): + return do_get_unit(style, ratio<1>(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(10): + return do_get_unit(style, deci(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(100): + return do_get_unit(style, centi(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(1000): + return do_get_unit(style, milli(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(1000000): + return do_get_unit(style, micro(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(1000000000): + return do_get_unit(style, nano(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(1000000000000): + return do_get_unit(style, pico(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(1000000000000000): + return do_get_unit(style, femto(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(1000000000000000000): + return do_get_unit(style, atto(), do_get_plural_form(v)); + default: + ; + } + } else if (rt.den==1) { + switch (rt.num) + { + case BOOST_RATIO_INTMAX_C(10): + return do_get_unit(style, deca(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(60): + return do_get_unit(style, ratio<60>(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(100): + return do_get_unit(style, hecto(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(1000): + return do_get_unit(style, kilo(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(3600): + return do_get_unit(style, ratio<3600>(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(1000000): + return do_get_unit(style, mega(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(1000000000): + return do_get_unit(style, giga(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(1000000000000): + return do_get_unit(style, tera(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(1000000000000000): + return do_get_unit(style, peta(), do_get_plural_form(v)); + case BOOST_RATIO_INTMAX_C(1000000000000000000): + return do_get_unit(style, exa(), do_get_plural_form(v)); + default: + ; + } + } + BOOST_ASSERT(false&&"ratio parameter can not be translated"); + //throw "exception"; + return string_type(); + } + + protected: + /** + * @return the number of associated plural forms this facet manages. + */ + virtual std::size_t do_get_plural_forms() const + { + return static_get_plural_forms(); + } + static std::size_t static_get_plural_forms() + { + return pfs_; + } + /** + * Gets the associated plural form. + * @param value the duration representation + * @return the plural form associated to the @c value parameter. In English there are 2 plural forms + * 0 singular (-1 or 1) + * 1 plural for all others + */ + virtual std::size_t do_get_plural_form(int_least64_t value) const + { + return static_get_plural_form(value); + } + static std::size_t static_get_plural_form(int_least64_t value) + { + return (value == -1 || value == 1) ? 0 : 1; + } + + /** + * @param style the duration style. + * @param period the period associated to the duration seconds. + * @param pf the requested plural form. + * @return if style is symbol returns "s", otherwise if pf is 0 return "second", if pf is 1 "seconds" + */ + virtual string_type do_get_unit(duration_style style, ratio<1> u, std::size_t pf) const + { + return static_get_unit(style,u,pf); + } + static string_type static_get_unit(duration_style style, ratio<1> , std::size_t pf) + { + static const CharT t[] = + { 's' }; + static const string_type symbol(t, t + sizeof (t) / sizeof (t[0])); + static const CharT u[] = + { 's', 'e', 'c', 'o', 'n', 'd' }; + static const string_type singular(u, u + sizeof (u) / sizeof (u[0])); + static const CharT v[] = + { 's', 'e', 'c', 'o', 'n', 'd', 's' }; + static const string_type plural(v, v + sizeof (v) / sizeof (v[0])); + + if (style == duration_style::symbol) + { + return symbol; + } + if (pf == 0) + { + return singular; + } + if (pf == 1) + { + return plural; + } + BOOST_ASSERT(false&&"style/pf parameters not valid"); + //throw "exception"; + return string_type(); + } + + /** + * @param style the duration style. + * @param period the period associated to the duration minutes. + * @param pf the requested plural form. + * @return if style is symbol returns "min", otherwise if pf is 0 return "minute", if pf is 1 "minutes" + */ + virtual string_type do_get_unit(duration_style style, ratio<60> u, std::size_t pf) const + { + return static_get_unit(style,u,pf); + } + static string_type static_get_unit(duration_style style, ratio<60> , std::size_t pf) + { + static const CharT t[] = + { 'm', 'i', 'n' }; + static const string_type symbol(t, t + sizeof (t) / sizeof (t[0])); + + static const CharT u[] = + { 'm', 'i', 'n', 'u', 't', 'e' }; + static const string_type singular(u, u + sizeof (u) / sizeof (u[0])); + static const CharT v[] = + { 'm', 'i', 'n', 'u', 't', 'e', 's' }; + static const string_type plural(v, v + sizeof (v) / sizeof (v[0])); + + if (style == duration_style::symbol) return symbol; + if (pf == 0) return singular; + if (pf == 1) return plural; + BOOST_ASSERT(false&&"style/pf parameters not valid"); + //throw "exception"; + return string_type(); + + } + + /** + * @param style the duration style. + * @param period the period associated to the duration hours. + * @param pf the requested plural form. + * @return if style is symbol returns "h", otherwise if pf is 0 return "hour", if pf is 1 "hours" + */ + virtual string_type do_get_unit(duration_style style, ratio<3600> u, std::size_t pf) const + { + return static_get_unit(style,u,pf); + } + static string_type static_get_unit(duration_style style, ratio<3600> , std::size_t pf) + { + static const CharT t[] = + { 'h' }; + static const string_type symbol(t, t + sizeof (t) / sizeof (t[0])); + static const CharT u[] = + { 'h', 'o', 'u', 'r' }; + static const string_type singular(u, u + sizeof (u) / sizeof (u[0])); + static const CharT v[] = + { 'h', 'o', 'u', 'r', 's' }; + static const string_type plural(v, v + sizeof (v) / sizeof (v[0])); + + if (style == duration_style::symbol) return symbol; + if (pf == 0) return singular; + if (pf == 1) return plural; + BOOST_ASSERT(false&&"style/pf parameters not valid"); + //throw "exception"; + return string_type(); + + } + /** + * @param style the duration style. + * @param u the period tag atto. + * @param pf the requested plural form. + * @return the concatenation of the prefix associated to @c period + the one associated to seconds. + */ + virtual string_type do_get_unit(duration_style style, atto u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, atto u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + /** + * @param style the duration style. + * @param u the period tag femto. + * @param pf the requested plural form. + * @return the concatenation of the prefix associated to period @c u + the one associated to seconds. + */ + virtual string_type do_get_unit(duration_style style, femto u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, femto u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + /** + * @param style the duration style. + * @param u the period tag femto. + * @param pf the requested plural form. + * @return the concatenation of the prefix associated to period @c u + the one associated to seconds. + */ + virtual string_type do_get_unit(duration_style style, pico u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, pico u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + virtual string_type do_get_unit(duration_style style, nano u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, nano u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + virtual string_type do_get_unit(duration_style style, micro u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, micro u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + virtual string_type do_get_unit(duration_style style, milli u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, milli u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + virtual string_type do_get_unit(duration_style style, centi u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, centi u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + virtual string_type do_get_unit(duration_style style, deci u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, deci u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + virtual string_type do_get_unit(duration_style style, deca u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, deca u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + virtual string_type do_get_unit(duration_style style, hecto u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, hecto u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + virtual string_type do_get_unit(duration_style style, kilo u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, kilo u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + virtual string_type do_get_unit(duration_style style, mega u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, mega u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + virtual string_type do_get_unit(duration_style style, giga u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, giga u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + virtual string_type do_get_unit(duration_style style, tera u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, tera u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + virtual string_type do_get_unit(duration_style style, peta u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, peta u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + virtual string_type do_get_unit(duration_style style, exa u, std::size_t pf) const + { + return do_get_ratio_prefix(style, u) + do_get_unit(style, ratio<1> (), pf); + } + static string_type static_get_unit(duration_style style, exa u, std::size_t pf) + { + return static_get_ratio_prefix(style, u) + static_get_unit(style, ratio<1> (), pf); + } + + protected: + + /** + * @param style the duration style. + * @param u the period tag atto. + * @return depending on the value of @c style return the ratio_string symbol or prefix. + */ + virtual string_type do_get_ratio_prefix(duration_style style, atto u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, atto) + { + if (style == duration_style::symbol) return ratio_string<atto, CharT>::symbol(); + return ratio_string<atto, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, femto u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, femto) + { + if (style == duration_style::symbol) return ratio_string<femto, CharT>::symbol(); + return ratio_string<femto, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, pico u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, pico) + { + if (style == duration_style::symbol) return ratio_string<pico, CharT>::symbol(); + return ratio_string<pico, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, nano u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, nano) + { + if (style == duration_style::symbol) return ratio_string<nano, CharT>::symbol(); + return ratio_string<nano, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, micro u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, micro) + { + if (style == duration_style::symbol) return ratio_string<micro, CharT>::symbol(); + return ratio_string<micro, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, milli u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, milli) + { + if (style == duration_style::symbol) return ratio_string<milli, CharT>::symbol(); + return ratio_string<milli, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, centi u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, centi) + { + if (style == duration_style::symbol) return ratio_string<centi, CharT>::symbol(); + return ratio_string<centi, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, deci u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, deci) + { + if (style == duration_style::symbol) return ratio_string<deci, CharT>::symbol(); + return ratio_string<deci, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, deca u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, deca) + { + if (style == duration_style::symbol) return ratio_string<deca, CharT>::symbol(); + return ratio_string<deca, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, hecto u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, hecto) + { + if (style == duration_style::symbol) return ratio_string<hecto, CharT>::symbol(); + return ratio_string<hecto, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, kilo u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, kilo) + { + if (style == duration_style::symbol) return ratio_string<kilo, CharT>::symbol(); + return ratio_string<kilo, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, mega u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, mega) + { + if (style == duration_style::symbol) return ratio_string<mega, CharT>::symbol(); + return ratio_string<mega, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, giga u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, giga) + { + if (style == duration_style::symbol) return ratio_string<giga, CharT>::symbol(); + return ratio_string<giga, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, tera u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, tera) + { + if (style == duration_style::symbol) return ratio_string<tera, CharT>::symbol(); + return ratio_string<tera, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, peta u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, peta) + { + if (style == duration_style::symbol) return ratio_string<peta, CharT>::symbol(); + return ratio_string<peta, CharT>::prefix(); + } + virtual string_type do_get_ratio_prefix(duration_style style, exa u) const + { + return static_get_ratio_prefix(style, u); + } + static string_type static_get_ratio_prefix(duration_style style, exa) + { + if (style == duration_style::symbol) return ratio_string<exa, CharT>::symbol(); + return ratio_string<exa, CharT>::prefix(); + } + + protected: + template <typename Period> + string_type* fill_units(string_type* it, Period) const + { + std::size_t pfs = do_get_plural_forms(); + for (std::size_t pf = 0; pf < pfs; ++pf) + { + *it++ = do_get_unit(duration_style::prefix, Period(), pf); + } + *it++ = do_get_unit(duration_style::symbol, Period(), 0); + return it; + } + public: + template <typename Period> + static string_type* static_fill_units(string_type* it, Period) + { + std::size_t pfs = static_get_plural_forms(); + for (std::size_t pf = 0; pf < pfs; ++pf) + { + *it++ = static_get_unit(duration_style::prefix, Period(), pf); + } + *it++ = static_get_unit(duration_style::symbol, Period(), 0); + return it; + } + static string_type* static_init_valid_units(string_type* it) + { + it = static_fill_units(it, atto()); + it = static_fill_units(it, femto()); + it = static_fill_units(it, pico()); + it = static_fill_units(it, nano()); + it = static_fill_units(it, micro()); + it = static_fill_units(it, milli()); + it = static_fill_units(it, centi()); + it = static_fill_units(it, deci()); + it = static_fill_units(it, deca()); + it = static_fill_units(it, hecto()); + it = static_fill_units(it, kilo()); + it = static_fill_units(it, mega()); + it = static_fill_units(it, giga()); + it = static_fill_units(it, tera()); + it = static_fill_units(it, peta()); + it = static_fill_units(it, exa()); + it = static_fill_units(it, ratio<1> ()); + it = static_fill_units(it, ratio<60> ()); + it = static_fill_units(it, ratio<3600> ()); + return it; + } + }; + + namespace detail + { + + template<typename CharT> + struct duration_units_default_initializer_t + { + duration_units_default_initializer_t() + { + if (!duration_units_default_holder<CharT>::initialized_) + { + typedef typename duration_units_default_holder<CharT>::string_type string_type; + duration_units_default_holder<CharT>::n_d_valid_units_ = new string_type[3]; + duration_units_default_holder<CharT>::valid_units_ = new string_type[19 * 3]; + + string_type* it = duration_units_default_holder<CharT>::n_d_valid_units_; + it = duration_units_default<CharT>::static_fill_units(it, ratio<1> ()); + it = duration_units_default<CharT>::static_init_valid_units(duration_units_default_holder<CharT>::valid_units_); + + duration_units_default_holder<CharT>::initialized_ = true; + } + } + ~duration_units_default_initializer_t() + { + if (duration_units_default_holder<CharT>::initialized_) + { + delete[] duration_units_default_holder<CharT>::n_d_valid_units_; + duration_units_default_holder<CharT>::n_d_valid_units_ = 0; + delete[] duration_units_default_holder<CharT>::valid_units_; + duration_units_default_holder<CharT>::valid_units_ = 0; + duration_units_default_holder<CharT>::initialized_ = false; + } + } + }; + namespace /**/ + { + duration_units_default_initializer_t<char> duration_units_default_initializer; + duration_units_default_initializer_t<wchar_t> wduration_units_default_initializer; + } // namespace + } + } // chrono + +} // boost + +#endif // header diff --git a/boost/chrono/io/ios_base_state.hpp b/boost/chrono/io/ios_base_state.hpp new file mode 100644 index 0000000000..6e320a5678 --- /dev/null +++ b/boost/chrono/io/ios_base_state.hpp @@ -0,0 +1,151 @@ +// (C) Copyright 2011 Vicente J. Botet Escriba +// 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). +// +// This code was adapted by Vicente from Howard Hinnant's experimental work +// on chrono i/o to Boost + +#ifndef BOOST_CHRONO_IO_IOS_BASE_STATE_HPP +#define BOOST_CHRONO_IO_IOS_BASE_STATE_HPP + +#include <boost/chrono/config.hpp> +#include <locale> +#include <boost/chrono/io/duration_style.hpp> +#include <boost/chrono/io/timezone.hpp> +#include <boost/chrono/io/utility/ios_base_state_ptr.hpp> + +namespace boost +{ + namespace chrono + { + + class fmt_masks : public ios_flags<fmt_masks> + { + typedef ios_flags<fmt_masks> base_type; + fmt_masks& operator=(fmt_masks const& rhs) ; + + public: + fmt_masks(std::ios_base& ios): base_type(ios) {} + enum type + { + uses_symbol = 1 << 0, + uses_local = 1 << 1 + }; + + inline duration_style get_duration_style() + { + return (flags() & uses_symbol) ? duration_style::symbol : duration_style::prefix; + } + inline void set_duration_style(duration_style style) + { + if (style == duration_style::symbol) + setf(uses_symbol); + else + unsetf(uses_symbol); + } + + inline timezone get_timezone() + { + return (flags() & uses_local) ? timezone::local : timezone::utc; + } + inline void set_timezone(timezone tz) + { + if (tz == timezone::local) + setf(uses_local); + else + unsetf(uses_local); + } + }; + namespace detail + { + namespace /**/ { + xalloc_key_initializer<fmt_masks > fmt_masks_xalloc_key_initializer; + } // namespace + } // namespace detail + + inline duration_style get_duration_style(std::ios_base & ios) + { + return fmt_masks(ios).get_duration_style(); + } + inline void set_duration_style(std::ios_base& ios, duration_style style) + { + fmt_masks(ios).set_duration_style(style); + } + inline std::ios_base& symbol_format(std::ios_base& ios) + { + fmt_masks(ios).setf(fmt_masks::uses_symbol); + return ios; + } + inline std::ios_base& name_format(std::ios_base& ios) + { + fmt_masks(ios).unsetf(fmt_masks::uses_symbol); + return ios; + } + + inline timezone get_timezone(std::ios_base & ios) + { + return fmt_masks(ios).get_timezone(); + } + inline void set_timezone(std::ios_base& ios, timezone tz) + { + fmt_masks(ios).set_timezone(tz); + } + inline std::ios_base& local_timezone(std::ios_base& ios) + { + fmt_masks(ios).setf(fmt_masks::uses_local); + return ios; + } + + inline std::ios_base& utc_timezone(std::ios_base& ios) + { + fmt_masks(ios).unsetf(fmt_masks::uses_local); + return ios; + } + + namespace detail + { + + template<typename CharT> + struct ios_base_data_aux + { + std::basic_string<CharT> time_fmt; + std::basic_string<CharT> duration_fmt; + public: + + ios_base_data_aux() : + time_fmt(""), + duration_fmt("") + { + } + }; + template<typename CharT> + struct ios_base_data {}; + namespace /**/ { + xalloc_key_initializer<detail::ios_base_data<char> > ios_base_data_aux_xalloc_key_initializer; + xalloc_key_initializer<detail::ios_base_data<wchar_t> > wios_base_data_aux_xalloc_key_initializer; +#if BOOST_CHRONO_HAS_UNICODE_SUPPORT + xalloc_key_initializer<detail::ios_base_data<char16_t> > u16ios_base_data_aux_xalloc_key_initializer; + xalloc_key_initializer<detail::ios_base_data<char32_t> > u32ios_base_data_aux_xalloc_key_initializer; +#endif + } // namespace + } // namespace detail + + template<typename CharT> + inline std::basic_string<CharT> get_time_fmt(std::ios_base & ios) + { + ios_state_not_null_ptr<detail::ios_base_data<CharT>, detail::ios_base_data_aux<CharT> > ptr(ios); + return ptr->time_fmt; + } + template<typename CharT> + inline void set_time_fmt(std::ios_base& ios, std::basic_string< + CharT> const& fmt) + { + ios_state_not_null_ptr<detail::ios_base_data<CharT>, detail::ios_base_data_aux<CharT> > ptr(ios); + ptr->time_fmt = fmt; + } + + } // chrono +} // boost + +#endif // header diff --git a/boost/chrono/io/time_point_get.hpp b/boost/chrono/io/time_point_get.hpp new file mode 100644 index 0000000000..5e4acd39cc --- /dev/null +++ b/boost/chrono/io/time_point_get.hpp @@ -0,0 +1,330 @@ +// (C) Copyright Howard Hinnant +// (C) Copyright 2011 Vicente J. Botet Escriba +// 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 BOOST_CHRONO_IO_TIME_POINT_GET_HPP +#define BOOST_CHRONO_IO_TIME_POINT_GET_HPP + +#include <boost/chrono/config.hpp> +#include <boost/chrono/detail/scan_keyword.hpp> +#include <boost/chrono/io/time_point_units.hpp> +#include <boost/chrono/io/duration_get.hpp> +#include <boost/assert.hpp> +#include <locale> +#include <string> + +/** + * Duration formatting facet for input. + */ +namespace boost +{ + namespace chrono + { + + template <class CharT, class InputIterator = std::istreambuf_iterator<CharT> > + class time_point_get: public std::locale::facet + { + public: + /** + * Type of character the facet is instantiated on. + */ + typedef CharT char_type; + /** + * Type of iterator used to scan the character buffer. + */ + typedef InputIterator iter_type; + + /** + * Construct a @c time_point_get facet. + * @param refs + * @Effects Construct a @c time_point_get facet. + * If the @c refs argument is @c 0 then destruction of the object is + * delegated to the @c locale, or locales, containing it. This allows + * the user to ignore lifetime management issues. On the other had, + * if @c refs is @c 1 then the object must be explicitly deleted; + * the @c locale will not do so. In this case, the object can be + * maintained across the lifetime of multiple locales. + */ + + explicit time_point_get(size_t refs = 0) : + std::locale::facet(refs) + { + } + + /** + * @param s start input stream iterator + * @param end end input stream iterator + * @param ios a reference to a ios_base + * @param err the ios_base state + * @param d the duration + * @param pattern begin of the formatting pattern + * @param pat_end end of the formatting pattern + * + * Requires: [pattern,pat_end) shall be a valid range. + * + * Effects: The function starts by evaluating err = std::ios_base::goodbit. + * It then enters a loop, reading zero or more characters from s at + * each iteration. Unless otherwise specified below, the loop + * terminates when the first of the following conditions holds: + * - The expression pattern == pat_end evaluates to true. + * - The expression err == std::ios_base::goodbit evaluates to false. + * - The expression s == end evaluates to true, in which case the + * function evaluates err = std::ios_base::eofbit | std::ios_base::failbit. + * - The next element of pattern is equal to '%', followed by a conversion + * specifier character, the functions @c get_duration or @c get_epoch are called depending on + * whether the format is @c 'd' or @c 'e'. + * If the number of elements in the range [pattern,pat_end) is not + * sufficient to unambiguously determine whether the conversion + * specification is complete and valid, the function evaluates + * err = std::ios_base::failbit. Otherwise, the function evaluates + * s = do_get(s, end, ios, err, d). If err == std::ios_base::goodbit holds after + * the evaluation of the expression, the function increments pattern to + * point just past the end of the conversion specification and continues + * looping. + * - The expression isspace(*pattern, ios.getloc()) evaluates to true, in + * which case the function first increments pattern until + * pattern == pat_end || !isspace(*pattern, ios.getloc()) evaluates to true, + * then advances s until s == end || !isspace(*s, ios.getloc()) is true, + * and finally resumes looping. + * - The next character read from s matches the element pointed to by + * pattern in a case-insensitive comparison, in which case the function + * evaluates ++pattern, ++s and continues looping. Otherwise, the function + * evaluates err = std::ios_base::failbit. + * + * Returns: s + */ + + template <class Clock, class Duration> + iter_type get(iter_type i, iter_type e, std::ios_base& is, std::ios_base::iostate& err, + time_point<Clock, Duration> &tp, const char_type *pattern, const char_type *pat_end) const + { + if (std::has_facet<time_point_units<CharT> >(is.getloc())) + { + time_point_units<CharT> const &facet = std::use_facet<time_point_units<CharT> >(is.getloc()); + return get(facet, i, e, is, err, tp, pattern, pat_end); + } + else + { + time_point_units_default<CharT> facet; + return get(facet, i, e, is, err, tp, pattern, pat_end); + } + } + + template <class Clock, class Duration> + iter_type get(time_point_units<CharT> const &facet, iter_type s, iter_type end, std::ios_base& ios, + std::ios_base::iostate& err, time_point<Clock, Duration> &tp, const char_type *pattern, + const char_type *pat_end) const + { + + Duration d; + bool duration_found = false, epoch_found = false; + + const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(ios.getloc()); + err = std::ios_base::goodbit; + while (pattern != pat_end && err == std::ios_base::goodbit) + { + if (s == end) + { + err |= std::ios_base::eofbit; + break; + } + if (ct.narrow(*pattern, 0) == '%') + { + if (++pattern == pat_end) + { + err |= std::ios_base::failbit; + return s; + } + char cmd = ct.narrow(*pattern, 0); + switch (cmd) + { + case 'd': + { + if (duration_found) + { + err |= std::ios_base::failbit; + return s; + } + duration_found = true; + s = get_duration(s, end, ios, err, d); + if (err & (std::ios_base::badbit | std::ios_base::failbit)) + { + return s; + } + break; + } + case 'e': + { + if (epoch_found) + { + err |= std::ios_base::failbit; + return s; + } + epoch_found = true; + s = get_epoch<Clock> (facet, s, end, ios, err); + if (err & (std::ios_base::badbit | std::ios_base::failbit)) + { + return s; + } + break; + } + default: + BOOST_ASSERT(false && "Boost::Chrono internal error."); + break; + } + + ++pattern; + } + else if (ct.is(std::ctype_base::space, *pattern)) + { + for (++pattern; pattern != pat_end && ct.is(std::ctype_base::space, *pattern); ++pattern) + ; + for (; s != end && ct.is(std::ctype_base::space, *s); ++s) + ; + } + else if (ct.toupper(*s) == ct.toupper(*pattern)) + { + ++s; + ++pattern; + } + else + { + err |= std::ios_base::failbit; + } + } + + // Success! Store it. + tp = time_point<Clock, Duration> (d); + return s; + } + + /** + * + * @param s an input stream iterator + * @param ios a reference to a ios_base + * @param d the duration + * Stores the duration pattern from the @c duration_unit facet in let say @c str. Last as if + * @code + * return get(s, end, ios, err, ios, d, str.data(), str.data() + str.size()); + * @codeend + * @Returns An iterator pointing just beyond the last character that can be determined to be part of a valid name + */ + template <class Clock, class Duration> + iter_type get(iter_type i, iter_type e, std::ios_base& is, std::ios_base::iostate& err, + time_point<Clock, Duration> &tp) const + { + if (std::has_facet<time_point_units<CharT> >(is.getloc())) + { + time_point_units<CharT> const &facet = std::use_facet<time_point_units<CharT> >(is.getloc()); + std::basic_string<CharT> str = facet.get_pattern(); + return get(facet, i, e, is, err, tp, str.data(), str.data() + str.size()); + } + else + { + time_point_units_default<CharT> facet; + std::basic_string<CharT> str = facet.get_pattern(); + return get(facet, i, e, is, err, tp, str.data(), str.data() + str.size()); + } + } + + /** + * As if + * @code + * return facet.get(s, end, ios, err, d); + * @endcode + * where @c facet is either the @c duration_get facet associated to the @c ios or an instance of the default @c duration_get facet. + * + * @Returns An iterator pointing just beyond the last character that can be determined to be part of a valid duration. + */ + template <typename Rep, typename Period> + iter_type get_duration(iter_type i, iter_type e, std::ios_base& is, std::ios_base::iostate& err, + duration<Rep, Period>& d) const + { + if (std::has_facet<duration_get<CharT> >(is.getloc())) + { + duration_get<CharT> const &facet = std::use_facet<duration_get<CharT> >(is.getloc()); + return get_duration(facet, i, e, is, err, d); + } + else + { + duration_get<CharT> facet; + return get_duration(facet, i, e, is, err, d); + } + } + + template <typename Rep, typename Period> + iter_type get_duration(duration_get<CharT> const& facet, iter_type s, iter_type end, std::ios_base& ios, + std::ios_base::iostate& err, duration<Rep, Period>& d) const + { + return facet.get(s, end, ios, err, d); + } + + /** + * + * @Effects Let @c facet be the @c time_point_units facet associated to @c is or a new instance of the default @c time_point_units_default facet. + * Let @c epoch be the epoch string associated to the Clock using this facet. + * Scans @c i to match @c epoch or @c e is reached. + * + * If not match before the @c e is reached @c std::ios_base::failbit is set in @c err. + * If @c e is reached @c std::ios_base::failbit is set in @c err. + * + * @Returns An iterator pointing just beyond the last character that can be determined to be part of a valid epoch. + */ + template <class Clock> + iter_type get_epoch(iter_type i, iter_type e, std::ios_base& is, std::ios_base::iostate& err) const + { + if (std::has_facet<time_point_units<CharT> >(is.getloc())) + { + time_point_units<CharT> const &facet = std::use_facet<time_point_units<CharT> >(is.getloc()); + return get_epoch(facet, i, e, is, err); + } + else + { + time_point_units_default<CharT> facet; + return get_epoch(facet, i, e, is, err); + } + } + + template <class Clock> + iter_type get_epoch(time_point_units<CharT> const &facet, iter_type i, iter_type e, std::ios_base&, + std::ios_base::iostate& err) const + { + const std::basic_string<CharT> epoch = facet.template get_epoch<Clock> (); + std::ptrdiff_t k = chrono_detail::scan_keyword(i, e, &epoch, &epoch + 1, + //~ std::use_facet<std::ctype<CharT> >(ios.getloc()), + err) - &epoch; + if (k == 1) + { + err |= std::ios_base::failbit; + return i; + } + return i; + } + + /** + * Unique identifier for this type of facet. + */ + static std::locale::id id; + + /** + * @Effects Destroy the facet + */ + ~time_point_get() + { + } + }; + + /** + * Unique identifier for this type of facet. + */ + template <class CharT, class InputIterator> + std::locale::id time_point_get<CharT, InputIterator>::id; + + } // chrono +} +// boost + +#endif // header diff --git a/boost/chrono/io/time_point_io.hpp b/boost/chrono/io/time_point_io.hpp new file mode 100644 index 0000000000..629479cde9 --- /dev/null +++ b/boost/chrono/io/time_point_io.hpp @@ -0,0 +1,1239 @@ +// (C) Copyright Howard Hinnant +// (C) Copyright 2010-2011 Vicente J. Botet Escriba +// 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). + +//===-------------------------- locale ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// This code was adapted by Vicente from Howard Hinnant's experimental work +// on chrono i/o to Boost and some functions from libc++/locale to emulate the missing time_get::get() + +#ifndef BOOST_CHRONO_IO_TIME_POINT_IO_HPP +#define BOOST_CHRONO_IO_TIME_POINT_IO_HPP + +#include <boost/chrono/io/time_point_put.hpp> +#include <boost/chrono/io/time_point_get.hpp> +#include <boost/chrono/io/duration_io.hpp> +#include <boost/chrono/io/ios_base_state.hpp> +#include <boost/chrono/io/utility/manip_base.hpp> +#include <boost/chrono/time_point.hpp> +#include <boost/chrono/clock_string.hpp> +#include <boost/chrono/round.hpp> +#include <boost/chrono/detail/scan_keyword.hpp> +#include <boost/static_assert.hpp> +#include <boost/detail/no_exceptions_support.hpp> +#include <cstring> +#include <locale> +#include <ctime> + +#define BOOST_CHRONO_INTERNAL_TIMEGM \ + ( defined BOOST_WINDOWS && ! defined(__CYGWIN__) ) \ + || (defined(sun) || defined(__sun)) \ + || (defined __IBMCPP__) \ + || defined __ANDROID__ \ + || defined __QNXNTO__ \ + || (defined(_AIX) && defined __GNUC__) + +#define BOOST_CHRONO_INTERNAL_GMTIME \ + (defined BOOST_WINDOWS && ! defined(__CYGWIN__)) \ + || ( (defined(sun) || defined(__sun)) && defined __GNUC__) \ + || (defined __IBMCPP__) \ + || defined __ANDROID__ \ + || (defined(_AIX) && defined __GNUC__) + +#define BOOST_CHRONO_USES_INTERNAL_TIME_GET + +namespace boost +{ + namespace chrono + { + typedef double fractional_seconds; + namespace detail + { + + + template <class CharT, class InputIterator = std::istreambuf_iterator<CharT> > + struct time_get + { + std::time_get<CharT> const &that_; + time_get(std::time_get<CharT> const& that) : that_(that) {} + + typedef std::time_get<CharT> facet; + typedef typename facet::iter_type iter_type; + typedef typename facet::char_type char_type; + typedef std::basic_string<char_type> string_type; + + static int + get_up_to_n_digits( + InputIterator& b, InputIterator e, + std::ios_base::iostate& err, + const std::ctype<CharT>& ct, + int n) + { + // Precondition: n >= 1 + if (b == e) + { + err |= std::ios_base::eofbit | std::ios_base::failbit; + return 0; + } + // get first digit + CharT c = *b; + if (!ct.is(std::ctype_base::digit, c)) + { + err |= std::ios_base::failbit; + return 0; + } + int r = ct.narrow(c, 0) - '0'; + for (++b, --n; b != e && n > 0; ++b, --n) + { + // get next digit + c = *b; + if (!ct.is(std::ctype_base::digit, c)) + return r; + r = r * 10 + ct.narrow(c, 0) - '0'; + } + if (b == e) + err |= std::ios_base::eofbit; + return r; + } + + + void get_day( + int& d, + iter_type& b, iter_type e, + std::ios_base::iostate& err, + const std::ctype<char_type>& ct) const + { + int t = get_up_to_n_digits(b, e, err, ct, 2); + if (!(err & std::ios_base::failbit) && 1 <= t && t <= 31) + d = t; + else + err |= std::ios_base::failbit; + } + + void get_month( + int& m, + iter_type& b, iter_type e, + std::ios_base::iostate& err, + const std::ctype<char_type>& ct) const + { + int t = get_up_to_n_digits(b, e, err, ct, 2) - 1; + if (!(err & std::ios_base::failbit) && t <= 11) + m = t; + else + err |= std::ios_base::failbit; + } + + + void get_year4(int& y, + iter_type& b, iter_type e, + std::ios_base::iostate& err, + const std::ctype<char_type>& ct) const + { + int t = get_up_to_n_digits(b, e, err, ct, 4); + if (!(err & std::ios_base::failbit)) + y = t - 1900; + } + + void + get_hour(int& h, + iter_type& b, iter_type e, + std::ios_base::iostate& err, + const std::ctype<char_type>& ct) const + { + int t = get_up_to_n_digits(b, e, err, ct, 2); + if (!(err & std::ios_base::failbit) && t <= 23) + h = t; + else + err |= std::ios_base::failbit; + } + + void + get_minute(int& m, + iter_type& b, iter_type e, + std::ios_base::iostate& err, + const std::ctype<char_type>& ct) const + { + int t = get_up_to_n_digits(b, e, err, ct, 2); + if (!(err & std::ios_base::failbit) && t <= 59) + m = t; + else + err |= std::ios_base::failbit; + } + + void get_second(int& s, + iter_type& b, iter_type e, + std::ios_base::iostate& err, + const std::ctype<char_type>& ct) const + { + int t = get_up_to_n_digits(b, e, err, ct, 2); + if (!(err & std::ios_base::failbit) && t <= 60) + s = t; + else + err |= std::ios_base::failbit; + } + + void get_white_space(iter_type& b, iter_type e, + std::ios_base::iostate& err, + const std::ctype<char_type>& ct) const + { + for (; b != e && ct.is(std::ctype_base::space, *b); ++b) + ; + if (b == e) + err |= std::ios_base::eofbit; + } + + void get_12_hour(int& h, + iter_type& b, iter_type e, + std::ios_base::iostate& err, + const std::ctype<char_type>& ct) const + { + int t = get_up_to_n_digits(b, e, err, ct, 2); + if (!(err & std::ios_base::failbit) && 1 <= t && t <= 12) + h = t; + else + err |= std::ios_base::failbit; + } + + void get_percent(iter_type& b, iter_type e, + std::ios_base::iostate& err, + const std::ctype<char_type>& ct) const + { + if (b == e) + { + err |= std::ios_base::eofbit | std::ios_base::failbit; + return; + } + if (ct.narrow(*b, 0) != '%') + err |= std::ios_base::failbit; + else if(++b == e) + err |= std::ios_base::eofbit; + } + + void get_day_year_num(int& d, + iter_type& b, iter_type e, + std::ios_base::iostate& err, + const std::ctype<char_type>& ct) const + { + int t = get_up_to_n_digits(b, e, err, ct, 3); + if (!(err & std::ios_base::failbit) && t <= 365) + d = t; + else + err |= std::ios_base::failbit; + } + + void + get_weekday(int& w, + iter_type& b, iter_type e, + std::ios_base::iostate& err, + const std::ctype<char_type>& ct) const + { + int t = get_up_to_n_digits(b, e, err, ct, 1); + if (!(err & std::ios_base::failbit) && t <= 6) + w = t; + else + err |= std::ios_base::failbit; + } +#if 0 + + void + get_am_pm(int& h, + iter_type& b, iter_type e, + std::ios_base::iostate& err, + const std::ctype<char_type>& ct) const + { + const string_type* ap = am_pm(); + if (ap[0].size() + ap[1].size() == 0) + { + err |= ios_base::failbit; + return; + } + ptrdiff_t i = detail::scan_keyword(b, e, ap, ap+2, ct, err, false) - ap; + if (i == 0 && h == 12) + h = 0; + else if (i == 1 && h < 12) + h += 12; + } + +#endif + + InputIterator get( + iter_type b, iter_type e, + std::ios_base& iob, + std::ios_base::iostate& err, + std::tm* tm, + char fmt, char) const + { + err = std::ios_base::goodbit; + const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(iob.getloc()); + + switch (fmt) + { + case 'a': + case 'A': + { + std::tm tm2; + std::memset(&tm2, 0, sizeof(std::tm)); + that_.get_weekday(b, e, iob, err, &tm2); + //tm->tm_wday = tm2.tm_wday; + } + break; + case 'b': + case 'B': + case 'h': + { + std::tm tm2; + std::memset(&tm2, 0, sizeof(std::tm)); + that_.get_monthname(b, e, iob, err, &tm2); + //tm->tm_mon = tm2.tm_mon; + } + break; +// case 'c': +// { +// const string_type& fm = c(); +// b = get(b, e, iob, err, tm, fm.data(), fm.data() + fm.size()); +// } +// break; + case 'd': + case 'e': + get_day(tm->tm_mday, b, e, err, ct); + break; + case 'D': + { + const char_type fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'}; + b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0])); + } + break; + case 'F': + { + const char_type fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'}; + b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0])); + } + break; + case 'H': + get_hour(tm->tm_hour, b, e, err, ct); + break; + case 'I': + get_12_hour(tm->tm_hour, b, e, err, ct); + break; + case 'j': + get_day_year_num(tm->tm_yday, b, e, err, ct); + break; + case 'm': + get_month(tm->tm_mon, b, e, err, ct); + break; + case 'M': + get_minute(tm->tm_min, b, e, err, ct); + break; + case 'n': + case 't': + get_white_space(b, e, err, ct); + break; +// case 'p': +// get_am_pm(tm->tm_hour, b, e, err, ct); +// break; + case 'r': + { + const char_type fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'}; + b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0])); + } + break; + case 'R': + { + const char_type fm[] = {'%', 'H', ':', '%', 'M'}; + b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0])); + } + break; + case 'S': + get_second(tm->tm_sec, b, e, err, ct); + break; + case 'T': + { + const char_type fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'}; + b = get(b, e, iob, err, tm, fm, fm + sizeof(fm)/sizeof(fm[0])); + } + break; + case 'w': + { + get_weekday(tm->tm_wday, b, e, err, ct); + } + break; + case 'x': + return that_.get_date(b, e, iob, err, tm); +// case 'X': +// return that_.get_time(b, e, iob, err, tm); +// { +// const string_type& fm = X(); +// b = that_.get(b, e, iob, err, tm, fm.data(), fm.data() + fm.size()); +// } +// break; +// case 'y': +// get_year(tm->tm_year, b, e, err, ct); + break; + case 'Y': + get_year4(tm->tm_year, b, e, err, ct); + break; + case '%': + get_percent(b, e, err, ct); + break; + default: + err |= std::ios_base::failbit; + } + return b; + } + + + InputIterator get( + iter_type b, iter_type e, + std::ios_base& iob, + std::ios_base::iostate& err, std::tm* tm, + const char_type* fmtb, const char_type* fmte) const + { + const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(iob.getloc()); + err = std::ios_base::goodbit; + while (fmtb != fmte && err == std::ios_base::goodbit) + { + if (b == e) + { + err = std::ios_base::failbit; + break; + } + if (ct.narrow(*fmtb, 0) == '%') + { + if (++fmtb == fmte) + { + err = std::ios_base::failbit; + break; + } + char cmd = ct.narrow(*fmtb, 0); + char opt = '\0'; + if (cmd == 'E' || cmd == '0') + { + if (++fmtb == fmte) + { + err = std::ios_base::failbit; + break; + } + opt = cmd; + cmd = ct.narrow(*fmtb, 0); + } + b = get(b, e, iob, err, tm, cmd, opt); + ++fmtb; + } + else if (ct.is(std::ctype_base::space, *fmtb)) + { + for (++fmtb; fmtb != fmte && ct.is(std::ctype_base::space, *fmtb); ++fmtb) + ; + for ( ; b != e && ct.is(std::ctype_base::space, *b); ++b) + ; + } + else if (ct.toupper(*b) == ct.toupper(*fmtb)) + { + ++b; + ++fmtb; + } + else + err = std::ios_base::failbit; + } + if (b == e) + err |= std::ios_base::eofbit; + return b; + } + + }; + + + template <class CharT> + class time_manip: public manip<time_manip<CharT> > + { + std::basic_string<CharT> fmt_; + timezone tz_; + public: + + time_manip(timezone tz, std::basic_string<CharT> fmt) + // todo move semantics + : + fmt_(fmt), tz_(tz) + { + } + + /** + * Change the timezone and time format ios state; + */ + void operator()(std::ios_base &ios) const + { + set_time_fmt<CharT> (ios, fmt_); + set_timezone(ios, tz_); + } + }; + + class time_man: public manip<time_man> + { + timezone tz_; + public: + + time_man(timezone tz) + // todo move semantics + : + tz_(tz) + { + } + + /** + * Change the timezone and time format ios state; + */ + void operator()(std::ios_base &ios) const + { + //set_time_fmt<typename out_stream::char_type>(ios, ""); + set_timezone(ios, tz_); + } + }; + + } + + template <class CharT> + inline detail::time_manip<CharT> time_fmt(timezone tz, const CharT* fmt) + { + return detail::time_manip<CharT>(tz, fmt); + } + + template <class CharT> + inline detail::time_manip<CharT> time_fmt(timezone tz, std::basic_string<CharT> fmt) + { + // todo move semantics + return detail::time_manip<CharT>(tz, fmt); + } + + inline detail::time_man time_fmt(timezone f) + { + return detail::time_man(f); + } + + /** + * time_fmt_io_saver i/o saver. + * + * See Boost.IO i/o state savers for a motivating compression. + */ + template <typename CharT = char, typename Traits = std::char_traits<CharT> > + struct time_fmt_io_saver + { + + //! the type of the state to restore + typedef std::basic_ostream<CharT, Traits> state_type; + //! the type of aspect to save + typedef std::basic_string<CharT, Traits> aspect_type; + + /** + * Explicit construction from an i/o stream. + * + * Store a reference to the i/o stream and the value of the associated @c time format . + */ + explicit time_fmt_io_saver(state_type &s) : + s_save_(s), a_save_(get_time_fmt(s_save_)) + { + } + + /** + * Construction from an i/o stream and a @c time format to restore. + * + * Stores a reference to the i/o stream and the value @c new_value to restore given as parameter. + */ + time_fmt_io_saver(state_type &s, aspect_type new_value) : + s_save_(s), a_save_(new_value) + { + } + + /** + * Destructor. + * + * Restores the i/o stream with the format to be restored. + */ + ~time_fmt_io_saver() + { + this->restore(); + } + + /** + * Restores the i/o stream with the time format to be restored. + */ + void restore() + { + set_time_fmt(a_save_, a_save_); + } + private: + state_type& s_save_; + aspect_type a_save_; + }; + + /** + * timezone_io_saver i/o saver. + * + * See Boost.IO i/o state savers for a motivating compression. + */ + struct timezone_io_saver + { + + //! the type of the state to restore + typedef std::ios_base state_type; + //! the type of aspect to save + typedef timezone aspect_type; + + /** + * Explicit construction from an i/o stream. + * + * Store a reference to the i/o stream and the value of the associated @c timezone. + */ + explicit timezone_io_saver(state_type &s) : + s_save_(s), a_save_(get_timezone(s_save_)) + { + } + + /** + * Construction from an i/o stream and a @c timezone to restore. + * + * Stores a reference to the i/o stream and the value @c new_value to restore given as parameter. + */ + timezone_io_saver(state_type &s, aspect_type new_value) : + s_save_(s), a_save_(new_value) + { + } + + /** + * Destructor. + * + * Restores the i/o stream with the format to be restored. + */ + ~timezone_io_saver() + { + this->restore(); + } + + /** + * Restores the i/o stream with the timezone to be restored. + */ + void restore() + { + set_timezone(s_save_, a_save_); + } + private: + timezone_io_saver& operator=(timezone_io_saver const& rhs) ; + + state_type& s_save_; + aspect_type a_save_; + }; + + /** + * + * @param os + * @param tp + * @Effects Behaves as a formatted output function. After constructing a @c sentry object, if the @ sentry + * converts to true, calls to @c facet.put(os,os,os.fill(),tp) where @c facet is the @c time_point_put<CharT> + * facet associated to @c os or a new created instance of the default @c time_point_put<CharT> facet. + * @return @c os. + */ + template <class CharT, class Traits, class Clock, class Duration> + std::basic_ostream<CharT, Traits>& + operator<<(std::basic_ostream<CharT, Traits>& os, const time_point<Clock, Duration>& tp) + { + + bool failed = false; + BOOST_TRY + { + std::ios_base::iostate err = std::ios_base::goodbit; + BOOST_TRY + { + typename std::basic_ostream<CharT, Traits>::sentry opfx(os); + if (bool(opfx)) + { + if (!std::has_facet<time_point_put<CharT> >(os.getloc())) + { + if (time_point_put<CharT> ().put(os, os, os.fill(), tp) .failed()) + { + err = std::ios_base::badbit; + } + } + else + { + if (std::use_facet<time_point_put<CharT> >(os.getloc()) .put(os, os, os.fill(), tp).failed()) + { + err = std::ios_base::badbit; + } + } + os.width(0); + } + } + BOOST_CATCH (...) + { + bool flag = false; + BOOST_TRY + { + os.setstate(std::ios_base::failbit); + } + BOOST_CATCH (std::ios_base::failure ) + { + flag = true; + } + BOOST_CATCH_END + if (flag) throw; + } + BOOST_CATCH_END + if (err) os.setstate(err); + return os; + } + BOOST_CATCH (...) + { + failed = true; + } + BOOST_CATCH_END + if (failed) os.setstate(std::ios_base::failbit | std::ios_base::badbit); + return os; + } + + template <class CharT, class Traits, class Clock, class Duration> + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, time_point<Clock, Duration>& tp) + { + std::ios_base::iostate err = std::ios_base::goodbit; + + BOOST_TRY + { + typename std::basic_istream<CharT, Traits>::sentry ipfx(is); + if (bool(ipfx)) + { + if (!std::has_facet<time_point_get<CharT> >(is.getloc())) + { + time_point_get<CharT> ().get(is, std::istreambuf_iterator<CharT, Traits>(), is, err, tp); + } + else + { + std::use_facet<time_point_get<CharT> >(is.getloc()).get(is, std::istreambuf_iterator<CharT, Traits>(), is, + err, tp); + } + } + } + BOOST_CATCH (...) + { + bool flag = false; + BOOST_TRY + { + is.setstate(std::ios_base::failbit); + } + BOOST_CATCH (std::ios_base::failure ) + { + flag = true; + } + BOOST_CATCH_END + if (flag) throw; + } + BOOST_CATCH_END + if (err) is.setstate(err); + return is; + } + + + namespace detail + { + +//#if BOOST_CHRONO_INTERNAL_TIMEGM + + inline int32_t is_leap(int32_t year) + { + if(year % 400 == 0) + return 1; + if(year % 100 == 0) + return 0; + if(year % 4 == 0) + return 1; + return 0; + } + inline int32_t days_from_0(int32_t year) + { + year--; + return 365 * year + (year / 400) - (year/100) + (year / 4); + } + inline int32_t days_from_1970(int32_t year) + { + static const int days_from_0_to_1970 = days_from_0(1970); + return days_from_0(year) - days_from_0_to_1970; + } + inline int32_t days_from_1jan(int32_t year,int32_t month,int32_t day) + { + static const int32_t days[2][12] = + { + { 0,31,59,90,120,151,181,212,243,273,304,334}, + { 0,31,60,91,121,152,182,213,244,274,305,335} + }; + + return days[is_leap(year)][month-1] + day - 1; + } + + inline time_t internal_timegm(std::tm const *t) + { + int year = t->tm_year + 1900; + int month = t->tm_mon; + if(month > 11) + { + year += month/12; + month %= 12; + } + else if(month < 0) + { + int years_diff = (-month + 11)/12; + year -= years_diff; + month+=12 * years_diff; + } + month++; + int day = t->tm_mday; + int day_of_year = days_from_1jan(year,month,day); + int days_since_epoch = days_from_1970(year) + day_of_year ; + + time_t seconds_in_day = 3600 * 24; + time_t result = seconds_in_day * days_since_epoch + 3600 * t->tm_hour + 60 * t->tm_min + t->tm_sec; + + return result; + } +//#endif + + /** + * from_ymd could be made more efficient by using a table + * day_count_table indexed by the y%400. + * This table could contain the day_count + * by*365 + by/4 - by/100 + by/400 + * + * from_ymd = (by/400)*days_by_400_years+day_count_table[by%400] + + * days_in_year_before[is_leap_table[by%400]][m-1] + d; + */ + inline unsigned days_before_years(int32_t y) + { + return y * 365 + y / 4 - y / 100 + y / 400; + } + + // Returns year/month/day triple in civil calendar + // Preconditions: z is number of days since 1970-01-01 and is in the range: + // [numeric_limits<Int>::min(), numeric_limits<Int>::max()-719468]. + template <class Int> + //constexpr + void + inline civil_from_days(Int z, Int& y, unsigned& m, unsigned& d) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(std::numeric_limits<unsigned>::digits >= 18, + "This algorithm has not been ported to a 16 bit unsigned integer"); + BOOST_STATIC_ASSERT_MSG(std::numeric_limits<Int>::digits >= 20, + "This algorithm has not been ported to a 16 bit signed integer"); + z += 719468; + const Int era = (z >= 0 ? z : z - 146096) / 146097; + const unsigned doe = static_cast<unsigned>(z - era * 146097); // [0, 146096] + const unsigned yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365; // [0, 399] + y = static_cast<Int>(yoe) + era * 400; + const unsigned doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365] + const unsigned mp = (5*doy + 2)/153; // [0, 11] + d = doy - (153*mp+2)/5 + 1; // [1, 31] + m = mp + (mp < 10 ? 3 : -9); // [1, 12] + y += (m <= 2); + --m; + } + inline std::tm * internal_gmtime(std::time_t const* t, std::tm *tm) + { + if (t==0) return 0; + if (tm==0) return 0; + +#if 0 + static const unsigned char + day_of_year_month[2][366] = + { + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 }, + + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 + + } }; + + static const int32_t days_in_year_before[2][13] = + { + { -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 }, + { -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 } + }; +#endif + + const time_t seconds_in_day = 3600 * 24; + int32_t days_since_epoch = static_cast<int32_t>(*t / seconds_in_day); + int32_t hms = static_cast<int32_t>(*t - seconds_in_day*days_since_epoch); + if (hms < 0) { + days_since_epoch-=1; + hms = seconds_in_day+hms; + } + +#if 0 + int32_t x = days_since_epoch; + int32_t y = static_cast<int32_t> (static_cast<long long> (x + 2) * 400 + / 146097); + const int32_t ym1 = y - 1; + int32_t doy = x - days_before_years(y); + const int32_t doy1 = x - days_before_years(ym1); + const int32_t N = std::numeric_limits<int>::digits - 1; + const int32_t mask1 = doy >> N; // arithmetic rshift - not portable - but nearly universal + const int32_t mask0 = ~mask1; + doy = (doy & mask0) | (doy1 & mask1); + y = (y & mask0) | (ym1 & mask1); + //y -= 32767 + 2; + y += 70; + tm->tm_year=y; + const int32_t leap = is_leap(y); + tm->tm_mon = day_of_year_month[leap][doy]-1; + tm->tm_mday = doy - days_in_year_before[leap][tm->tm_mon] ; +#else + int32_t y; + unsigned m, d; + civil_from_days(days_since_epoch, y, m, d); + tm->tm_year=y-1900; tm->tm_mon=m; tm->tm_mday=d; +#endif + + tm->tm_hour = hms / 3600; + const int ms = hms % 3600; + tm->tm_min = ms / 60; + tm->tm_sec = ms % 60; + + tm->tm_isdst = -1; + (void)mktime(tm); + return tm; + } + + } // detail +#ifndef BOOST_CHRONO_NO_UTC_TIMEPOINT + +#if defined BOOST_CHRONO_PROVIDES_DATE_IO_FOR_SYSTEM_CLOCK_TIME_POINT + + template <class CharT, class Traits, class Duration> + std::basic_ostream<CharT, Traits>& + operator<<(std::basic_ostream<CharT, Traits>& os, const time_point<system_clock, Duration>& tp) + { + typename std::basic_ostream<CharT, Traits>::sentry ok(os); + if (bool(ok)) + { + bool failed = false; + BOOST_TRY + { + const CharT* pb = 0; //nullptr; + const CharT* pe = pb; + std::basic_string<CharT> fmt = get_time_fmt<CharT> (os); + pb = fmt.data(); + pe = pb + fmt.size(); + + timezone tz = get_timezone(os); + std::locale loc = os.getloc(); + time_t t = system_clock::to_time_t(time_point_cast<system_clock::duration>(tp)); + std::tm tm; + std::memset(&tm, 0, sizeof(std::tm)); + if (tz == timezone::local) + { +#if defined BOOST_WINDOWS && ! defined(__CYGWIN__) + std::tm *tmp = 0; + if ((tmp=localtime(&t)) == 0) + failed = true; + else + tm =*tmp; +#else + if (localtime_r(&t, &tm) == 0) failed = true; +#endif + } + else + { +#if BOOST_CHRONO_INTERNAL_GMTIME + if (detail::internal_gmtime(&t, &tm) == 0) failed = true; + +#elif defined BOOST_WINDOWS && ! defined(__CYGWIN__) + std::tm *tmp = 0; + if((tmp = gmtime(&t)) == 0) + failed = true; + else + tm = *tmp; +#else + if (gmtime_r(&t, &tm) == 0) failed = true; + tm.tm_isdst = -1; + (void)mktime(&tm); + +#endif + + } + if (!failed) + { + const std::time_put<CharT>& tpf = std::use_facet<std::time_put<CharT> >(loc); + if (pb == pe) + { + CharT pattern[] = + { '%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', '%', 'H', ':', '%', 'M', ':' }; + pb = pattern; + pe = pb + sizeof (pattern) / sizeof(CharT); + failed = tpf.put(os, os, os.fill(), &tm, pb, pe).failed(); + if (!failed) + { + duration<fractional_seconds> d = tp - system_clock::from_time_t(t) + seconds(tm.tm_sec); + if (d.count() < 10) os << CharT('0'); + //if (! os.good()) { + // throw "exception"; + //} + std::ios::fmtflags flgs = os.flags(); + os.setf(std::ios::fixed, std::ios::floatfield); + //if (! os.good()) { + //throw "exception"; + //} + os.precision(9); + os << d.count(); + //if (! os.good()) { + //throw "exception"; + //} + os.flags(flgs); + if (tz == timezone::local) + { + CharT sub_pattern[] = + { ' ', '%', 'z' }; + pb = sub_pattern; + pe = pb + +sizeof (sub_pattern) / sizeof(CharT); + failed = tpf.put(os, os, os.fill(), &tm, pb, pe).failed(); + } + else + { + CharT sub_pattern[] = + { ' ', '+', '0', '0', '0', '0', 0 }; + os << sub_pattern; + } + } + } + else + { + failed = tpf.put(os, os, os.fill(), &tm, pb, pe).failed(); + } + } + } + BOOST_CATCH (...) + { + failed = true; + } + BOOST_CATCH_END + if (failed) + { + os.setstate(std::ios_base::failbit | std::ios_base::badbit); + } + } + return os; + } +#endif + + namespace detail + { + + template <class CharT, class InputIterator> + minutes extract_z(InputIterator& b, InputIterator e, std::ios_base::iostate& err, const std::ctype<CharT>& ct) + { + int min = 0; + if (b != e) + { + char cn = ct.narrow(*b, 0); + if (cn != '+' && cn != '-') + { + err |= std::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 |= std::ios_base::eofbit | std::ios_base::failbit; + return minutes(0); + } + cn = ct.narrow(*b, 0); + if (! ('0' <= cn && cn <= '9')) + { + err |= std::ios_base::failbit; + return minutes(0); + } + hr = hr * 10 + cn - '0'; + } + for (int i = 0; i < 2; ++i) + { + if (++b == e) + { + err |= std::ios_base::eofbit | std::ios_base::failbit; + return minutes(0); + } + cn = ct.narrow(*b, 0); + if (! ('0' <= cn && cn <= '9')) + { + err |= std::ios_base::failbit; + return minutes(0); + } + min = min * 10 + cn - '0'; + } + if (++b == e) { + err |= std::ios_base::eofbit; + } + min += hr * 60; + min *= sn; + } + else + { + err |= std::ios_base::eofbit | std::ios_base::failbit; + } + return minutes(min); + } + + } // detail + +#if defined BOOST_CHRONO_PROVIDES_DATE_IO_FOR_SYSTEM_CLOCK_TIME_POINT + + template <class CharT, class Traits, class Duration> + std::basic_istream<CharT, Traits>& + operator>>(std::basic_istream<CharT, Traits>& is, time_point<system_clock, Duration>& tp) + { + typename std::basic_istream<CharT, Traits>::sentry ok(is); + if (bool(ok)) + { + std::ios_base::iostate err = std::ios_base::goodbit; + BOOST_TRY + { + const CharT* pb = 0; //nullptr; + const CharT* pe = pb; + std::basic_string<CharT> fmt = get_time_fmt<CharT> (is); + pb = fmt.data(); + pe = pb + fmt.size(); + + timezone tz = get_timezone(is); + std::locale loc = is.getloc(); + const std::time_get<CharT>& tg = std::use_facet<std::time_get<CharT> >(loc); + const std::ctype<CharT>& ct = std::use_facet<std::ctype<CharT> >(loc); + tm tm; // {0} + std::memset(&tm, 0, sizeof(std::tm)); + + typedef std::istreambuf_iterator<CharT, Traits> It; + if (pb == pe) + { + CharT pattern[] = + { '%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', '%', 'H', ':', '%', 'M', ':' }; + pb = pattern; + pe = pb + sizeof (pattern) / sizeof(CharT); + +#if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET + const detail::time_get<CharT>& dtg(tg); + dtg.get(is, 0, is, err, &tm, pb, pe); +#else + tg.get(is, 0, is, err, &tm, pb, pe); +#endif + if (err & std::ios_base::failbit) goto exit; + fractional_seconds sec; + CharT c = CharT(); + std::ios::fmtflags flgs = is.flags(); + is.setf(std::ios::fixed, std::ios::floatfield); + is.precision(9); + is >> sec; + is.flags(flgs); + if (is.fail()) + { + err |= std::ios_base::failbit; + goto exit; + } + It i(is); + It eof; + c = *i; + if (++i == eof || c != ' ') + { + err |= std::ios_base::failbit; + goto exit; + } + minutes min = detail::extract_z(i, eof, err, ct); + + if (err & std::ios_base::failbit) goto exit; + time_t t; + +#if BOOST_CHRONO_INTERNAL_TIMEGM + t = detail::internal_timegm(&tm); +#else + t = timegm(&tm); +#endif + tp = time_point_cast<Duration>( + system_clock::from_time_t(t) - min + round<system_clock::duration> (duration<fractional_seconds> (sec)) + ); + } + else + { + const CharT z[2] = + { '%', 'z' }; + const CharT* fz = std::search(pb, pe, z, z + 2); +#if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET + const detail::time_get<CharT>& dtg(tg); + dtg.get(is, 0, is, err, &tm, pb, fz); +#else + tg.get(is, 0, is, err, &tm, pb, fz); +#endif + minutes minu(0); + if (fz != pe) + { + if (err != std::ios_base::goodbit) + { + err |= std::ios_base::failbit; + goto exit; + } + It i(is); + It eof; + minu = detail::extract_z(i, eof, err, ct); + if (err & std::ios_base::failbit) goto exit; + if (fz + 2 != pe) + { + if (err != std::ios_base::goodbit) + { + err |= std::ios_base::failbit; + goto exit; + } +#if defined BOOST_CHRONO_USES_INTERNAL_TIME_GET + const detail::time_get<CharT>& dtg(tg); + dtg.get(is, 0, is, err, &tm, fz + 2, pe); +#else + tg.get(is, 0, is, err, &tm, fz + 2, pe); +#endif + if (err & std::ios_base::failbit) goto exit; + } + } + tm.tm_isdst = -1; + time_t t; + if (tz == timezone::utc || fz != pe) + { +#if BOOST_CHRONO_INTERNAL_TIMEGM + t = detail::internal_timegm(&tm); +#else + t = timegm(&tm); +#endif + } + else + { + t = mktime(&tm); + } + tp = time_point_cast<Duration>( + system_clock::from_time_t(t) - minu + ); + } + } + BOOST_CATCH (...) + { + err |= std::ios_base::badbit | std::ios_base::failbit; + } + BOOST_CATCH_END + exit: is.setstate(err); + } + return is; + } + +#endif +#endif //UTC + } // chrono + +} + +#endif // header diff --git a/boost/chrono/io/time_point_put.hpp b/boost/chrono/io/time_point_put.hpp new file mode 100644 index 0000000000..9c8c7cadd0 --- /dev/null +++ b/boost/chrono/io/time_point_put.hpp @@ -0,0 +1,261 @@ +// (C) Copyright Howard Hinnant +// (C) Copyright 2011 Vicente J. Botet Escriba +// 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). +// + +/** + * Duration formatting facet for output. + */ +#ifndef BOOST_CHRONO_IO_TIME_POINT_PUT_HPP +#define BOOST_CHRONO_IO_TIME_POINT_PUT_HPP + +#include <boost/chrono/config.hpp> +#include <boost/chrono/io/time_point_units.hpp> +#include <boost/chrono/io/duration_put.hpp> +#include <boost/assert.hpp> +#include <locale> + +namespace boost +{ + namespace chrono + { + + /** + * @tparam ChatT a character type + * @tparam OutputIterator a model of @c OutputIterator + * + * The @c time_point_put facet provides facilities for formatted output of @c time_point values. + * The member function of @c time_point_put take a @c time_point and format it into character string representation. + * + */ + template <class CharT, class OutputIterator = std::ostreambuf_iterator<CharT> > + class time_point_put: public std::locale::facet + { + public: + /** + * Type of character the facet is instantiated on. + */ + typedef CharT char_type; + /** + * Type of character string passed to member functions. + */ + typedef std::basic_string<CharT> string_type; + /** + * Type of iterator used to write in the character buffer. + */ + typedef OutputIterator iter_type; + + /** + * Construct a time_point_put facet. + * @param refs + * @Effects Construct a time_point_put facet. + * If the @c refs argument is @c 0 then destruction of the object is + * delegated to the @c locale, or locales, containing it. This allows + * the user to ignore lifetime management issues. On the other had, + * if @c refs is @c 1 then the object must be explicitly deleted; + * the @c locale will not do so. In this case, the object can be + * maintained across the lifetime of multiple locales. + */ + explicit time_point_put(size_t refs = 0) : + std::locale::facet(refs) + { + } + + /** + * @param i an output stream iterator + * @param ios a reference to a ios_base + * @param fill the character used as filler + * @param tp the @c time_point + * @param pattern begin of the formatting pattern + * @param pat_end end of the formatting pattern + * + * @Effects Steps through the sequence from @c pattern to @c pat_end, + * identifying characters that are part of a pattern sequence. Each character + * that is not part of a pattern sequence is written to @c s immediately, and + * each pattern sequence, as it is identified, results in a call to + * @c put_duration or @c put_epoch; + * thus, pattern elements and other characters are interleaved in the output + * in the order in which they appear in the pattern. Pattern sequences are + * identified by converting each character @c c to a @c char value as if by + * @c ct.narrow(c,0), where @c ct is a reference to @c ctype<charT> obtained from + * @c ios.getloc(). The first character of each sequence is equal to @c '%', + * followed by a pattern specifier character @c spec, which can be @c 'd' for + * the duration value or @c 'e' for the epoch. + * For each valid pattern sequence identified, calls + * <c>put_duration(s, ios, fill, tp.time_since_epoch())</c> or <c>put_epoch(s, ios)</c>. + * + * @Returns An iterator pointing immediately after the last character produced. + */ + + template <class Clock, class Duration> + iter_type put(iter_type i, std::ios_base& ios, char_type fill, time_point<Clock, Duration> const& tp, const CharT* pattern, + const CharT* pat_end) const + { + if (std::has_facet<time_point_units<CharT> >(ios.getloc())) + { + time_point_units<CharT> const &facet = + std::use_facet<time_point_units<CharT> >(ios.getloc()); + return put(facet, i, ios, fill, tp, pattern, pat_end); + } + else + { + time_point_units_default<CharT> facet; + return put(facet, i, ios, fill, tp, pattern, pat_end); + } + } + + template <class Clock, class Duration> + iter_type put(time_point_units<CharT> const& units_facet, iter_type s, std::ios_base& ios, char_type fill, + time_point<Clock, Duration> const& tp, const CharT* pattern, const CharT* pat_end) const + { + + const std::ctype<char_type>& ct = std::use_facet<std::ctype<char_type> >(ios.getloc()); + for (; pattern != pat_end; ++pattern) + { + if (ct.narrow(*pattern, 0) == '%') + { + if (++pattern == pat_end) + { + *s++ = pattern[-1]; + break; + } + char fmt = ct.narrow(*pattern, 0); + switch (fmt) + { + case 'd': + { + s = put_duration(s, ios, fill, tp.time_since_epoch()); + break; + } + case 'e': + { + s = put_epoch<Clock> (units_facet, s, ios); + break; + } + default: + BOOST_ASSERT(false && "Boost::Chrono internal error."); + break; + } + } + else + *s++ = *pattern; + } + return s; + } + + /** + * @param i an output stream iterator + * @param ios a reference to a ios_base + * @param fill the character used as filler + * @param tp the @c time_point + * @param pattern begin of the formatting pattern + * @param pat_end end of the formatting pattern + * + * @Effects Stores the time_point pattern from the @c time_point_unit facet in let say @c str. Last as if + * @code + * return put(s, ios, dill, tp, str.data(), str.data() + str.size()); + * @endcode + * @Returns An iterator pointing immediately after the last character produced. + */ + template <class Clock, class Duration> + iter_type put(iter_type i, std::ios_base& ios, char_type fill, time_point<Clock, Duration> const& tp) const + { + if (std::has_facet<time_point_units<CharT> >(ios.getloc())) + { + time_point_units<CharT> const &facet = + std::use_facet<time_point_units<CharT> >(ios.getloc()); + std::basic_string<CharT> str = facet.get_pattern(); + return put(facet, i, ios, fill, tp, str.data(), str.data() + str.size()); + } + else + { + time_point_units_default<CharT> facet; + std::basic_string<CharT> str = facet.get_pattern(); + return put(facet, i, ios, fill, tp, str.data(), str.data() + str.size()); + } + } + + /** + * @param i an output stream iterator + * @param ios a reference to a ios_base + * @param fill the character used as filler + * @param d the @c duration + * @Effects As if <c>facet.put(s, ios, fill, d)</c> where facet is the @c duration_put<CharT> facet associated + * to the @c ios or a new instance of @c duration_put<CharT>. + * @Returns An iterator pointing immediately after the last character produced. + */ + template <typename Rep, typename Period> + iter_type put_duration(iter_type i, std::ios_base& ios, char_type fill, duration<Rep, Period> const& d) const + { + if (std::has_facet<duration_put<CharT> >(ios.getloc())) + { + duration_put<CharT> const &facet = std::use_facet<duration_put<CharT> >(ios.getloc()); + return facet.put(i, ios, fill, d); + } + else + { + duration_put<CharT> facet; + return facet.put(i, ios, fill, d); + } + } + + /** + * + * @param i an output stream iterator + * @param ios a reference to a ios_base + * @Effects As if + * @code + * string_type str = facet.template get_epoch<Clock>(); + * s=std::copy(str.begin(), str.end(), s); + * @endcode + * where facet is the @c time_point_units<CharT> facet associated + * to the @c ios or a new instance of @c time_point_units_default<CharT>. + * @Returns s, iterator pointing immediately after the last character produced. + */ + + template <typename Clock> + iter_type put_epoch(iter_type i, std::ios_base& os) const + { + if (std::has_facet<time_point_units<CharT> >(os.getloc())) + { + time_point_units<CharT> const &facet = std::use_facet<time_point_units<CharT> >(os.getloc()); + return put_epoch<Clock> (facet, i, os); + } + else + { + time_point_units_default<CharT> facet; + return put_epoch<Clock> (facet, i, os); + } + } + + template <typename Clock> + iter_type put_epoch(time_point_units<CharT> const& facet, iter_type s, std::ios_base&) const + { + string_type str = facet.template get_epoch<Clock>(); + s= std::copy(str.begin(), str.end(), s); + return s; + } + + /** + * Unique identifier for this type of facet. + */ + static std::locale::id id; + + /** + * @Effects Destroy the facet + */ + ~time_point_put() + { + } + + }; + + template <class CharT, class OutputIterator> + std::locale::id time_point_put<CharT, OutputIterator>::id; + + } // chrono +} // boost + +#endif // header diff --git a/boost/chrono/io/time_point_units.hpp b/boost/chrono/io/time_point_units.hpp new file mode 100644 index 0000000000..378c112603 --- /dev/null +++ b/boost/chrono/io/time_point_units.hpp @@ -0,0 +1,249 @@ +// (C) Copyright Howard Hinnant +// (C) Copyright 2011 Vicente J. Botet Escriba +// Copyright (c) Microsoft Corporation 2014 +// 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 BOOST_CHRONO_IO_TIME_POINT_UNITS_HPP +#define BOOST_CHRONO_IO_TIME_POINT_UNITS_HPP + +#include <boost/chrono/config.hpp> +#include <boost/chrono/process_cpu_clocks.hpp> +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/thread_clock.hpp> +#include <boost/chrono/io/ios_base_state.hpp> +#include <string> +#include <iostream> +#include <ios> +#include <locale> +#include <algorithm> + +namespace boost +{ + namespace chrono + { + + /** + * @c time_point_units facet gives useful information about the time_point pattern, + * the text associated to a time_point's epoch, + */ + template <typename CharT=char> + class time_point_units: public std::locale::facet + { + public: + /** + * Type of character the facet is instantiated on. + */ + typedef CharT char_type; + /** + * Type of character string used by member functions. + */ + typedef std::basic_string<char_type> string_type; + + /** + * Unique identifier for this type of facet. + */ + static std::locale::id id; + + /** + * Construct a @c time_point_units facet. + * @param refs + * @Effects Construct a @c time_point_units facet. + * If the @c refs argument is @c 0 then destruction of the object is + * delegated to the @c locale, or locales, containing it. This allows + * the user to ignore lifetime management issues. On the other had, + * if @c refs is @c 1 then the object must be explicitly deleted; + * the @c locale will not do so. In this case, the object can be + * maintained across the lifetime of multiple locales. + */ + explicit time_point_units(size_t refs = 0) : + std::locale::facet(refs) + { + } + + /** + * @return the pattern to be used by default. + */ + virtual string_type get_pattern() const =0; + + /** + * @return the epoch associated to the clock @c Clock calling @c do_get_epoch(Clock()) + */ + template <typename Clock> + string_type get_epoch() const + { + return do_get_epoch(Clock()); + } + + protected: + /** + * Destroy the facet. + */ + virtual ~time_point_units() {} + + + /** + * + * @param c a dummy instance of @c system_clock. + * @return The epoch string associated to the @c system_clock. + */ + virtual string_type do_get_epoch(system_clock) const=0; + + /** + * + * @param c a dummy instance of @c steady_clock. + * @return The epoch string associated to the @c steady_clock. + */ + virtual string_type do_get_epoch(steady_clock) const=0; + +#if defined(BOOST_CHRONO_HAS_PROCESS_CLOCKS) + /** + * + * @param c a dummy instance of @c process_real_cpu_clock. + * @return The epoch string associated to the @c process_real_cpu_clock. + */ + virtual string_type do_get_epoch(process_real_cpu_clock) const=0; +#if ! BOOST_OS_WINDOWS || BOOST_PLAT_WINDOWS_DESKTOP + /** + * + * @param c a dummy instance of @c process_user_cpu_clock. + * @return The epoch string associated to the @c process_user_cpu_clock. + */ + virtual string_type do_get_epoch(process_user_cpu_clock) const=0; + /** + * + * @param c a dummy instance of @c process_system_cpu_clock. + * @return The epoch string associated to the @c process_system_cpu_clock. + */ + virtual string_type do_get_epoch(process_system_cpu_clock) const=0; + /** + * + * @param c a dummy instance of @c process_cpu_clock. + * @return The epoch string associated to the @c process_cpu_clock. + */ + virtual string_type do_get_epoch(process_cpu_clock) const=0; +#endif +#endif +#if defined(BOOST_CHRONO_HAS_THREAD_CLOCK) + /** + * + * @param c a dummy instance of @c thread_clock. + * @return The epoch string associated to the @c thread_clock. + */ + virtual string_type do_get_epoch(thread_clock) const=0; +#endif + + }; + + template <typename CharT> + std::locale::id time_point_units<CharT>::id; + + + // This class is used to define the strings for the default English + template <typename CharT=char> + class time_point_units_default: public time_point_units<CharT> + { + public: + /** + * Type of character the facet is instantiated on. + */ + typedef CharT char_type; + /** + * Type of character string returned by member functions. + */ + typedef std::basic_string<char_type> string_type; + + explicit time_point_units_default(size_t refs = 0) : + time_point_units<CharT> (refs) + { + } + ~time_point_units_default() {} + + /** + * @return the default pattern "%d%e". + */ + string_type get_pattern() const + { + static const CharT t[] = + { '%', 'd', '%', 'e' }; + static const string_type pattern(t, t + sizeof (t) / sizeof (t[0])); + + return pattern; + } + + protected: + /** + * @param c a dummy instance of @c system_clock. + * @return The epoch string returned by @c clock_string<system_clock,CharT>::since(). + */ + string_type do_get_epoch(system_clock ) const + { + return clock_string<system_clock,CharT>::since(); + } + /** + * @param c a dummy instance of @c steady_clock. + * @return The epoch string returned by @c clock_string<steady_clock,CharT>::since(). + */ + string_type do_get_epoch(steady_clock ) const + { + return clock_string<steady_clock,CharT>::since(); + } + +#if defined(BOOST_CHRONO_HAS_PROCESS_CLOCKS) + /** + * @param c a dummy instance of @c process_real_cpu_clock. + * @return The epoch string returned by @c clock_string<process_real_cpu_clock,CharT>::since(). + */ + string_type do_get_epoch(process_real_cpu_clock ) const + { + return clock_string<process_real_cpu_clock,CharT>::since(); + } +#if ! BOOST_OS_WINDOWS || BOOST_PLAT_WINDOWS_DESKTOP + /** + * @param c a dummy instance of @c process_user_cpu_clock. + * @return The epoch string returned by @c clock_string<process_user_cpu_clock,CharT>::since(). + */ + string_type do_get_epoch(process_user_cpu_clock ) const + { + return clock_string<process_user_cpu_clock,CharT>::since(); + } + /** + * @param c a dummy instance of @c process_system_cpu_clock. + * @return The epoch string returned by @c clock_string<process_system_cpu_clock,CharT>::since(). + */ + string_type do_get_epoch(process_system_cpu_clock ) const + { + return clock_string<process_system_cpu_clock,CharT>::since(); + } + /** + * @param c a dummy instance of @c process_cpu_clock. + * @return The epoch string returned by @c clock_string<process_cpu_clock,CharT>::since(). + */ + string_type do_get_epoch(process_cpu_clock ) const + { + return clock_string<process_cpu_clock,CharT>::since(); + } + +#endif +#endif +#if defined(BOOST_CHRONO_HAS_THREAD_CLOCK) + /** + * @param c a dummy instance of @c thread_clock. + * @return The epoch string returned by @c clock_string<thread_clock,CharT>::since(). + */ + string_type do_get_epoch(thread_clock ) const + { + return clock_string<thread_clock,CharT>::since(); + } +#endif + + }; + + + } // chrono + +} // boost + +#endif // header diff --git a/boost/chrono/io/timezone.hpp b/boost/chrono/io/timezone.hpp new file mode 100644 index 0000000000..67975da96f --- /dev/null +++ b/boost/chrono/io/timezone.hpp @@ -0,0 +1,30 @@ +// (C) Copyright Howard Hinnant +// (C) Copyright 2010-2011 Vicente J. Botet Escriba +// 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). +// +// This code was adapted by Vicente from Howard Hinnant's experimental work +// on chrono i/o to Boost + +#ifndef BOOST_CHRONO_IO_TIMEZONE_HPP +#define BOOST_CHRONO_IO_TIMEZONE_HPP +#include <boost/detail/scoped_enum_emulation.hpp> + +namespace boost +{ + namespace chrono + { + /** + * Scoped enumeration emulation stating whether the time_point for system_clock I/O is UTC or local. + */ + BOOST_SCOPED_ENUM_DECLARE_BEGIN(timezone) + { + utc, local + } + BOOST_SCOPED_ENUM_DECLARE_END(timezone) + + } // chrono +} // boost + +#endif // header diff --git a/boost/chrono/io/utility/ios_base_state_ptr.hpp b/boost/chrono/io/utility/ios_base_state_ptr.hpp new file mode 100644 index 0000000000..f7dfdddca0 --- /dev/null +++ b/boost/chrono/io/utility/ios_base_state_ptr.hpp @@ -0,0 +1,436 @@ +// boost/chrono/utility/ios_base_pword_ptr.hpp ------------------------------------------------------------// + +// Copyright 2011 Vicente J. Botet Escriba + +// Distributed under 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) + +// See http://www.boost.org/libs/chrono for documentation. + +#ifndef BOOST_CHRONO_UTILITY_IOS_BASE_STATE_PTR_HPP +#define BOOST_CHRONO_UTILITY_IOS_BASE_STATE_PTR_HPP + +#include <ios> +#include <boost/assert.hpp> + +/** + * + + + */ +namespace boost +{ + namespace chrono + { + namespace detail + { + + /** + * xalloc key holder. + */ + template <typename T> + struct xalloc_key_holder + { + static int value; //< the xalloc value associated to T. + static bool initialized; //< whether the value has been initialized or not. + }; + + template <typename T> + int xalloc_key_holder<T>::value = 0; + + template <typename T> + bool xalloc_key_holder<T>::initialized = false; + + } + + /** + * xalloc key initialiazer. + * + * Declare a static variable of this type to ensure that the xalloc_key_holder<T> is initialized correctly. + */ + template <typename T> + struct xalloc_key_initializer + { + xalloc_key_initializer() + { + if (!detail::xalloc_key_holder<T>::initialized) + { + detail::xalloc_key_holder<T>::value = std::ios_base::xalloc(); + detail::xalloc_key_holder<T>::initialized = true; + } + } + }; + /** + * @c ios_state_ptr is a smart pointer to a ios_base specific state. + */ + template <typename Final, typename T> + class ios_state_ptr + { + ios_state_ptr& operator=(ios_state_ptr const& rhs) ; + + public: + /** + * The pointee type + */ + typedef T element_type; + /** + * Explicit constructor. + * @param ios the ios + * @Effects Constructs a @c ios_state_ptr by storing the associated @c ios. + */ + explicit ios_state_ptr(std::ios_base& ios) : + ios_(ios) + { + + } + /** + * Nothing to do as xalloc index can not be removed. + */ + ~ios_state_ptr() + { + } + + /** + * @Effects Allocates the index if not already done. + * Registers the callback responsible of maintaining the state pointer coherency, if not already done. + * Retrieves the associated ios pointer + * @return the retrieved pointer statically casted to const. + */ + T const* get() const BOOST_NOEXCEPT + { + register_once(index(), ios_); + void* &pw = ios_.pword(index()); + if (pw == 0) + { + return 0; + } + return static_cast<const T*> (pw); + } + /** + * @Effects Allocates the index if not already done. + * Registers the callback responsible of maintaining the state pointer coherency, if not already done. + * Retrieves the associated ios pointer + * @return the retrieved pointer. + */ + T * get() BOOST_NOEXCEPT + { + register_once(index(), ios_); + void* &pw = ios_.pword(index()); + if (pw == 0) + { + return 0; + } + return static_cast<T*> (pw); + } + /** + * @Effects as if @c return get(); + * @return the retrieved pointer. + */ + T * operator->()BOOST_NOEXCEPT + { + return get(); + } + /** + * @Effects as if @c return get(); + * @return the retrieved pointer. + */ + T const * operator->() const BOOST_NOEXCEPT + { + return get(); + } + + /** + * @Effects as if @c return *get(); + * @return a reference to the retrieved state. + * @Remark The behavior is undefined if @c get()==0. + */ + T & operator*() BOOST_NOEXCEPT + { + return *get(); + } + /** + * @Effects as if @c return *get(); + * @return a reference to the retrieved state. + * @Remark The behavior is undefined if @c get()==0. + */ + T const & operator *() const BOOST_NOEXCEPT + { + return *get(); + } + + /** + * @Effects reset the current pointer after storing in a temporary variable the pointer to the current state. + * @return the stored state pointer. + */ + T * release() BOOST_NOEXCEPT + { + T const* f = get(); + reset(); + return f; + } + + /** + * + * @param new_ptr the new pointer. + * @Effects deletes the current state and replace it with the new one. + */ + void reset(T* new_ptr = 0)BOOST_NOEXCEPT + { + register_once(index(), ios_); + void*& pw = ios_.pword(index()); + delete static_cast<T*> (pw); + pw = new_ptr; + } + +#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + typedef T* (ios_state_ptr::*bool_type)(); + operator bool_type() const BOOST_NOEXCEPT + { + return (get()!=0)?&ios_state_ptr::release:0; + } + bool operator!() const BOOST_NOEXCEPT + { + return (get()==0)?&ios_state_ptr::release:0; + } +#else + /** + * Explicit conversion to bool. + */ + explicit operator bool() const BOOST_NOEXCEPT + { + return get()!=0; + } +#endif + + std::ios_base& getios()BOOST_NOEXCEPT + { + return ios_; + } + std::ios_base& getios() const BOOST_NOEXCEPT + { + return ios_; + } + /** + * Implicit conversion to the ios_base + */ + operator std::ios_base&() BOOST_NOEXCEPT + { + return ios_; + } + /** + * Implicit conversion to the ios_base const + */ + operator std::ios_base&() const BOOST_NOEXCEPT + { + return ios_; + } + private: + static inline bool is_registerd(std::ios_base& ios) + { + long iw = ios.iword(index()); + return (iw == 1); + } + static inline void set_registered(std::ios_base& ios) + { + long& iw = ios.iword(index()); + iw = 1; + } + static inline void callback(std::ios_base::event evt, std::ios_base& ios, int index) + { + switch (evt) + { + case std::ios_base::erase_event: + { + void*& pw = ios.pword(index); + if (pw != 0) + { + T* ptr = static_cast<T*> (pw); + delete ptr; + pw = 0; + } + break; + } + case std::ios_base::copyfmt_event: + { + void*& pw = ios.pword(index); + if (pw != 0) + { + pw = new T(*static_cast<T*> (pw)); + } + break; + } + default: + break; + } + } + + static inline int index() + { + return detail::xalloc_key_holder<Final>::value; + } + + static inline void register_once(int indx, std::ios_base& ios) + { + // needs a mask registered + if (!is_registerd(ios)) + { + set_registered(ios); + ios.register_callback(callback, indx); + } + } + + + protected: + std::ios_base& ios_; + //static detail::xalloc_key_initializer<Final> xalloc_key_initializer_; + + }; + //template <typename Final, typename T> + //detail::xalloc_key_initializer<Final> ios_state_ptr<Final,T>::xalloc_key_initializer_; + + + /** + * @c ios_state_not_null_ptr is a non null variant of @c ios_state_ptr. + * @tparm T + * @Requires @c T must be @c DefaultConstructible and @c HeapAllocatable + */ + template <typename Final, typename T> + class ios_state_not_null_ptr: public ios_state_ptr<Final, T> + { + typedef ios_state_ptr<Final, T> base_type; + public: + explicit ios_state_not_null_ptr(std::ios_base& ios) : + base_type(ios) + { + if (this->get() == 0) + { + this->base_type::reset(new T()); + } + } + ~ios_state_not_null_ptr() + { + } + + void reset(T* new_value) BOOST_NOEXCEPT + { + BOOST_ASSERT(new_value!=0); + this->base_type::reset(new_value); + } + + }; + + /** + * This class is useful to associate some flags to an std::ios_base. + */ + template <typename Final> + class ios_flags + { + public: + /** + * + * @param ios the associated std::ios_base. + * @Postcondition <c>flags()==0</c> + */ + explicit ios_flags(std::ios_base& ios) : + ios_(ios) + { + } + ~ios_flags() + { + } + /** + * @Returns The format control information. + */ + long flags() const BOOST_NOEXCEPT + { + return value(); + } + + /** + * @param v the new bit mask. + * @Postcondition <c>v == flags()</c>. + * @Returns The previous value of @c flags(). + */ + long flags(long v)BOOST_NOEXCEPT + { + long tmp = flags(); + ref() = v; + return tmp; + } + + /** + * @param v the new value + * @Effects: Sets @c v in @c flags(). + * @Returns: The previous value of @c flags(). + */ + long setf(long v) + { + long tmp = value(); + ref() |= v; + return tmp; + } + + /** + * @param mask the bit mask to clear. + * @Effects: Clears @c mask in @c flags(). + */ + void unsetf(long mask) + { + ref() &= ~mask; + } + + /** + * + * @param v + * @param mask + * @Effects: Clears @c mask in @c flags(), sets <c>v & mask</c> in @c flags(). + * @Returns: The previous value of flags(). + */ + long setf(long v, long mask) + { + long tmp = value(); + unsetf(mask); + ref() |= v & mask; + return tmp; + } + + /** + * implicit conversion to the @c ios_base + */ + operator std::ios_base&()BOOST_NOEXCEPT + { + return ios_; + } + /** + * implicit conversion to the @c ios_base const + */ + operator std::ios_base const&() const BOOST_NOEXCEPT + { + return ios_; + } + private: + long value() const BOOST_NOEXCEPT + { + return ios_.iword(index()); + } + long& ref()BOOST_NOEXCEPT + { + return ios_.iword(index()); + } + static inline int index() + { + return detail::xalloc_key_holder<Final>::value; + } + ios_flags& operator=(ios_flags const& rhs) ; + + std::ios_base& ios_; + //static detail::xalloc_key_initializer<Final> xalloc_key_initializer_; + + }; + //template <typename Final> + //detail::xalloc_key_initializer<Final> ios_flags<Final>::xalloc_key_initializer_; + + } // namespace chrono +} // namespace boost + +#endif // header diff --git a/boost/chrono/io/utility/manip_base.hpp b/boost/chrono/io/utility/manip_base.hpp new file mode 100644 index 0000000000..f4a5f562c4 --- /dev/null +++ b/boost/chrono/io/utility/manip_base.hpp @@ -0,0 +1,101 @@ +// boost/chrono/utility/manip_base.hpp ------------------------------------------------------------// + +// Copyright 2011 Vicente J. Botet Escriba + +// Distributed under 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) + +// See http://www.boost.org/libs/chrono for documentation. + +#ifndef BOOST_CHRONO_UTILITY_MANIP_BASE_PTR_HPP +#define BOOST_CHRONO_UTILITY_MANIP_BASE_PTR_HPP + +#include <ios> + +/** + * + + */ + +namespace boost +{ + namespace chrono + { + + /** + * manip is a manipulator mixin class following the CRTP. + * @tparam Final the derived from manip and final type + * + * @Example + * @code + + class mendl: public manip<mendl> + { + public: + explicit mendl(size_t how_many) : + count(how_many) {} + template <typename out_stream> + void operator()(out_stream &out) const + { + for (size_t line = 0; line < count; ++line) + { + out.put(out.widen('\n')); + } + out.flush(); + } + private: + size_t count; + }; + + * @codeend + */ + template <typename Final> + class manip + { + public: + /** + * + * @param ios the io stream or ios_base. + * @Effects calls to the manipulator final functor. + */ + //template <typename out_stream> + void operator()(std::ios_base &ios) const + { + (*static_cast<const Final *> (this))(ios); + } + }; + + /** + * @c manip stream inserter + * @param out the io stream or ios_base. + * @param op the manipulator instance. + * @Effects if @c out is good calls to the manipulator functor @op. + * @return @c out + */ + template <typename out_stream, typename manip_type> + out_stream &operator<<(out_stream &out, const manip<manip_type> &op) + { + if (out.good()) + op(out); + return out; + } + + /** + * @c manip stream extractor + * @param in the io stream or ios_base. + * @param op the manipulator instance. + * @Effects if @c in is good calls to the manipulator functor @op. + * @return @c in + */ + template <typename in_stream, typename manip_type> + in_stream &operator>>(in_stream &in, const manip<manip_type> &op) + { + if (in.good()) + op(in); + return in; + } + + } // namespace chrono +} // namespace boost + +#endif // header diff --git a/boost/chrono/io/utility/to_string.hpp b/boost/chrono/io/utility/to_string.hpp new file mode 100644 index 0000000000..4717ba6ad3 --- /dev/null +++ b/boost/chrono/io/utility/to_string.hpp @@ -0,0 +1,50 @@ +// boost/chrono/utility/to_string.hpp +// +// Copyright 2011 Vicente J. Botet Escriba +// 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 BOOST_CHRONO_UTILITY_TO_STRING_HPP +#define BOOST_CHRONO_UTILITY_TO_STRING_HPP + +#include <boost/chrono/config.hpp> +#include <string> +#include <sstream> + +namespace boost +{ + namespace chrono + { + template <typename CharT, typename T> + std::basic_string<CharT> to_basic_string(T const&v) { + std::basic_stringstream<CharT> sstr; + sstr << v; + return sstr.str(); + } + + template <typename T> + std::string to_string(T const&v) { + return to_basic_string<char>(v); + } +#ifndef BOOST_NO_STD_WSTRING + template <typename T> + std::wstring to_wstring(T const&v) { + return to_basic_string<wchar_t>(v); + } +#endif +#if BOOST_CHRONO_HAS_UNICODE_SUPPORT + template <typename T> + std::basic_string<char16_t> to_u16string(T const&v) { + return to_basic_string<char16_t>(v); + } + template <typename T> + std::basic_string<char32_t> to_u32string(T const&v) { + return to_basic_string<char32_t>(v); + } +#endif + } // chrono + +} // boost + +#endif // header diff --git a/boost/chrono/io_v1/chrono_io.hpp b/boost/chrono/io_v1/chrono_io.hpp index 6ca1ca2d69..1a7e832b5b 100644 --- a/boost/chrono/io_v1/chrono_io.hpp +++ b/boost/chrono/io_v1/chrono_io.hpp @@ -265,59 +265,59 @@ template <class CharT, class Traits, class Rep, class Period> std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is, duration<Rep, Period>& d) { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; typedef duration_punct<CharT> Facet; std::locale loc = is.getloc(); - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; if (!std::has_facet<Facet>(loc)) { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; is.imbue(std::locale(loc, new Facet)); } - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; loc = is.getloc(); const Facet& f = std::use_facet<Facet>(loc); typedef typename chrono_detail::duration_io_intermediate<Rep>::type intermediate_type; intermediate_type r; std::ios_base::iostate err = std::ios_base::goodbit; // read value into r - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; is >> r; - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; if (is.good()) { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; // now determine unit typedef std::istreambuf_iterator<CharT, Traits> in_iterator; in_iterator i(is); in_iterator e; - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; if (i != e && *i == ' ') // mandatory ' ' after value { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; ++i; if (i != e) { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; // unit is num / den (yet to be determined) unsigned long long num = 0; unsigned long long den = 0; if (*i == '[') { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; // parse [N/D]s or [N/D]seconds format ++i; CharT x; is >> num >> x >> den; if (!is.good() || (x != '/')) { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; is.setstate(is.failbit); return is; } i = in_iterator(is); if (*i != ']') { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; is.setstate(is.failbit); return is; } @@ -328,27 +328,27 @@ operator>>(std::basic_istream<CharT, Traits>& is, duration<Rep, Period>& d) f.template plural<ratio<1> >(), f.template short_name<ratio<1> >() }; - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; const std::basic_string<CharT>* k = chrono_detail::scan_keyword(i, e, units, units + sizeof(units)/sizeof(units[0]), //~ std::use_facet<std::ctype<CharT> >(loc), err); - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; is.setstate(err); switch ((k - units) / 3) { case 0: - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; break; default: is.setstate(err); - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; return is; } } else { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; // parse SI name, short or long const std::basic_string<CharT> units[] = { @@ -410,12 +410,12 @@ operator>>(std::basic_istream<CharT, Traits>& is, duration<Rep, Period>& d) f.template plural<ratio<3600> >(), f.template short_name<ratio<3600> >() }; - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; const std::basic_string<CharT>* k = chrono_detail::scan_keyword(i, e, units, units + sizeof(units)/sizeof(units[0]), //~ std::use_facet<std::ctype<CharT> >(loc), err); - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; switch ((k - units) / 3) { case 0: @@ -495,12 +495,12 @@ operator>>(std::basic_istream<CharT, Traits>& is, duration<Rep, Period>& d) den = 1; break; default: - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; is.setstate(err|is.failbit); return is; } } - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; // unit is num/den // r should be multiplied by (num/den) / Period // Reduce (num/den) / Period to lowest terms @@ -513,7 +513,7 @@ operator>>(std::basic_istream<CharT, Traits>& is, duration<Rep, Period>& d) if (num > (std::numeric_limits<unsigned long long>::max)() / d2 || den > (std::numeric_limits<unsigned long long>::max)() / n2) { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; // (num/den) / Period overflows is.setstate(err|is.failbit); return is; @@ -523,68 +523,68 @@ operator>>(std::basic_istream<CharT, Traits>& is, duration<Rep, Period>& d) typedef typename common_type<intermediate_type, unsigned long long>::type common_type_t; - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; // num / den is now factor to multiply by r if (!chrono_detail::reduce(r, den, err)) { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; is.setstate(err|is.failbit); return is; } //if (r > ((duration_values<common_type_t>::max)() / num)) - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; if (chrono::detail::gt(r,((duration_values<common_type_t>::max)() / num))) { // Conversion to Period overflowed - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; is.setstate(err|is.failbit); return is; } - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; common_type_t t = r * num; t /= den; - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; - if (t > 0) + if (t > duration_values<common_type_t>::zero()) { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; Rep pt = t; if ( (duration_values<Rep>::max)() < pt) { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; // Conversion to Period overflowed is.setstate(err|is.failbit); return is; } } - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; // Success! Store it. r = Rep(t); d = duration<Rep, Period>(r); is.setstate(err); - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; return is; } else { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; is.setstate(is.failbit | is.eofbit); return is; } } else { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; if (i == e) is.setstate(is.failbit|is.eofbit); else is.setstate(is.failbit); - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; return is; } } else { - std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; + //std::cerr << __FILE__ << "[" << __LINE__ << "]"<< std::endl; //is.setstate(is.failbit); return is; } diff --git a/boost/chrono/process_cpu_clocks.hpp b/boost/chrono/process_cpu_clocks.hpp index 486950da40..248837506e 100644 --- a/boost/chrono/process_cpu_clocks.hpp +++ b/boost/chrono/process_cpu_clocks.hpp @@ -1,6 +1,7 @@ // boost/chrono/process_cpu_clocks.hpp -----------------------------------------------------------// // Copyright 2009-2011 Vicente J. Botet Escriba +// Copyright (c) Microsoft Corporation 2014 // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt @@ -43,6 +44,7 @@ namespace boost { namespace chrono { #endif }; +#if ! BOOST_OS_WINDOWS || BOOST_PLAT_WINDOWS_DESKTOP class BOOST_CHRONO_DECL process_user_cpu_clock { public: typedef nanoseconds duration; @@ -70,6 +72,7 @@ namespace boost { namespace chrono { static BOOST_CHRONO_INLINE time_point now(system::error_code & ec ); #endif }; +#endif template <typename Rep> struct process_times @@ -83,12 +86,15 @@ namespace boost { namespace chrono { : real(0) , user(0) , system(0){} + +#if ! defined BOOST_CHRONO_DONT_PROVIDES_DEPRECATED_IO_SINCE_V2_0_0 template <typename Rep2> explicit process_times( Rep2 r) : real(r) , user(r) , system(r){} +#endif template <typename Rep2> explicit process_times( process_times<Rep2> const& rhs) @@ -107,10 +113,12 @@ namespace boost { namespace chrono { rep user; // user cpu time rep system; // system cpu time +#if ! defined BOOST_CHRONO_DONT_PROVIDES_DEPRECATED_IO_SINCE_V2_0_0 operator rep() const { return real; } +#endif template <typename Rep2> bool operator==(process_times<Rep2> const& rhs) { return (real==rhs.real && @@ -180,7 +188,7 @@ namespace boost { namespace chrono { } template <class CharT, class Traits> - void read(std::basic_istream<CharT, Traits>& is) const + void read(std::basic_istream<CharT, Traits>& is) { typedef std::istreambuf_iterator<CharT, Traits> in_iterator; in_iterator i(is); @@ -292,6 +300,7 @@ namespace chrono typedef process_times<nanoseconds::rep> process_cpu_clock_times; +#if ! BOOST_OS_WINDOWS || BOOST_PLAT_WINDOWS_DESKTOP class BOOST_CHRONO_DECL process_cpu_clock { public: @@ -308,6 +317,7 @@ namespace chrono static BOOST_CHRONO_INLINE time_point now(system::error_code & ec ); #endif }; +#endif template <class CharT, class Traits, typename Rep> std::basic_ostream<CharT, Traits>& @@ -321,7 +331,7 @@ namespace chrono template <class CharT, class Traits, typename Rep> std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is, - process_times<Rep> const& rhs) + process_times<Rep>& rhs) { rhs.read(is); return is; @@ -372,6 +382,7 @@ namespace chrono } }; +#if ! BOOST_OS_WINDOWS || BOOST_PLAT_WINDOWS_DESKTOP template<class CharT> struct clock_string<process_user_cpu_clock, CharT> { @@ -436,6 +447,7 @@ namespace chrono return str; } }; +#endif } // namespace chrono } // namespace boost diff --git a/boost/chrono/round.hpp b/boost/chrono/round.hpp index 3d0619e681..09741fcf09 100644 --- a/boost/chrono/round.hpp +++ b/boost/chrono/round.hpp @@ -26,18 +26,22 @@ namespace boost template <class To, class Rep, class Period> To round(const duration<Rep, Period>& d) { + typedef typename common_type<To, duration<Rep, Period> >::type result_type; + result_type diff0; + result_type diff1; + To t0 = duration_cast<To>(d); To t1 = t0; - ++t1; -#if 0 - // Avoid the user of BOOST_AUTO to make the library portable to Sun, PGI, .. - BOOST_AUTO(diff0, d - t0); - BOOST_AUTO(diff1, t1 - d); -#else - typedef typename common_type<To, duration<Rep, Period> >::type result_type; - result_type diff0 = d - t0; - result_type diff1 = t1 - d; -#endif + if (t0>d) { + --t1; + diff0 = t0 - d; + diff1 = d - t1; + } else { + ++t1; + diff0 = d - t0; + diff1 = t1 - d; + } + if (diff0 == diff1) { if (t0.count() & 1) diff --git a/boost/chrono/system_clocks.hpp b/boost/chrono/system_clocks.hpp index df8b79e207..5ba6a3b0e9 100644 --- a/boost/chrono/system_clocks.hpp +++ b/boost/chrono/system_clocks.hpp @@ -67,7 +67,7 @@ TODO: #include <ctime> # if defined( BOOST_CHRONO_POSIX_API ) -# if ! defined(CLOCK_REALTIME) +# if ! defined(CLOCK_REALTIME) && ! defined (__hpux__) # error <time.h> does not supply CLOCK_REALTIME # endif # endif diff --git a/boost/chrono/time_point.hpp b/boost/chrono/time_point.hpp index 9aad25e66c..6449fac6e1 100644 --- a/boost/chrono/time_point.hpp +++ b/boost/chrono/time_point.hpp @@ -168,16 +168,17 @@ namespace chrono { duration d_; public: - BOOST_CONSTEXPR + BOOST_FORCEINLINE BOOST_CONSTEXPR time_point() : d_(duration::zero()) {} - BOOST_CONSTEXPR explicit time_point(const duration& d) + BOOST_FORCEINLINE BOOST_CONSTEXPR + explicit time_point(const duration& d) : d_(d) {} // conversions template <class Duration2> - BOOST_CONSTEXPR + BOOST_FORCEINLINE BOOST_CONSTEXPR time_point(const time_point<clock, Duration2>& t , typename boost::enable_if < @@ -217,12 +218,12 @@ namespace chrono { // special values - static BOOST_CONSTEXPR time_point + static BOOST_CHRONO_LIB_CONSTEXPR time_point min BOOST_PREVENT_MACRO_SUBSTITUTION () { return time_point((duration::min)()); } - static BOOST_CONSTEXPR time_point + static BOOST_CHRONO_LIB_CONSTEXPR time_point max BOOST_PREVENT_MACRO_SUBSTITUTION () { return time_point((duration::max)()); diff --git a/boost/chrono/typeof/boost/chrono/chrono.hpp b/boost/chrono/typeof/boost/chrono/chrono.hpp index 88dad54ed0..0b0d274800 100644 --- a/boost/chrono/typeof/boost/chrono/chrono.hpp +++ b/boost/chrono/typeof/boost/chrono/chrono.hpp @@ -15,7 +15,6 @@ #define BOOST_CHRONO_TYPEOF_CHRONO_HPP #include <boost/chrono/chrono.hpp> -#define BOOST_TYPEOF_SILENT #include <boost/typeof/typeof.hpp> #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() diff --git a/boost/chrono/typeof/boost/ratio.hpp b/boost/chrono/typeof/boost/ratio.hpp index 4438a4f9dc..d61ce2440c 100644 --- a/boost/chrono/typeof/boost/ratio.hpp +++ b/boost/chrono/typeof/boost/ratio.hpp @@ -15,8 +15,6 @@ #define BOOST_CHRONO_TYPEOF_RATIO_HPP #include <boost/ratio/ratio.hpp> -#define BOOST_TYPEOF_SILENT - #include <boost/typeof/typeof.hpp> #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() |