From 985e8f5f28da87be779b80942577f088321024af Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 5 Dec 2014 13:26:29 +0200 Subject: Add support for starting processes, getting file timestamps g++-4.9 -std=c++11 -I.. -o bd bd.cxx process.cxx timestamp.cxx --- build/timestamp.cxx | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 build/timestamp.cxx (limited to 'build/timestamp.cxx') diff --git a/build/timestamp.cxx b/build/timestamp.cxx new file mode 100644 index 0000000..db8efb2 --- /dev/null +++ b/build/timestamp.cxx @@ -0,0 +1,154 @@ +// file : build/timestamp.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include + +#include // stat +#include // stat +#include // stat + +#include // localtime, gmtime, strftime + +#include +#include + +using namespace std; + +namespace build +{ + // Figuring out whether we have the nanoseconds in some form. + // + template + constexpr auto nsec (const S* s) -> decltype(s->st_mtim.tv_nsec) + { + return s->st_mtim.tv_nsec; // POSIX (GNU/Linux, Solaris). + } + + template + constexpr auto nsec (const S* s) -> decltype(s->st_mtimespec.tv_nsec) + { + return s->st_mtimespec.tv_nsec; // MacOS X. + } + + template + constexpr auto nsec (const S* s) -> decltype(s->st_mtime_n) + { + return s->st_mtime_n; // AIX 5.2 and later. + } + + template + constexpr int nsec (...) {return 0;} + + timestamp + path_timestamp (const std::string& p) + { + struct stat s; + if (stat (p.c_str (), &s) != 0) + { + if (errno == ENOENT || errno == ENOTDIR) + return timestamp_nonexistent; + else + throw system_error (errno, system_category ()); + } + + return system_clock::from_time_t (s.st_mtime) + + chrono::duration_cast ( + chrono::nanoseconds (nsec (&s))); + } + + ostream& + operator<< (ostream& os, timestamp ts) + { + // @@ replace with put_time() + // + + time_t t (system_clock::to_time_t (ts)); + + if (t == 0) + return os << ""; + + std::tm tm; + if (localtime_r (&t, &tm) == nullptr) + throw system_error (errno, system_category ()); + + // If year is greater than 9999, we will overflow. + // + char buf[20]; // YYYY-MM-DD HH:MM:SS\0 + if (strftime (buf, sizeof (buf), "%Y-%m-%d %H:%M:%S", &tm) == 0) + return os << ""; + + os << buf; + + using namespace chrono; + + timestamp sec (system_clock::from_time_t (t)); + nanoseconds ns (duration_cast (ts - sec)); + + if (ns != nanoseconds::zero ()) + { + os << '.'; + os.width (9); + os.fill ('0'); + os << ns.count (); + } + + return os; + } + + ostream& + operator<< (ostream& os, duration d) + { + // @@ replace with put_time() + // + + timestamp ts; // Epoch. + ts += d; + + time_t t (system_clock::to_time_t (ts)); + + const char* fmt (nullptr); + if (t >= 365 * 12 * 24 * 60 * 60) + fmt = "%Y-%m-%d %H:%M:%S"; + else if (t >= 12 * 24 * 60* 60) + fmt = "%m-%d %H:%M:%S"; + else if (t >= 24 * 60* 60) + fmt = "%d %H:%M:%S"; + else if (t >= 60 * 60) + fmt = "%H:%M:%S"; + else if (t >= 60) + fmt = "%M:%S"; + else if (t >= 1) + fmt = "%S"; + + if (fmt != nullptr) + { + std::tm tm; + if (gmtime_r (&t, &tm) == nullptr) + throw system_error (errno, system_category ()); + + char buf[20]; // YYYY-MM-DD HH:MM:SS\0 + if (strftime (buf, sizeof (buf), fmt, &tm) == 0) + return os << ""; + + os << buf; + } + + using namespace chrono; + + timestamp sec (system_clock::from_time_t (t)); + nanoseconds ns (duration_cast (ts - sec)); + + if (ns != nanoseconds::zero ()) + { + os << '.'; + os.width (9); + os.fill ('0'); + os << ns.count (); + } + else if (fmt == 0) + os << '0'; + + return os; + } +} -- cgit v1.1