From 6f24c4e93f6ae897b793f894b67543d86c7de477 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Wed, 13 Mar 2019 16:54:01 +0100 Subject: New cmFileTime class The new cmFileTime class stores the file modification time as an OS independent nanosecond count. Its main use is to load and compare file modification times in nanosecond and second resolution. --- Source/CMakeLists.txt | 4 ++ Source/cmFileTime.cxx | 49 +++++++++++++++++++ Source/cmFileTime.h | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++ bootstrap | 1 + 4 files changed, 184 insertions(+) create mode 100644 Source/cmFileTime.cxx create mode 100644 Source/cmFileTime.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 696826f..140754c 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -236,6 +236,8 @@ set(SRCS cmFileLockResult.h cmFilePathChecksum.cxx cmFilePathChecksum.h + cmFileTime.cxx + cmFileTime.h cmFileTimeComparison.cxx cmFileTimeComparison.h cmFortranParserImpl.cxx @@ -796,6 +798,8 @@ foreach(check else() set(CMake_${check} 0) endif() + set_property(SOURCE cmFileTime.cxx APPEND PROPERTY + COMPILE_DEFINITIONS CMake_${check}=${CMake_${check}}) set_property(SOURCE cmFileTimeComparison.cxx APPEND PROPERTY COMPILE_DEFINITIONS CMake_${check}=${CMake_${check}}) endforeach() diff --git a/Source/cmFileTime.cxx b/Source/cmFileTime.cxx new file mode 100644 index 0000000..253457f --- /dev/null +++ b/Source/cmFileTime.cxx @@ -0,0 +1,49 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmFileTime.h" + +#include +#include + +// Use a platform-specific API to get file times efficiently. +#if !defined(_WIN32) || defined(__CYGWIN__) +# include "cm_sys_stat.h" +#else +# include "cmsys/Encoding.hxx" +# include +#endif + +bool cmFileTime::Load(std::string const& fileName) +{ +#if !defined(_WIN32) || defined(__CYGWIN__) + // POSIX version. Use the stat function. + struct stat fst; + if (::stat(fileName.c_str(), &fst) != 0) { + return false; + } +# if CMake_STAT_HAS_ST_MTIM + // Nanosecond resolution + this->NS = fst.st_mtim.tv_sec * NsPerS + fst.st_mtim.tv_nsec; +# elif CMake_STAT_HAS_ST_MTIMESPEC + // Nanosecond resolution + this->NS = fst.st_mtimespec.tv_sec * NsPerS + fst.st_mtimespec.tv_nsec; +# else + // Second resolution + this->NS = fst.st_mtime * NsPerS; +# endif +#else + // Windows version. Get the modification time from extended file attributes. + WIN32_FILE_ATTRIBUTE_DATA fdata; + if (!GetFileAttributesExW(cmsys::Encoding::ToWide(fileName).c_str(), + GetFileExInfoStandard, &fdata)) { + return false; + } + + // Copy the file time to the output location. + this->NS = (static_cast(fdata.ftLastWriteTime.dwHighDateTime) << 32) | + static_cast(fdata.ftLastWriteTime.dwLowDateTime); + // The file time resolution is 100 ns. + this->NS *= 100; +#endif + return true; +} diff --git a/Source/cmFileTime.h b/Source/cmFileTime.h new file mode 100644 index 0000000..4c8e556 --- /dev/null +++ b/Source/cmFileTime.h @@ -0,0 +1,130 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmFileTime_h +#define cmFileTime_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include + +/** \class cmFileTime + * \brief Abstract file modification time with support for comparison with + * other file modification times. + */ +class cmFileTime +{ +public: + typedef long long NSC; + static constexpr NSC NsPerS = 1000000000; + + cmFileTime() = default; + ~cmFileTime() = default; + + /** + * @brief Loads the file time of fileName from the file system + * @return true on success + */ + bool Load(std::string const& fileName); + + /** + * @brief Return true if this is older than ftm + */ + bool Older(cmFileTime const& ftm) const { return (this->NS - ftm.NS) < 0; } + + /** + * @brief Return true if this is newer than ftm + */ + bool Newer(cmFileTime const& ftm) const { return (ftm.NS - this->NS) < 0; } + + /** + * @brief Return true if this is the same as ftm + */ + bool Equal(cmFileTime const& ftm) const { return this->NS == ftm.NS; } + + /** + * @brief Return true if this is not the same as ftm + */ + bool Differ(cmFileTime const& ftm) const { return this->NS != ftm.NS; } + + /** + * @brief Compare file modification times. + * @return -1, 0, +1 for this older, same, or newer than ftm. + */ + int Compare(cmFileTime const& ftm) + { + NSC const diff = this->NS - ftm.NS; + if (diff == 0) { + return 0; + } + return (diff < 0) ? -1 : 1; + } + + // -- Comparison in second resolution + + /** + * @brief Return true if this is at least a second older than ftm + */ + bool OlderS(cmFileTime const& ftm) const + { + return (ftm.NS - this->NS) >= cmFileTime::NsPerS; + } + + /** + * @brief Return true if this is at least a second newer than ftm + */ + bool NewerS(cmFileTime const& ftm) const + { + return (this->NS - ftm.NS) >= cmFileTime::NsPerS; + } + + /** + * @brief Return true if this is within the same second as ftm + */ + bool EqualS(cmFileTime const& ftm) const + { + NSC diff = this->NS - ftm.NS; + if (diff < 0) { + diff = -diff; + } + return (diff < cmFileTime::NsPerS); + } + + /** + * @brief Return true if this is older or newer than ftm by at least a second + */ + bool DifferS(cmFileTime const& ftm) const + { + NSC diff = this->NS - ftm.NS; + if (diff < 0) { + diff = -diff; + } + return (diff >= cmFileTime::NsPerS); + } + + /** + * @brief Compare file modification times. + * @return -1: this at least a second older, 0: this within the same second + * as ftm, +1: this at least a second newer than ftm. + */ + int CompareS(cmFileTime const& ftm) const + { + NSC const diff = this->NS - ftm.NS; + if (diff <= -cmFileTime::NsPerS) { + return -1; + } + if (diff >= cmFileTime::NsPerS) { + return 1; + } + return 0; + } + + /** + * @brief The file modification time in nanoseconds + */ + NSC GetNS() const { return this->NS; } + +private: + NSC NS = 0; +}; + +#endif diff --git a/bootstrap b/bootstrap index af05024..77293c8 100755 --- a/bootstrap +++ b/bootstrap @@ -304,6 +304,7 @@ CMAKE_CXX_SOURCES="\ cmFileCommand \ cmFileCopier \ cmFileInstaller \ + cmFileTime \ cmFileTimeComparison \ cmFindBase \ cmFindCommon \ -- cgit v0.12