From 9aab0cc267169fb2d2bf889f64f49afbdaa16dc2 Mon Sep 17 00:00:00 2001 From: Daniel Scharrer Date: Sun, 20 Jan 2013 13:48:44 +0100 Subject: [PATCH] Abstract platform-specific time functions --- CMakeLists.txt | 6 +++ src/cli/debug.cpp | 12 +++--- src/configure.hpp.in | 3 ++ src/setup/data.cpp | 37 +---------------- src/util/time.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++ src/util/time.hpp | 48 ++++++++++++++++++++++ 6 files changed, 162 insertions(+), 42 deletions(-) create mode 100644 src/util/time.cpp create mode 100644 src/util/time.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a87c74..79ad4a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,6 +122,11 @@ add_cxxflag("-fvisibility-inlines-hidden") check_symbol_exists(isatty "unistd.h" INNOEXTRACT_HAVE_ISATTY) check_symbol_exists(ioctl "sys/ioctl.h" INNOEXTRACT_HAVE_IOCTL) check_symbol_exists(timegm "time.h" INNOEXTRACT_HAVE_TIMEGM) +check_symbol_exists(_mkgmtime "time.h" INNOEXTRACT_HAVE_MKGMTIME) +check_symbol_exists(gmtime_r "time.h" INNOEXTRACT_HAVE_GMTIME_R) +if(NOT INNOEXTRACT_HAVE_GMTIME_R) + check_symbol_exists(_gmtime_s "time.h" INNOEXTRACT_HAVE_GMTIME_S) +endif() check_symbol_exists(bswap_16 "byteswap.h" INNOEXTRACT_HAVE_BSWAP_16) check_symbol_exists(bswap_32 "byteswap.h" INNOEXTRACT_HAVE_BSWAP_32) @@ -176,6 +181,7 @@ set(INNOEXTRACT_SOURCES src/util/console.cpp src/util/load.cpp src/util/log.cpp + src/util/time.cpp ) diff --git a/src/cli/debug.cpp b/src/cli/debug.cpp index cbd3c30..ed4c028 100644 --- a/src/cli/debug.cpp +++ b/src/cli/debug.cpp @@ -47,6 +47,7 @@ #include "util/load.hpp" #include "util/log.hpp" #include "util/output.hpp" +#include "util/time.hpp" #include "util/util.hpp" using std::cout; @@ -345,12 +346,7 @@ static void print_entry(const setup::info & info, size_t i, const setup::data_en cout << " Checksum: " << entry.file.checksum << '\n'; - std::tm t; - if(entry.options & setup::data_entry::TimeStampInUTC) { - gmtime_r(&entry.timestamp, &t); - } else { - localtime_r(&entry.timestamp, &t); - } + std::tm t = util::format_time(entry.timestamp); cout << " Timestamp: " << color::cyan << (t.tm_year + 1900) << '-' << std::setfill('0') << std::setw(2) << (t.tm_mon + 1) @@ -358,7 +354,9 @@ static void print_entry(const setup::info & info, size_t i, const setup::data_en << ' ' << std::setfill(' ') << std::setw(2) << t.tm_hour << ':' << std::setfill('0') << std::setw(2) << t.tm_min << ':' << std::setfill('0') << std::setw(2) << t.tm_sec - << color::reset << " +" << entry.timestamp_nsec << '\n'; + << color::reset << " +" << entry.timestamp_nsec + << ((entry.options & setup::data_entry::TimeStampInUTC) ? " (UTC)" : " (local)") + << '\n'; cout << if_not_zero(" Options", entry.options); diff --git a/src/configure.hpp.in b/src/configure.hpp.in index 720239c..3f5e3d8 100644 --- a/src/configure.hpp.in +++ b/src/configure.hpp.in @@ -5,6 +5,9 @@ #cmakedefine01 INNOEXTRACT_HAVE_ISATTY #cmakedefine01 INNOEXTRACT_HAVE_IOCTL #cmakedefine01 INNOEXTRACT_HAVE_TIMEGM +#cmakedefine01 INNOEXTRACT_HAVE_MKGMTIME +#cmakedefine01 INNOEXTRACT_HAVE_GMTIME_R +#cmakedefine01 INNOEXTRACT_HAVE_GMTIME_S #cmakedefine01 INNOEXTRACT_HAVE_LZMA #cmakedefine01 INNOEXTRACT_IS_BIG_ENDIAN #cmakedefine01 INNOEXTRACT_HAVE_BSWAP_16 diff --git a/src/setup/data.cpp b/src/setup/data.cpp index 6b6e6d2..fd9336c 100644 --- a/src/setup/data.cpp +++ b/src/setup/data.cpp @@ -20,44 +20,15 @@ #include "setup/data.hpp" -#include "configure.hpp" - -#if INNOEXTRACT_HAVE_TIMEGM -#include -#else -#include -#endif - #include "setup/version.hpp" #include "util/load.hpp" #include "util/log.hpp" #include "util/output.hpp" #include "util/storedenum.hpp" +#include "util/time.hpp" namespace setup { -#if !INNOEXTRACT_HAVE_TIMEGM - -static std::time_t mkgmtime(struct tm * tm) { - - char * tz = getenv("TZ"); - setenv("TZ", "UTC", 1); - tzset(); - - std::time_t ret = std::mktime(tm); - - if(tz) { - setenv("TZ", tz, 1); - } else { - unsetenv("TZ"); - } - tzset(); - - return ret; -} - -#endif - void data_entry::load(std::istream & is, const version & version) { chunk.first_slice = load_number(is, version.bits); @@ -117,11 +88,7 @@ void data_entry::load(std::istream & is, const version & version) { t.tm_year = get_bits(date, 9, 15) + 1980 - 1900; // [80, 199] t.tm_isdst = -1; -#if INNOEXTRACT_HAVE_TIMEGM - timestamp = timegm(&t); -#else - timestamp = mkgmtime(&t); -#endif + timestamp = util::parse_time(t); timestamp_nsec = 0; } else { diff --git a/src/util/time.cpp b/src/util/time.cpp new file mode 100644 index 0000000..cb78aba --- /dev/null +++ b/src/util/time.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2011-2013 Daniel Scharrer + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author(s) be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#include "util/time.hpp" + +#include "configure.hpp" + +#if INNOEXTRACT_HAVE_TIMEGM || INNOEXTRACT_HAVE_MKGMTIME \ + || INNOEXTRACT_HAVE_GMTIME_R || INNOEXTRACT_HAVE_GMTIME_S +#include +#endif + +#if !INNOEXTRACT_HAVE_TIMEGM +#include +#endif + +namespace util { + +std::time_t parse_time(std::tm tm) { + +#if INNOEXTRACT_HAVE_TIMEGM + + return timegm(&tm); + +#elif INNOEXTRACT_HAVE_MKGMTIME + + return _mkgmtime(&tm); + +#else + + char * tz = getenv("TZ"); + setenv("TZ", "UTC", 1); + tzset(); + + std::time_t ret = std::mktime(&tm); + + if(tz) { + setenv("TZ", tz, 1); + } else { + unsetenv("TZ"); + } + tzset(); + + return ret; + +#endif + +} + +std::tm format_time(time_t t) { + + std::tm ret; + +#if INNOEXTRACT_HAVE_GMTIME_R + + gmtime_r(&t, &ret); + +#elif INNOEXTRACT_HAVE_GMTIME_S + + _gmtime_s(&ret, &t); + +#else + + // Hope that this is threadsafe... + ret = *gmtime(&t); + +#endif + + return ret; +} + +time_t to_local_time(time_t t) { + + // Format time as UTC ... + std::tm time = format_time(t); + + //... and interpret it as local time + return std::mktime(&time); +} + +} // namespace util diff --git a/src/util/time.hpp b/src/util/time.hpp new file mode 100644 index 0000000..65424f5 --- /dev/null +++ b/src/util/time.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011-2013 Daniel Scharrer + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author(s) be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#ifndef INNOEXTRACT_UTIL_TIME_HPP +#define INNOEXTRACT_UTIL_TIME_HPP + +#include + +namespace util { + +/*! + * Convert UTC clock time to a timestamp + * Note: may not be threadsafe on all systems! + */ +std::time_t parse_time(std::tm tm); + +/*! + * Convert a timestamp to UTC clock time + * Note: may not be threadsafe on all systems! + */ +std::tm format_time(std::time_t t); + +/*! + * Convert a timestamp to local time + * Note: may not be threadsafe on all systems! + */ +std::time_t to_local_time(std::time_t t); + +} // namespace util + +#endif // INNOEXTRACT_UTIL_TIME_HPP