diff --git a/src/common/string.h b/src/common/string.h index 5cb2fdba6..9a344ce2e 100644 --- a/src/common/string.h +++ b/src/common/string.h @@ -1,4 +1,5 @@ #pragma once +#include "fmt/core.h" #include "types.h" #include #include @@ -6,6 +7,7 @@ #include #include #include +#include // // String @@ -38,6 +40,8 @@ public: }; public: + using value_type = char; + // Creates an empty string. String(); @@ -107,6 +111,9 @@ public: void AppendFormattedString(const char* FormatString, ...) printflike(2, 3); void AppendFormattedStringVA(const char* FormatString, va_list ArgPtr); + template + void AppendFmtString(fmt::format_string fmt, T&&... args); + // append a single character to this string void PrependCharacter(char c); @@ -125,6 +132,9 @@ public: void PrependFormattedString(const char* FormatString, ...) printflike(2, 3); void PrependFormattedStringVA(const char* FormatString, va_list ArgPtr); + template + void PrependFmtString(fmt::format_string fmt, T&&... args); + // insert a string at the specified offset void InsertString(s32 offset, const String& appendStr); void InsertString(s32 offset, const char* appendStr); @@ -136,6 +146,9 @@ public: void Format(const char* FormatString, ...) printflike(2, 3); void FormatVA(const char* FormatString, va_list ArgPtr); + template + void Fmt(fmt::format_string fmt, T&&... args); + // compare one string to another bool Compare(const String& otherString) const; bool Compare(const char* otherText) const; @@ -283,6 +296,9 @@ public: bool operator>(const String& compString) const { return (NumericCompare(compString) > 0); } bool operator>(const char* compString) const { return (NumericCompare(compString) > 0); } + // STL adapters + ALWAYS_INLINE void push_back(value_type&& val) { AppendCharacter(val); } + protected: // Internal append function. void InternalPrepend(const char* pString, u32 Length); @@ -358,6 +374,14 @@ public: return returnValue; } + template + static StackString FromFmt(fmt::format_string fmt, T&&... args) + { + StackString ret; + fmt::vformat_to(std::back_inserter(ret), fmt, fmt::make_format_args(args...)); + return ret; + } + // Will use the string data provided. StackString& operator=(const StackString& copyString) { @@ -415,3 +439,24 @@ typedef StackString<512> PathString; // empty string global extern const String EmptyString; + +template +void String::AppendFmtString(fmt::format_string fmt, T&&... args) +{ + fmt::vformat_to(std::back_inserter(*this), fmt, fmt::make_format_args(args...)); +} + +template +void String::PrependFmtString(fmt::format_string fmt, T&&... args) +{ + TinyString str; + fmt::vformat_to(std::back_inserter(str), fmt, fmt::make_format_args(args...)); + PrependString(str); +} + +template +void String::Fmt(fmt::format_string fmt, T&&... args) +{ + Clear(); + fmt::vformat_to(std::back_inserter(*this), fmt, fmt::make_format_args(args...)); +} diff --git a/src/core/cheevos.cpp b/src/core/cheevos.cpp index 8cf5c2064..ffa3e1934 100644 --- a/src/core/cheevos.cpp +++ b/src/core/cheevos.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -539,7 +540,7 @@ void Cheevos::LoginCallback(s32 status_code, const FrontendCommon::HTTPDownloade g_host_interface->GetSettingsInterface()->SetStringValue("Cheevos", "Username", username.c_str()); g_host_interface->GetSettingsInterface()->SetStringValue("Cheevos", "Token", login_token.c_str()); g_host_interface->GetSettingsInterface()->SetStringValue( - "Cheevos", "LoginTimestamp", TinyString::FromFormat("%" PRIu64, Timestamp::Now().AsUnixTimestamp())); + "Cheevos", "LoginTimestamp", TinyString::FromFormat("%" PRIu64, static_cast(std::time(nullptr)))); g_host_interface->GetSettingsInterface()->Save(); } diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp index 67743e55b..73ae20d0f 100644 --- a/src/core/host_interface.cpp +++ b/src/core/host_interface.cpp @@ -11,6 +11,7 @@ #include "cpu_code_cache.h" #include "cpu_core.h" #include "dma.h" +#include "fmt/chrono.h" #include "gpu.h" #include "gte.h" #include "host_display.h" @@ -949,11 +950,7 @@ std::string HostInterface::GetProgramDirectoryRelativePath(const char* format, . TinyString HostInterface::GetTimestampStringForFileName() { - const Timestamp ts(Timestamp::Now()); - - TinyString str; - ts.ToString(str, "%Y-%m-%d_%H-%M-%S"); - return str; + return TinyString::FromFmt("{:%Y-%m-%d_%H-%M-%S}", fmt::localtime(std::time(nullptr))); } std::string HostInterface::GetMemoryCardDirectory() const diff --git a/src/frontend-common/common_host_interface.cpp b/src/frontend-common/common_host_interface.cpp index cc5623040..6ebb77c7d 100644 --- a/src/frontend-common/common_host_interface.cpp +++ b/src/frontend-common/common_host_interface.cpp @@ -3094,7 +3094,8 @@ std::vector CommonHostInterface::GetAvailabl if (!FileSystem::StatFile(path.c_str(), &sd)) return; - si.push_back(SaveStateInfo{std::move(path), sd.ModificationTime.AsUnixTimestamp(), static_cast(slot), global}); + si.push_back(SaveStateInfo{std::move(path), static_cast(sd.ModificationTime.AsUnixTimestamp()), + static_cast(slot), global}); }; if (game_code && std::strlen(game_code) > 0) @@ -3119,7 +3120,7 @@ std::optional CommonHostInterface::GetSaveSt if (!FileSystem::StatFile(path.c_str(), &sd)) return std::nullopt; - return SaveStateInfo{std::move(path), sd.ModificationTime.AsUnixTimestamp(), slot, global}; + return SaveStateInfo{std::move(path), static_cast(sd.ModificationTime.AsUnixTimestamp()), slot, global}; } std::optional diff --git a/src/frontend-common/common_host_interface.h b/src/frontend-common/common_host_interface.h index 574c48226..b538bed1a 100644 --- a/src/frontend-common/common_host_interface.h +++ b/src/frontend-common/common_host_interface.h @@ -4,6 +4,7 @@ #include "core/controller.h" #include "core/host_interface.h" #include +#include #include #include #include @@ -78,7 +79,7 @@ public: struct SaveStateInfo { std::string path; - u64 timestamp; + std::time_t timestamp; s32 slot; bool global; }; @@ -89,7 +90,7 @@ public: std::string title; std::string game_code; std::string media_path; - u64 timestamp; + std::time_t timestamp; s32 slot; bool global; diff --git a/src/frontend-common/fullscreen_ui.cpp b/src/frontend-common/fullscreen_ui.cpp index 603e36454..aab2a315e 100644 --- a/src/frontend-common/fullscreen_ui.cpp +++ b/src/frontend-common/fullscreen_ui.cpp @@ -20,6 +20,8 @@ #include "core/resources.h" #include "core/settings.h" #include "core/system.h" +#include "fmt/chrono.h" +#include "fmt/format.h" #include "fullscreen_ui_progress_callback.h" #include "game_list.h" #include "icon.h" @@ -2391,12 +2393,12 @@ void DrawSettingsWindow() ActiveButton(SmallString::FromFormat(ICON_FA_USER " Username: %s", Cheevos::GetUsername().c_str()), false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); - Timestamp ts; TinyString ts_string; - ts.SetUnixTimestamp(StringUtil::FromChars(s_host_interface->GetSettingsInterface()->GetStringValue( - "Cheevos", "LoginTimestamp", "0")) - .value_or(0)); - ts.ToString(ts_string, "%Y-%m-%d %H:%M:%S"); + ts_string.AppendFmtString( + "{:%Y-%m-%d %H:%M:%S}", + fmt::localtime(StringUtil::FromChars( + s_host_interface->GetSettingsInterface()->GetStringValue("Cheevos", "LoginTimestamp", "0")) + .value_or(0))); ActiveButton(SmallString::FromFormat(ICON_FA_CLOCK " Login token generated on %s", ts_string.GetCharArray()), false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); ImGui::PopStyleColor(); @@ -2767,9 +2769,7 @@ void InitializeSaveStateListEntry(SaveStateListEntry* li, CommonHostInterface::E li->title = StringUtil::StdStringFromFormat("%s Slot %d##game_slot_%d", ssi->title.c_str(), ssi->slot, ssi->slot); } - li->summary = - StringUtil::StdStringFromFormat("%s - Saved %s", ssi->game_code.c_str(), - Timestamp::FromUnixTimestamp(ssi->timestamp).ToString("%c").GetCharArray()); + li->summary = fmt::format("{} - Saved {:%c}", ssi->game_code.c_str(), fmt::localtime(ssi->timestamp)); li->slot = ssi->slot; li->global = ssi->global; diff --git a/src/frontend-common/save_state_selector_ui.cpp b/src/frontend-common/save_state_selector_ui.cpp index 3260fa9b5..214418d56 100644 --- a/src/frontend-common/save_state_selector_ui.cpp +++ b/src/frontend-common/save_state_selector_ui.cpp @@ -4,6 +4,8 @@ #include "common/timestamp.h" #include "core/host_display.h" #include "core/system.h" +#include "fmt/chrono.h" +#include "fmt/format.h" #include "icon.h" #include "imgui.h" Log_SetChannel(SaveStateSelectorUI); @@ -146,7 +148,7 @@ void SaveStateSelectorUI::InitializeListEntry(ListEntry* li, CommonHostInterface li->title = std::move(ssi->title); li->game_code = std::move(ssi->game_code); li->path = std::move(ssi->path); - li->formatted_timestamp = Timestamp::FromUnixTimestamp(ssi->timestamp).ToString("%c"); + li->formatted_timestamp = fmt::format("{:%c}", fmt::localtime(ssi->timestamp)); li->slot = ssi->slot; li->global = ssi->global;