diff --git a/src/openrct2-ui/input/ShortcutManager.cpp b/src/openrct2-ui/input/ShortcutManager.cpp index 193d5585dd..2a3ccbcc81 100644 --- a/src/openrct2-ui/input/ShortcutManager.cpp +++ b/src/openrct2-ui/input/ShortcutManager.cpp @@ -283,7 +283,7 @@ void ShortcutManager::LoadLegacyBindings(const fs::path& path) void ShortcutManager::LoadUserBindings(const fs::path& path) { - auto root = Json::ReadFromFile(path); + auto root = Json::ReadFromFile(path.u8string()); if (root.is_object()) { for (auto it = root.begin(); it != root.end(); ++it) @@ -329,7 +329,7 @@ void ShortcutManager::SaveUserBindings(const fs::path& path) json_t root; if (fs::exists(path)) { - root = Json::ReadFromFile(path); + root = Json::ReadFromFile(path.u8string()); } for (const auto& shortcut : Shortcuts) @@ -349,7 +349,7 @@ void ShortcutManager::SaveUserBindings(const fs::path& path) } } - Json::WriteToFile(path, root); + Json::WriteToFile(path.u8string(), root); } std::string_view ShortcutManager::GetLegacyShortcutId(size_t index) diff --git a/src/openrct2-ui/windows/LoadSave.cpp b/src/openrct2-ui/windows/LoadSave.cpp index d240cf8218..78e6c719da 100644 --- a/src/openrct2-ui/windows/LoadSave.cpp +++ b/src/openrct2-ui/windows/LoadSave.cpp @@ -142,13 +142,13 @@ static int32_t _type; static int32_t maxDateWidth = 0; static int32_t maxTimeWidth = 0; -static void WindowLoadsavePopulateList(rct_window* w, int32_t includeNewItem, const char* directory, const char* extension); -static void WindowLoadsaveSelect(rct_window* w, const char* path); +static void WindowLoadsavePopulateList(rct_window* w, int32_t includeNewItem, const utf8* directory, const char* extension); +static void WindowLoadsaveSelect(rct_window* w, const utf8* path); static void WindowLoadsaveSortList(); static rct_window* WindowOverwritePromptOpen(const char* name, const char* path); -static utf8* GetLastDirectoryByType(int32_t type) +static u8string GetLastDirectoryByType(int32_t type) { switch (type & 0x0E) { @@ -165,7 +165,7 @@ static utf8* GetLastDirectoryByType(int32_t type) return gConfigGeneral.last_save_track_directory; default: - return nullptr; + return u8string(); } } @@ -228,23 +228,17 @@ static const char* GetFilterPatternByType(const int32_t type, const bool isSave) return ""; } -static int32_t WindowLoadsaveGetDir(const int32_t type, char* path, size_t pathSize) +static u8string WindowLoadsaveGetDir(const int32_t type) { - const char* last_save = GetLastDirectoryByType(type); - if (last_save != nullptr && Path::DirectoryExists(last_save)) + u8string result = GetLastDirectoryByType(type); + if (result.empty() || !Path::DirectoryExists(result)) { - safe_strcpy(path, last_save, pathSize); + result = GetInitialDirectoryByType(type); } - else - { - auto result = GetInitialDirectoryByType(type); - path = String::Duplicate(result.c_str()); - pathSize = sizeof(path); - } - return 1; + return result; } -static bool Browse(bool isSave, char* path, size_t pathSize); +static u8string Browse(bool isSave); rct_window* WindowLoadsaveOpen( int32_t type, std::string_view defaultPath, std::function callback, @@ -256,22 +250,21 @@ rct_window* WindowLoadsaveOpen( _defaultPath = defaultPath; bool isSave = (type & 0x01) == LOADSAVETYPE_SAVE; - char path[MAX_PATH]; - bool success = WindowLoadsaveGetDir(type, path, sizeof(path)); - if (!success) - return nullptr; // Bypass the lot? auto hasFilePicker = OpenRCT2::GetContext()->GetUiContext()->HasFilePicker(); if (gConfigGeneral.use_native_browse_dialog && hasFilePicker) { - if (Browse(isSave, path, sizeof(path))) + const u8string path = Browse(isSave); + if (!path.empty()) { - WindowLoadsaveSelect(nullptr, path); + WindowLoadsaveSelect(nullptr, path.c_str()); } return nullptr; } + const u8string path = WindowLoadsaveGetDir(type); + rct_window* w = window_bring_to_front_by_class(WC_LOADSAVE); if (w == nullptr) { @@ -294,7 +287,7 @@ rct_window* WindowLoadsaveOpen( } const char* pattern = GetFilterPatternByType(type, isSave); - WindowLoadsavePopulateList(w, isSave, path, pattern); + WindowLoadsavePopulateList(w, isSave, path.c_str(), pattern); w->no_list_items = static_cast(_listItems.size()); w->selected_list_item = -1; @@ -352,7 +345,7 @@ static void WindowLoadsaveResize(rct_window* w) } } -static bool Browse(bool isSave, char* path, size_t pathSize) +static u8string Browse(bool isSave) { OpenRCT2::Ui::FileDialogDesc desc = {}; u8string extension = ""; @@ -395,13 +388,13 @@ static bool Browse(bool isSave, char* path, size_t pathSize) break; } - safe_strcpy(path, _directory, pathSize); + u8string path = _directory; if (isSave) { // The file browser requires a file path instead of just a directory if (!_defaultPath.empty()) { - safe_strcat_path(path, _defaultPath.c_str(), pathSize); + Path::Combine(path, _defaultPath); } else { @@ -412,7 +405,7 @@ static bool Browse(bool isSave, char* path, size_t pathSize) // Use localised "Unnamed Park" if park name was empty. buffer = format_string(STR_UNNAMED_PARK, nullptr); } - safe_strcat_path(path, buffer.c_str(), pathSize); + Path::Combine(path, buffer); } } @@ -424,23 +417,21 @@ static bool Browse(bool isSave, char* path, size_t pathSize) desc.Filters.emplace_back(language_get_string(STR_ALL_FILES), "*"); desc.Title = language_get_string(title); - if (platform_open_common_file_dialog(path, desc, pathSize)) + + utf8 outPath[MAX_PATH]; + if (platform_open_common_file_dialog(outPath, desc, std::size(outPath))) { // When the given save type was given, Windows still interprets a filename with a dot in its name as a custom extension, // meaning files like "My Coaster v1.2" will not get the .td6 extension by default. if (isSave && get_file_extension_type(path) != fileType) - path_append_extension(path, extension.c_str(), pathSize); - - return true; + path_append_extension(outPath, extension.c_str(), std::size(outPath)); } - return false; + return u8string(outPath); } static void WindowLoadsaveMouseup(rct_window* w, rct_widgetindex widgetIndex) { - char path[MAX_PATH]; - bool isSave = (_type & 0x01) == LOADSAVETYPE_SAVE; switch (widgetIndex) { @@ -449,8 +440,7 @@ static void WindowLoadsaveMouseup(rct_window* w, rct_widgetindex widgetIndex) break; case WIDX_UP: - safe_strcpy(path, _parentDirectory, sizeof(path)); - WindowLoadsavePopulateList(w, isSave, path, _extension); + WindowLoadsavePopulateList(w, isSave, _parentDirectory, _extension); WindowInitScrollWidgets(w); w->no_list_items = static_cast(_listItems.size()); break; @@ -466,19 +456,21 @@ static void WindowLoadsaveMouseup(rct_window* w, rct_widgetindex widgetIndex) break; case WIDX_BROWSE: - if (Browse(isSave, path, sizeof(path))) + { + u8string path = Browse(isSave); + if (!path.empty()) { - WindowLoadsaveSelect(w, path); + WindowLoadsaveSelect(w, path.c_str()); } else { // If user cancels file dialog, refresh list - safe_strcpy(path, _directory, sizeof(path)); - WindowLoadsavePopulateList(w, isSave, path, _extension); + WindowLoadsavePopulateList(w, isSave, _directory, _extension); WindowInitScrollWidgets(w); w->no_list_items = static_cast(_listItems.size()); } - break; + } + break; case WIDX_SORT_NAME: if (gConfigGeneral.load_save_sort == Sort::NameAscending) @@ -509,9 +501,7 @@ static void WindowLoadsaveMouseup(rct_window* w, rct_widgetindex widgetIndex) break; case WIDX_DEFAULT: - auto result = GetInitialDirectoryByType(_type); - safe_strcpy(path, result.c_str(), sizeof(path)); - WindowLoadsavePopulateList(w, isSave, path, _extension); + WindowLoadsavePopulateList(w, isSave, GetInitialDirectoryByType(_type).c_str(), _extension); WindowInitScrollWidgets(w); w->no_list_items = static_cast(_listItems.size()); break; @@ -826,7 +816,7 @@ static void WindowLoadsaveSortList() std::sort(_listItems.begin(), _listItems.end(), ListItemSort); } -static void WindowLoadsavePopulateList(rct_window* w, int32_t includeNewItem, const char* directory, const char* extension) +static void WindowLoadsavePopulateList(rct_window* w, int32_t includeNewItem, const utf8* directory, const char* extension) { const auto absoluteDirectory = Path::GetAbsolute(directory); safe_strcpy(_directory, absoluteDirectory.c_str(), std::size(_directory)); diff --git a/src/openrct2/core/Json.cpp b/src/openrct2/core/Json.cpp index 39572fddbf..2c2ade5156 100644 --- a/src/openrct2/core/Json.cpp +++ b/src/openrct2/core/Json.cpp @@ -15,7 +15,7 @@ namespace Json { - json_t ReadFromFile(const utf8* path, size_t maxSize) + json_t ReadFromFile(u8string_view path, size_t maxSize) { auto fs = OpenRCT2::FileStream(path, OpenRCT2::FILE_MODE_OPEN); @@ -36,19 +36,14 @@ namespace Json } catch (const json_t::exception& e) { - throw JsonException(String::Format("Unable to parse JSON file (%s)\n\t%s", path, e.what())); + throw JsonException(String::StdFormat( + "Unable to parse JSON file (%.*s)\n\t%s", static_cast(path.length()), path.data(), e.what())); } return json; } - json_t ReadFromFile(const fs::path& path, size_t maxSize) - { - auto path8 = path.u8string(); - return ReadFromFile(path8.c_str(), maxSize); - } - - void WriteToFile(const utf8* path, const json_t& jsonData, int indentSize) + void WriteToFile(u8string_view path, const json_t& jsonData, int indentSize) { // Serialise JSON std::string jsonOutput = jsonData.dump(indentSize); @@ -58,12 +53,6 @@ namespace Json fs.Write(jsonOutput.data(), jsonOutput.size()); } - void WriteToFile(const fs::path& path, const json_t& jsonData, int indentSize) - { - auto path8 = path.u8string(); - WriteToFile(path8.c_str(), jsonData, indentSize); - } - json_t FromString(std::string_view raw) { json_t json; @@ -74,7 +63,7 @@ namespace Json } catch (const json_t::exception& e) { - log_error("Unable to parse JSON string (%s)\n\t%s", raw, e.what()); + log_error("Unable to parse JSON string (%.*s)\n\t%s", static_cast(raw.length()), raw.data(), e.what()); } return json; @@ -90,7 +79,7 @@ namespace Json } catch (const json_t::exception& e) { - log_error("Unable to parse JSON vector (%s)\n\t%s", vec.data(), e.what()); + log_error("Unable to parse JSON vector (%.*s)\n\t%s", static_cast(vec.size()), vec.data(), e.what()); } return json; diff --git a/src/openrct2/core/Json.hpp b/src/openrct2/core/Json.hpp index c34d5d64d4..7cab65fc42 100644 --- a/src/openrct2/core/Json.hpp +++ b/src/openrct2/core/Json.hpp @@ -11,7 +11,6 @@ #include "../common.h" #include "../core/String.hpp" -#include "FileSystem.hpp" #include #include @@ -35,8 +34,7 @@ namespace Json * @return A JSON representation of the file * @note This function will throw an exception if the JSON file cannot be parsed */ - json_t ReadFromFile(const utf8* path, size_t maxSize = MAX_JSON_SIZE); - json_t ReadFromFile(const fs::path& path, size_t maxSize = MAX_JSON_SIZE); + json_t ReadFromFile(u8string_view path, size_t maxSize = MAX_JSON_SIZE); /** * Read JSON file and parse the contents @@ -44,8 +42,7 @@ namespace Json * @param jsonData A JSON object * @param indentSize The number of spaces in an indent, or removes whitespace on -1 */ - void WriteToFile(const utf8* path, const json_t& jsonData, int indentSize = 4); - void WriteToFile(const fs::path& path, const json_t& jsonData, int indentSize = 4); + void WriteToFile(u8string_view path, const json_t& jsonData, int indentSize = 4); /** * Parse JSON from a string