Merge branch 'std-filesystem-time-hotfix' into 'master'

Fix "7020-crash-when-clicking-load-shortly-after-quicksaving"

Closes #7020

See merge request OpenMW/openmw!2428
coverity_clang_test
AnyOldName3 2 years ago
commit ebbd4e059e

@ -639,14 +639,13 @@ std::time_t MwIniImporter::lastWriteTime(const std::filesystem::path& filename,
if (std::filesystem::exists(filename)) if (std::filesystem::exists(filename))
{ {
std::filesystem::path resolved = std::filesystem::canonical(filename); std::filesystem::path resolved = std::filesystem::canonical(filename);
writeTime = Misc::to_time_t(std::filesystem::last_write_time(resolved)); const auto time = std::filesystem::last_write_time(resolved);
writeTime = Misc::toTimeT(time);
// print timestamp // print timestamp
const int size = 1024; const auto str = Misc::fileTimeToString(time, "%x %X");
char timeStrBuffer[size]; if (!str.empty())
if (std::strftime(timeStrBuffer, size, "%x %X", localtime(&writeTime)) > 0) std::cout << "content file: " << resolved << " timestamp = (" << writeTime << ") " << str << std::endl;
std::cout << "content file: " << resolved << " timestamp = (" << writeTime << ") " << timeStrBuffer
<< std::endl;
} }
return writeTime; return writeTime;
} }

@ -30,6 +30,7 @@
#include <components/files/conversion.hpp> #include <components/files/conversion.hpp>
#include <components/misc/helpviewer.hpp> #include <components/misc/helpviewer.hpp>
#include <components/misc/timeconvert.hpp>
#include <components/version/version.hpp> #include <components/version/version.hpp>
#include "globaldebugprofilemenu.hpp" #include "globaldebugprofilemenu.hpp"
@ -765,11 +766,7 @@ void CSVDoc::View::infoAbout()
#endif #endif
// Get current year // Get current year
time_t now = time(nullptr); const auto copyrightInfo = Misc::timeToString(std::chrono::system_clock::now(), "Copyright © 2008-%Y OpenMW Team");
struct tm tstruct;
char copyrightInfo[40];
tstruct = *localtime(&now);
strftime(copyrightInfo, sizeof(copyrightInfo), "Copyright © 2008-%Y OpenMW Team", &tstruct);
QString aboutText = QString( QString aboutText = QString(
"<p style=\"white-space: pre-wrap;\">" "<p style=\"white-space: pre-wrap;\">"
@ -788,7 +785,8 @@ void CSVDoc::View::infoAbout()
.arg(versionInfo, .arg(versionInfo,
tr("OpenMW-CS is a content file editor for OpenMW, a modern, free and open source game " tr("OpenMW-CS is a content file editor for OpenMW, a modern, free and open source game "
"engine."), "engine."),
tr(copyrightInfo), tr("Home Page:"), tr("Forum:"), tr("Bug Tracker:"), tr("IRC:")); tr(copyrightInfo.c_str()), tr("Home Page:"), tr("Forum:"), tr("Bug Tracker:"),
tr("IRC:"));
QMessageBox::about(this, "About OpenMW-CS", aboutText); QMessageBox::about(this, "About OpenMW-CS", aboutText);
} }

@ -410,11 +410,8 @@ namespace MWGui
throw std::runtime_error("Can't find selected slot"); throw std::runtime_error("Can't find selected slot");
std::stringstream text; std::stringstream text;
time_t time = Misc::to_time_t(mCurrentSlot->mTimeStamp);
struct tm* timeinfo;
timeinfo = localtime(&time);
text << std::put_time(timeinfo, "%Y.%m.%d %T") << "\n"; text << Misc::fileTimeToString(mCurrentSlot->mTimeStamp, "%Y.%m.%d %T") << "\n";
text << "#{sLevel} " << mCurrentSlot->mProfile.mPlayerLevel << "\n"; text << "#{sLevel} " << mCurrentSlot->mProfile.mPlayerLevel << "\n";
text << "#{sCell=" << mCurrentSlot->mProfile.mPlayerCell << "}\n"; text << "#{sCell=" << mCurrentSlot->mProfile.mPlayerCell << "}\n";

@ -79,7 +79,7 @@ void MWState::Character::addSlot(const ESM::SavedGame& profile)
} }
slot.mProfile = profile; slot.mProfile = profile;
slot.mTimeStamp = std::filesystem::file_time_type(); slot.mTimeStamp = std::filesystem::file_time_type::clock::now();
mSlots.push_back(slot); mSlots.push_back(slot);
} }
@ -157,7 +157,7 @@ const MWState::Slot* MWState::Character::updateSlot(const Slot* slot, const ESM:
Slot newSlot = *slot; Slot newSlot = *slot;
newSlot.mProfile = profile; newSlot.mProfile = profile;
newSlot.mTimeStamp = std::filesystem::file_time_type(); newSlot.mTimeStamp = std::filesystem::file_time_type::clock::now();
mSlots.erase(mSlots.begin() + index); mSlots.erase(mSlots.begin() + index);

@ -223,18 +223,20 @@ bool Config::LauncherSettings::isEqual(const QStringList& list1, const QStringLi
QString Config::LauncherSettings::makeNewContentListName() QString Config::LauncherSettings::makeNewContentListName()
{ {
// basically, use date and time as the name e.g. YYYY-MM-DDThh:mm:ss // basically, use date and time as the name e.g. YYYY-MM-DDThh:mm:ss
time_t rawtime; auto rawtime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
struct tm* timeinfo; tm timeinfo{};
#ifdef _WIN32
time(&rawtime); (void)localtime_s(&timeinfo, &rawtime);
timeinfo = localtime(&rawtime); #else
(void)localtime_r(&rawtime, &timeinfo);
#endif
int base = 10; int base = 10;
QChar zeroPad('0'); QChar zeroPad('0');
return QString("%1-%2-%3T%4:%5:%6") return QString("%1-%2-%3T%4:%5:%6")
.arg(timeinfo->tm_year + 1900, 4) .arg(timeinfo.tm_year + 1900, 4)
.arg(timeinfo->tm_mon + 1, 2, base, zeroPad) .arg(timeinfo.tm_mon + 1, 2, base, zeroPad)
.arg(timeinfo->tm_mday, 2, base, zeroPad) .arg(timeinfo.tm_mday, 2, base, zeroPad)
.arg(timeinfo->tm_hour, 2, base, zeroPad) .arg(timeinfo.tm_hour, 2, base, zeroPad)
.arg(timeinfo->tm_min, 2, base, zeroPad) .arg(timeinfo.tm_min, 2, base, zeroPad)
.arg(timeinfo->tm_sec, 2, base, zeroPad); .arg(timeinfo.tm_sec, 2, base, zeroPad);
} }

@ -99,7 +99,13 @@ namespace Debug
prefix[0] = '['; prefix[0] = '[';
const auto now = std::chrono::system_clock::now(); const auto now = std::chrono::system_clock::now();
const auto time = std::chrono::system_clock::to_time_t(now); const auto time = std::chrono::system_clock::to_time_t(now);
prefixSize = std::strftime(prefix + 1, sizeof(prefix) - 1, "%T", std::localtime(&time)) + 1; tm time_info{};
#ifdef _WIN32
(void)localtime_s(&time_info, &time);
#else
(void)localtime_r(&time, &time_info);
#endif
prefixSize = std::strftime(prefix + 1, sizeof(prefix) - 1, "%T", &time_info) + 1;
char levelLetter = " EWIVD*"[int(level)]; char levelLetter = " EWIVD*"[int(level)];
const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count(); const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
prefixSize += snprintf(prefix + prefixSize, sizeof(prefix) - prefixSize, ".%03u %c] ", prefixSize += snprintf(prefix + prefixSize, sizeof(prefix) - prefixSize, ".%03u %c] ",

@ -44,7 +44,7 @@ namespace fx
: mName(std::move(name)) : mName(std::move(name))
, mFileName(Files::pathToUnicodeString( , mFileName(Files::pathToUnicodeString(
(Files::pathFromUnicodeString(Technique::sSubdir) / (mName + Technique::sExt)))) (Files::pathFromUnicodeString(Technique::sSubdir) / (mName + Technique::sExt))))
, mLastModificationTime(std::filesystem::file_time_type()) , mLastModificationTime(std::filesystem::file_time_type::clock::now())
, mWidth(width) , mWidth(width)
, mHeight(height) , mHeight(height)
, mVFS(vfs) , mVFS(vfs)

@ -2,16 +2,42 @@
#define OPENMW_COMPONENTS_MISC_TIMECONVERT_H #define OPENMW_COMPONENTS_MISC_TIMECONVERT_H
#include <chrono> #include <chrono>
#include <ctime>
namespace Misc namespace Misc
{ {
template <typename TP> inline std::time_t toTimeT(std::filesystem::file_time_type tp)
inline std::time_t to_time_t(TP tp)
{ {
using namespace std::chrono; using namespace std::chrono;
auto sctp = time_point_cast<system_clock::duration>(tp - TP::clock::now() + system_clock::now()); #if __cpp_lib_chrono >= 201907
return system_clock::to_time_t(sctp); const auto systemTime = clock_cast<system_clock>(tp);
#else
auto systemTime = time_point_cast<system_clock::duration>(
tp - std::filesystem::file_time_type::clock::now() + system_clock::now());
#endif
return system_clock::to_time_t(systemTime);
}
inline std::string timeTToString(const std::time_t tp, const char* fmt)
{
tm time_info{};
#ifdef _WIN32
(void)localtime_s(&time_info, &tp);
#else
(void)localtime_r(&tp, &time_info);
#endif
std::stringstream out;
out << std::put_time(&time_info, fmt);
return out.str();
}
inline std::string fileTimeToString(const std::filesystem::file_time_type& tp, const char* fmt)
{
return timeTToString(toTimeT(tp), fmt);
}
inline std::string timeToString(const std::chrono::system_clock::time_point& tp, const char* fmt)
{
return timeTToString(std::chrono::system_clock::to_time_t(tp), fmt);
} }
} // namespace Misc } // namespace Misc

Loading…
Cancel
Save