From 775c3495e215ed1a9604ec045465483360704b52 Mon Sep 17 00:00:00 2001
From: Andy Cedilnik <andy.cedilnik@kitware.com>
Date: Wed, 12 Oct 2005 13:36:07 -0400
Subject: ENH: Add file time comparison code

---
 Source/CMakeLists.txt           |   2 +
 Source/cmFileTimeComparison.cxx | 168 ++++++++++++++++++++++++++++++++++++++++
 Source/cmFileTimeComparison.h   |  50 ++++++++++++
 bootstrap                       |   1 +
 4 files changed, 221 insertions(+)
 create mode 100644 Source/cmFileTimeComparison.cxx
 create mode 100644 Source/cmFileTimeComparison.h

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 21334b2..970d11b 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -115,6 +115,8 @@ SET(SRCS
   cmMakefile.cxx
   cmMakefile.h
   cmOrderLinkDirectories.cxx
+  cmFileTimeComparison.cxx
+  cmFileTimeComparison.h
   cmSourceFile.cxx
   cmSourceFile.h
   cmSourceGroup.cxx
diff --git a/Source/cmFileTimeComparison.cxx b/Source/cmFileTimeComparison.cxx
new file mode 100644
index 0000000..2b0c8cf
--- /dev/null
+++ b/Source/cmFileTimeComparison.cxx
@@ -0,0 +1,168 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmFileTimeComparison.h"
+
+#include <cmsys/Directory.hxx>
+#include <cmsys/RegularExpression.hxx>
+#include <cmsys/SystemTools.hxx>
+
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+# include <cmsys/hash_map.hxx>
+#endif
+
+#include <ctype.h>
+#include <sys/stat.h>
+
+#if !defined(_WIN32) || defined(__CYGWIN__)
+#  define cmFileTimeComparison_Type struct stat
+#else
+#  define cmFileTimeComparison_Type FILETIME
+#endif
+
+class cmFileTimeComparisonInternal
+{
+public:
+  inline bool FileTimeCompare(const char* f1, const char* f2, int* result);
+
+private:
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+  class HashString
+    {
+  public:
+    size_t operator()(const cmStdString& s) const
+      {
+      return h(s.c_str());
+      }
+    cmsys::hash<const char*> h;
+    };
+  typedef cmsys::hash_map<cmStdString, cmFileTimeComparison_Type, HashString> FileStatsMap;
+  FileStatsMap Files;
+#endif
+
+  inline bool Stat(const char* fname, cmFileTimeComparison_Type* st);
+  inline int Compare(cmFileTimeComparison_Type* st1, cmFileTimeComparison_Type* st2);
+};
+
+bool cmFileTimeComparisonInternal::Stat(const char* fname, cmFileTimeComparison_Type* st)
+{
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+  cmFileTimeComparisonInternal::FileStatsMap::iterator fit = this->Files.find(fname);
+  if ( fit != this->Files.end() )
+    {
+    *st = fit->second;
+    return 0;
+    }
+#endif
+#if !defined(_WIN32) || defined(__CYGWIN__)
+  int res = ::stat(fname, st);
+  if ( res != 0 )
+    {
+    return false;
+    }
+#else
+  // Windows version.  Create file handles and get the modification times.
+  HANDLE hf1 = CreateFile(f1, GENERIC_READ, FILE_SHARE_READ,
+                          NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
+                          NULL);
+  if(hf1 == INVALID_HANDLE_VALUE)
+    {
+    return false;
+    }
+  if(!GetFileTime(hf1, 0, 0, st))
+    {
+    CloseHandle(hf1);
+    return false;
+    }
+  CloseHandle(hf1);
+#endif
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+  this->Files[fname] = *st;
+#endif
+  return true;
+}
+
+cmFileTimeComparison::cmFileTimeComparison()
+{
+  m_Internals = new cmFileTimeComparisonInternal;
+}
+
+cmFileTimeComparison::~cmFileTimeComparison()
+{
+  delete m_Internals;
+}
+
+bool cmFileTimeComparison::FileTimeCompare(const char* f1, const char* f2, int* result)
+{
+  return m_Internals->FileTimeCompare(f1, f2, result);
+}
+
+int cmFileTimeComparisonInternal::Compare(cmFileTimeComparison_Type* s1, cmFileTimeComparison_Type* s2)
+{
+#if !defined(_WIN32) || defined(__CYGWIN__)
+# if KWSYS_STAT_HAS_ST_MTIM
+  // Compare using nanosecond resolution.
+  if(s1->st_mtim.tv_sec < s2->st_mtim.tv_sec)
+    {
+    return -1;
+    }
+  else if(s1->st_mtim.tv_sec > s2->st_mtim.tv_sec)
+    {
+    return 1;
+    }
+  else if(s1->st_mtim.tv_nsec < s2->st_mtim.tv_nsec)
+    {
+    return -1;
+    }
+  else if(s1->st_mtim.tv_nsec > s2->st_mtim.tv_nsec)
+    {
+    return 1;
+    }
+# else
+  // Compare using 1 second resolution.
+  if(s1->st_mtime < s2->st_mtime)
+    {
+    return -1;
+    }
+  else if(s1->st_mtime > s2->st_mtime)
+    {
+    return 1;
+    }
+  return 0;
+# endif
+#else
+  return (int)CompareFileTime(s1, s2);
+#endif
+}
+
+bool cmFileTimeComparisonInternal::FileTimeCompare(const char* f1, const char* f2, int* result)
+{
+  // Default to same time.
+  *result = 0;
+  cmFileTimeComparison_Type s1;
+  if(!this->Stat(f1, &s1))
+    {
+    return false;
+    }
+  cmFileTimeComparison_Type s2;
+  if(!this->Stat(f2, &s2))
+    {
+    return false;
+    }
+  *result = this->Compare(&s1, &s2);
+  return true;
+}
+
diff --git a/Source/cmFileTimeComparison.h b/Source/cmFileTimeComparison.h
new file mode 100644
index 0000000..2fc243f
--- /dev/null
+++ b/Source/cmFileTimeComparison.h
@@ -0,0 +1,50 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmFileTimeComparison_h
+#define cmFileTimeComparison_h
+
+#include "cmStandardIncludes.h"
+
+class cmFileTimeComparisonInternal;
+
+/** \class cmFileTimeComparison
+ * \brief Helper class for performing globbing searches.
+ *
+ * Finds all files that match a given globbing expression.
+ */
+class cmFileTimeComparison
+{
+public:
+  cmFileTimeComparison();
+  ~cmFileTimeComparison();
+
+  /**
+   *  Compare file modification times.
+   *  Return true for successful comparison and false for error.
+   *  When true is returned, result has -1, 0, +1 for
+   *  f1 older, same, or newer than f2.  
+   */
+  bool FileTimeCompare(const char* f1, const char* f2, int* result);
+
+protected:
+  
+  cmFileTimeComparisonInternal* m_Internals;
+};
+
+
+#endif
+
diff --git a/bootstrap b/bootstrap
index 7e912ff..0070a5d 100755
--- a/bootstrap
+++ b/bootstrap
@@ -49,6 +49,7 @@ CMAKE_CXX_SOURCES="\
   cmLocalGenerator \
   cmSourceFile \
   cmSystemTools \
+  cmFileTimeComparison \
   cmGlobalUnixMakefileGenerator3 \
   cmGlobalXCodeGenerator \
   cmLocalXCodeGenerator \
-- 
cgit v0.12