diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index 4221f08562..7e174d03d6 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -396,25 +396,28 @@ void fmt::raw_append(std::string& out, const char* fmt, const fmt_type_info* sup cfmt_append(out, fmt, cfmt_src{sup, args}); } -std::string fmt::replace_first(const std::string& src, const std::string& from, const std::string& to) +std::string fmt::replace_all(std::string_view src, std::string_view from, std::string_view to, usz count) { - auto pos = src.find(from); + std::string target; + target.reserve(src.size() + to.size()); - if (pos == umax) + for (usz i = 0, replaced = 0; i < src.size();) { - return src; - } + const usz pos = src.find(from, i); - return (pos ? src.substr(0, pos) + to : to) + std::string(src.c_str() + pos + from.length()); -} + if (pos == umax || replaced++ >= count) + { + // No match or too many encountered, append the rest of the string as is + target.append(src.substr(i)); + break; + } -std::string fmt::replace_all(const std::string& src, const std::string& from, const std::string& to) -{ - std::string target = src; - for (auto pos = target.find(from); pos != umax; pos = target.find(from, pos + 1)) - { - target = (pos ? target.substr(0, pos) + to : to) + std::string(target.c_str() + pos + from.length()); - pos += to.length(); + // Append source until the matched string position + target.append(src.substr(i, pos - i)); + + // Replace string + target.append(to); + i = pos + from.size(); } return target; diff --git a/Utilities/StrUtil.h b/Utilities/StrUtil.h index e8f4185902..9e622d6ae3 100644 --- a/Utilities/StrUtil.h +++ b/Utilities/StrUtil.h @@ -24,8 +24,7 @@ inline void strcpy_trunc(D& dst, const T& src) namespace fmt { - std::string replace_first(const std::string& src, const std::string& from, const std::string& to); - std::string replace_all(const std::string& src, const std::string& from, const std::string& to); + std::string replace_all(std::string_view src, std::string_view from, std::string_view to, usz count = -1); template std::string replace_all(std::string src, const std::pair (&list)[list_size]) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 2dd5ab992f..e16af25925 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -193,8 +193,8 @@ void Emulator::Init(bool add_only) // Create directories (can be disabled if necessary) const std::string emu_dir = GetEmuDir(); const std::string dev_hdd0 = GetHddDir(); - const std::string dev_hdd1 = fmt::replace_all(g_cfg.vfs.dev_hdd1, "$(EmulatorDir)", emu_dir); - const std::string dev_usb = fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir); + const std::string dev_hdd1 = g_cfg.vfs.get(g_cfg.vfs.dev_hdd1, emu_dir); + const std::string dev_usb = g_cfg.vfs.get(g_cfg.vfs.dev_usb000, emu_dir); const std::string dev_flsh = g_cfg.vfs.get_dev_flash(); auto make_path_verbose = [](const std::string& path) @@ -846,12 +846,12 @@ std::string Emulator::GetEmuDir() std::string Emulator::GetHddDir() { - return fmt::replace_all(g_cfg.vfs.dev_hdd0, "$(EmulatorDir)", GetEmuDir()); + return g_cfg.vfs.get(g_cfg.vfs.dev_hdd0, GetEmuDir()); } std::string Emulator::GetHdd1Dir() { - return fmt::replace_all(g_cfg.vfs.dev_hdd1, "$(EmulatorDir)", GetEmuDir()); + return g_cfg.vfs.get(g_cfg.vfs.dev_hdd1, GetEmuDir()); } std::string Emulator::GetCacheDir() @@ -1158,15 +1158,14 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool // Mount all devices const std::string emu_dir = GetEmuDir(); - const std::string home_dir = g_cfg.vfs.app_home; std::string bdvd_dir = g_cfg.vfs.dev_bdvd; // Mount default relative path to non-existent directory - vfs::mount("/dev_hdd0", fmt::replace_all(g_cfg.vfs.dev_hdd0, "$(EmulatorDir)", emu_dir)); + vfs::mount("/dev_hdd0", g_cfg.vfs.get(g_cfg.vfs.dev_hdd0, emu_dir)); vfs::mount("/dev_flash", g_cfg.vfs.get_dev_flash()); - vfs::mount("/dev_usb", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir)); - vfs::mount("/dev_usb000", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir)); - vfs::mount("/app_home", home_dir.empty() ? elf_dir + '/' : fmt::replace_all(home_dir, "$(EmulatorDir)", emu_dir)); + vfs::mount("/dev_usb", g_cfg.vfs.get(g_cfg.vfs.dev_usb000, emu_dir)); + vfs::mount("/dev_usb000", g_cfg.vfs.get(g_cfg.vfs.dev_usb000, emu_dir)); + vfs::mount("/app_home", g_cfg.vfs.app_home.to_string().empty() ? elf_dir + '/' : g_cfg.vfs.get(g_cfg.vfs.app_home, emu_dir)); if (!hdd1.empty()) { diff --git a/rpcs3/Emu/system_config.cpp b/rpcs3/Emu/system_config.cpp index 2555088c04..bf79ffbf60 100644 --- a/rpcs3/Emu/system_config.cpp +++ b/rpcs3/Emu/system_config.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "system_config.h" #include "Utilities/StrUtil.h" +#include "Utilities/StrFmt.h" #include "util/sysinfo.hpp" @@ -11,16 +12,43 @@ bool cfg_root::node_core::has_rtm() const return utils::has_rtm(); } -std::string cfg_root::node_vfs::get(const cfg::string& _cfg, const char* _def) const +std::string cfg_root::node_vfs::get(const cfg::string& _cfg, std::string_view emu_dir) const { - auto [spath, sshared] = _cfg.get(); + std::string _emu_dir; // Storage only - if (spath.empty()) + if (emu_dir.empty()) { - return fs::get_config_dir() + _def; + // Optimization if provided arg + _emu_dir = emulator_dir; + + if (_emu_dir.empty()) + { + _emu_dir = fs::get_config_dir() + '/'; + } + // Check if path does not end with a delimiter + else if (_emu_dir.back() != fs::delim[0] && _emu_dir.back() != fs::delim[1]) + { + _emu_dir += '/'; + } + + emu_dir = _emu_dir; } - auto [semudir, sshared2] = emulator_dir.get(); + std::string path = _cfg.to_string(); - return fmt::replace_all(spath, "$(EmulatorDir)", semudir.empty() ? fs::get_config_dir() : semudir); + if (path.empty()) + { + // Fallback + path = _cfg.def; + } + + path = fmt::replace_all(path, "$(EmulatorDir)", emu_dir); + + // Check if path does not end with a delimiter + if (path.back() != fs::delim[0] && path.back() != fs::delim[1]) + { + path += '/'; + } + + return path; } diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index ade3a50cb7..cbeb5eaa34 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -80,7 +80,7 @@ struct cfg_root : cfg::node { node_vfs(cfg::node* _this) : cfg::node(_this, "VFS") {} - std::string get(const cfg::string&, const char*) const; + std::string get(const cfg::string&, std::string_view emu_dir = {}) const; cfg::string emulator_dir{ this, "$(EmulatorDir)" }; // Default (empty): taken from fs::get_config_dir() cfg::string dev_hdd0{ this, "/dev_hdd0/", "$(EmulatorDir)dev_hdd0/" }; @@ -92,7 +92,7 @@ struct cfg_root : cfg::node std::string get_dev_flash() const { - return get(dev_flash, "dev_flash/"); + return get(dev_flash); } cfg::_bool host_root{ this, "Enable /host_root/" };