#ifndef FILESYSTEM_TIME_UTILS_H
#define FILESYSTEM_TIME_UTILS_H
#include <__config>
#include <array>
#include <chrono>
#include <filesystem>
#include <limits>
#include <ratio>
#include <system_error>
#include <type_traits>
#include <utility>
#include "error.h"
#include "format_string.h"
#if defined(_LIBCPP_WIN32API)
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
# include <windows.h>
#else
# include <fcntl.h>
# include <sys/stat.h>
# include <sys/time.h>
#endif
#if defined(UTIME_OMIT)
#define _LIBCPP_USE_UTIMENSAT
#endif
_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
namespace detail {
#if defined(_LIBCPP_WIN32API)
struct TimeSpec {
int64_t tv_sec;
int64_t tv_nsec;
};
struct StatT {
unsigned st_mode;
TimeSpec st_atim;
TimeSpec st_mtim;
uint64_t st_dev;
struct FileIdStruct {
unsigned char id[16];
bool operator==(const FileIdStruct& other) const {
for (int i = 0; i < 16; i++)
if (id[i] != other.id[i])
return false;
return true;
}
} st_ino;
uint32_t st_nlink;
uintmax_t st_size;
};
#define FILE_TIME_OFFSET_SECS …
inline TimeSpec filetime_to_timespec(LARGE_INTEGER li) {
TimeSpec ret;
ret.tv_sec = li.QuadPart / 10000000 - FILE_TIME_OFFSET_SECS;
ret.tv_nsec = (li.QuadPart % 10000000) * 100;
return ret;
}
inline TimeSpec filetime_to_timespec(FILETIME ft) {
LARGE_INTEGER li;
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
return filetime_to_timespec(li);
}
inline FILETIME timespec_to_filetime(TimeSpec ts) {
LARGE_INTEGER li;
li.QuadPart = ts.tv_nsec / 100 + (ts.tv_sec + FILE_TIME_OFFSET_SECS) * 10000000;
FILETIME ft;
ft.dwLowDateTime = li.LowPart;
ft.dwHighDateTime = li.HighPart;
return ft;
}
#else
TimeSpec;
TimeVal;
StatT;
inline TimeVal make_timeval(TimeSpec const& ts) { … }
#endif
duration;
duration_cast;
template <class FileTimeT, class TimeT, bool IsFloat = is_floating_point<typename FileTimeT::rep>::value>
struct time_util_base { … };
time_util_base<FileTimeT, TimeT, true>;
template <class FileTimeT, class TimeT>
const typename FileTimeT::rep time_util_base<FileTimeT, TimeT, true>::max_seconds = …;
template <class FileTimeT, class TimeT>
const typename FileTimeT::rep time_util_base<FileTimeT, TimeT, true>::max_nsec = …;
template <class FileTimeT, class TimeT>
const typename FileTimeT::rep time_util_base<FileTimeT, TimeT, true>::min_seconds = …;
template <class FileTimeT, class TimeT>
const typename FileTimeT::rep time_util_base<FileTimeT, TimeT, true>::min_nsec_timespec = …;
template <class FileTimeT, class TimeT, class TimeSpecT>
struct time_util : time_util_base<FileTimeT, TimeT> { … };
#if defined(_LIBCPP_WIN32API)
using fs_time = time_util<file_time_type, int64_t, TimeSpec>;
#else
fs_time;
#endif
#if defined(__APPLE__)
inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
inline TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
#elif defined(__MVS__)
inline TimeSpec extract_mtime(StatT const& st) {
TimeSpec TS = {st.st_mtime, 0};
return TS;
}
inline TimeSpec extract_atime(StatT const& st) {
TimeSpec TS = {st.st_atime, 0};
return TS;
}
#elif defined(_AIX)
inline TimeSpec extract_mtime(StatT const& st) {
TimeSpec TS = {st.st_mtime, st.st_mtime_n};
return TS;
}
inline TimeSpec extract_atime(StatT const& st) {
TimeSpec TS = {st.st_atime, st.st_atime_n};
return TS;
}
#else
inline TimeSpec extract_mtime(StatT const& st) { … }
inline TimeSpec extract_atime(StatT const& st) { … }
#endif
#ifndef _LIBCPP_HAS_NO_FILESYSTEM
# if !defined(_LIBCPP_WIN32API)
inline bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS, error_code& ec) { … }
# if defined(_LIBCPP_USE_UTIMENSAT)
inline bool posix_utimensat(const path& p, std::array<TimeSpec, 2> const& TS, error_code& ec) { … }
# endif
inline bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS, error_code& ec) { … }
# endif
inline file_time_type __extract_last_write_time(const path& p, const StatT& st, error_code* ec) { … }
#endif
}
_LIBCPP_END_NAMESPACE_FILESYSTEM
#endif