From d660aba20fae070a51e01936aa32044d31a96df7 Mon Sep 17 00:00:00 2001 From: David Korth Date: Tue, 24 Sep 2019 00:19:22 -0400 Subject: [PATCH 01/10] VolumeVerifier.cpp: Use arrays of string_view objects instead of strings. string_view is a thin wrapper around C strings, so it's more efficient for constant strings than C++ strings. The unordered_set<> also adds extra runtime overhead. For small arrays, a simple linear search works. For larger arrays, std::binary_search() works better than linear but without the unordered_set<> overhead. ShouldBeDualLayer(): Removed a duplicate "SK8X52" entry. --- Source/Core/DiscIO/VolumeVerifier.cpp | 29 +++++++++++++++++---------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/Source/Core/DiscIO/VolumeVerifier.cpp b/Source/Core/DiscIO/VolumeVerifier.cpp index 905a1cc26d..0634e34b66 100644 --- a/Source/Core/DiscIO/VolumeVerifier.cpp +++ b/Source/Core/DiscIO/VolumeVerifier.cpp @@ -678,38 +678,45 @@ bool VolumeVerifier::IsDebugSigned() const bool VolumeVerifier::ShouldHaveChannelPartition() const { - const std::unordered_set channel_discs{ + static constexpr std::array channel_discs = { "RFNE01", "RFNJ01", "RFNK01", "RFNP01", "RFNW01", "RFPE01", "RFPJ01", "RFPK01", "RFPP01", "RFPW01", "RGWE41", "RGWJ41", "RGWP41", "RGWX41", "RMCE01", "RMCJ01", "RMCK01", "RMCP01", }; - return channel_discs.find(m_volume.GetGameID()) != channel_discs.end(); + return std::binary_search(channel_discs.cbegin(), channel_discs.cend(), + std::string_view(m_volume.GetGameID())); } bool VolumeVerifier::ShouldHaveInstallPartition() const { - const std::unordered_set dragon_quest_x{"S4MJGD", "S4SJGD", "S6TJGD", "SDQJGD"}; - return dragon_quest_x.find(m_volume.GetGameID()) != dragon_quest_x.end(); + static constexpr std::array dragon_quest_x = {"S4MJGD", "S4SJGD", "S6TJGD", + "SDQJGD"}; + const std::string& game_id = m_volume.GetGameID(); + return std::any_of(dragon_quest_x.cbegin(), dragon_quest_x.cend(), + [&game_id](std::string_view x) { return x == game_id; }); } bool VolumeVerifier::ShouldHaveMasterpiecePartitions() const { - const std::unordered_set ssbb{"RSBE01", "RSBJ01", "RSBK01", "RSBP01"}; - return ssbb.find(m_volume.GetGameID()) != ssbb.end(); + static constexpr std::array ssbb = {"RSBE01", "RSBJ01", "RSBK01", "RSBP01"}; + const std::string& game_id = m_volume.GetGameID(); + return std::any_of(ssbb.cbegin(), ssbb.cend(), + [&game_id](std::string_view x) { return x == game_id; }); } bool VolumeVerifier::ShouldBeDualLayer() const { // The Japanese versions of Xenoblade and The Last Story are single-layer // (unlike the other versions) and must not be added to this list. - const std::unordered_set dual_layer_discs{ + static constexpr std::array dual_layer_discs = { "R3ME01", "R3MP01", "R3OE01", "R3OJ01", "R3OP01", "RSBE01", "RSBJ01", "RSBK01", "RSBP01", - "RXMJ8P", "S59E01", "S59JC8", "S59P01", "S5QJC8", "SK8X52", "SAKENS", "SAKPNS", "SK8V52", - "SK8X52", "SLSEXJ", "SLSP01", "SQIE4Q", "SQIP4Q", "SQIY4Q", "SR5E41", "SR5P41", "SUOE41", - "SUOP41", "SVXX52", "SVXY52", "SX4E01", "SX4P01", "SZ3EGT", "SZ3PGT", + "RXMJ8P", "S59E01", "S59JC8", "S59P01", "S5QJC8", "SAKENS", "SAKPNS", "SK8V52", "SK8X52", + "SLSEXJ", "SLSP01", "SQIE4Q", "SQIP4Q", "SQIY4Q", "SR5E41", "SR5P41", "SUOE41", "SUOP41", + "SVXX52", "SVXY52", "SX4E01", "SX4P01", "SZ3EGT", "SZ3PGT", }; - return dual_layer_discs.find(m_volume.GetGameID()) != dual_layer_discs.end(); + return std::binary_search(dual_layer_discs.cbegin(), dual_layer_discs.cend(), + std::string_view(m_volume.GetGameID())); } void VolumeVerifier::CheckDiscSize() From afe2e7de0f83552c1c2235bfcdb993cd6be23c2b Mon Sep 17 00:00:00 2001 From: David Korth Date: Tue, 24 Sep 2019 00:24:56 -0400 Subject: [PATCH 02/10] VolumeVerifier.cpp: Verify that the string arrays are sorted before using std::binary_sort(). Debug builds only, since this is wrapped in assert(). --- Source/Core/DiscIO/VolumeVerifier.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Core/DiscIO/VolumeVerifier.cpp b/Source/Core/DiscIO/VolumeVerifier.cpp index 0634e34b66..15d53f62a1 100644 --- a/Source/Core/DiscIO/VolumeVerifier.cpp +++ b/Source/Core/DiscIO/VolumeVerifier.cpp @@ -5,6 +5,7 @@ #include "DiscIO/VolumeVerifier.h" #include +#include #include #include #include @@ -682,6 +683,7 @@ bool VolumeVerifier::ShouldHaveChannelPartition() const "RFNE01", "RFNJ01", "RFNK01", "RFNP01", "RFNW01", "RFPE01", "RFPJ01", "RFPK01", "RFPP01", "RFPW01", "RGWE41", "RGWJ41", "RGWP41", "RGWX41", "RMCE01", "RMCJ01", "RMCK01", "RMCP01", }; + assert(std::is_sorted(channel_discs.cbegin(), channel_discs.cend())); return std::binary_search(channel_discs.cbegin(), channel_discs.cend(), std::string_view(m_volume.GetGameID())); @@ -714,6 +716,7 @@ bool VolumeVerifier::ShouldBeDualLayer() const "SLSEXJ", "SLSP01", "SQIE4Q", "SQIP4Q", "SQIY4Q", "SR5E41", "SR5P41", "SUOE41", "SUOP41", "SVXX52", "SVXY52", "SX4E01", "SX4P01", "SZ3EGT", "SZ3PGT", }; + assert(std::is_sorted(dual_layer_discs.cbegin(), dual_layer_discs.cend())); return std::binary_search(dual_layer_discs.cbegin(), dual_layer_discs.cend(), std::string_view(m_volume.GetGameID())); From 9f3b9acad9fc5a86068cba80b562a721aa6b0fc8 Mon Sep 17 00:00:00 2001 From: David Korth Date: Wed, 11 Sep 2019 23:32:26 -0400 Subject: [PATCH 03/10] PowerPC.cpp: No need to explicitly initialize ppcState. "ppcState{}" is stored in the .data segment, which means the full ~4 MB is stored in the executable. "ppcState" is stored in the .bss segment, which means it only stores a note that tells it to allocate and zero ~4 MB at runtime. --- Source/Core/Core/PowerPC/PowerPC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index 3dd7894915..ebac1a07d9 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -32,7 +32,7 @@ namespace PowerPC { // STATE_TO_SAVE -PowerPCState ppcState{}; +PowerPCState ppcState; static CPUCoreBase* s_cpu_core_base = nullptr; static bool s_cpu_core_base_is_injected = false; From 1d7f128693688efa65c5f24bafacea3bb4439941 Mon Sep 17 00:00:00 2001 From: David Korth Date: Wed, 11 Sep 2019 23:44:57 -0400 Subject: [PATCH 04/10] GetSysMenuVersionString(): Use a char instead of std::string for the region letter. Append the region letter after determining the version number. --- Source/Core/DiscIO/Enums.cpp | 58 ++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/Source/Core/DiscIO/Enums.cpp b/Source/Core/DiscIO/Enums.cpp index 349d4bc194..a97b6fc34f 100644 --- a/Source/Core/DiscIO/Enums.cpp +++ b/Source/Core/DiscIO/Enums.cpp @@ -348,21 +348,22 @@ Region GetSysMenuRegion(u16 title_version) std::string GetSysMenuVersionString(u16 title_version) { - std::string region_letter; + std::string version; + char region_letter = '\0'; switch (GetSysMenuRegion(title_version)) { case Region::NTSC_J: - region_letter = "J"; + region_letter = 'J'; break; case Region::NTSC_U: - region_letter = "U"; + region_letter = 'U'; break; case Region::PAL: - region_letter = "E"; + region_letter = 'E'; break; case Region::NTSC_K: - region_letter = "K"; + region_letter = 'K'; break; case Region::Unknown: WARN_LOG(DISCIO, "Unknown region for Wii Menu version %u", title_version); @@ -372,36 +373,55 @@ std::string GetSysMenuVersionString(u16 title_version) switch (title_version & 0xff0) { case 32: - return "1.0" + region_letter; + version = "1.0"; + break; case 96: case 128: - return "2.0" + region_letter; + version = "2.0"; + break; case 160: - return "2.1" + region_letter; + version = "2.1"; + break; case 192: - return "2.2" + region_letter; + version = "2.2"; + break; case 224: - return "3.0" + region_letter; + version = "3.0"; + break; case 256: - return "3.1" + region_letter; + version = "3.1"; + break; case 288: - return "3.2" + region_letter; + version = "3.2"; + break; case 320: case 352: - return "3.3" + region_letter; + version = "3.3"; + break; case 384: - return (region_letter != "K" ? "3.4" : "3.5") + region_letter; + version = (region_letter != 'K' ? "3.4" : "3.5"); + break; case 416: - return "4.0" + region_letter; + version = "4.0"; + break; case 448: - return "4.1" + region_letter; + version = "4.1"; + break; case 480: - return "4.2" + region_letter; + version = "4.2"; + break; case 512: - return "4.3" + region_letter; + version = "4.3"; + break; default: - return "?.?" + region_letter; + version = "?.?"; + break; } + + if (region_letter != '\0') + version += region_letter; + + return version; } const std::string& GetCompanyFromID(const std::string& company_id) From 05101b251c3a6b63f7250671259d842f5f362475 Mon Sep 17 00:00:00 2001 From: David Korth Date: Tue, 24 Sep 2019 00:30:20 -0400 Subject: [PATCH 05/10] OGL/Render.cpp, InitDriverInfo(): Use std::string_view to eliminate string copies. Consolidate the NVIDIA Tegra and non-Tegra checks into one branch. --- Source/Core/VideoBackends/OGL/Render.cpp | 29 +++++++++++++----------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 14bc05757a..27a8c05287 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -144,28 +144,35 @@ static void APIENTRY ClearDepthf(GLfloat depthval) static void InitDriverInfo() { - std::string svendor = std::string(g_ogl_config.gl_vendor); - std::string srenderer = std::string(g_ogl_config.gl_renderer); - std::string sversion = std::string(g_ogl_config.gl_version); + const std::string_view svendor(g_ogl_config.gl_vendor); + const std::string_view srenderer(g_ogl_config.gl_renderer); + const std::string_view sversion(g_ogl_config.gl_version); DriverDetails::Vendor vendor = DriverDetails::VENDOR_UNKNOWN; DriverDetails::Driver driver = DriverDetails::DRIVER_UNKNOWN; DriverDetails::Family family = DriverDetails::Family::UNKNOWN; double version = 0.0; // Get the vendor first - if (svendor == "NVIDIA Corporation" && srenderer != "NVIDIA Tegra") + if (svendor == "NVIDIA Corporation") { - vendor = DriverDetails::VENDOR_NVIDIA; + if (srenderer != "NVIDIA Tegra") + { + vendor = DriverDetails::VENDOR_NVIDIA; + } + else + { + vendor = DriverDetails::VENDOR_TEGRA; + } } else if (svendor == "ATI Technologies Inc." || svendor == "Advanced Micro Devices, Inc.") { vendor = DriverDetails::VENDOR_ATI; } - else if (std::string::npos != sversion.find("Mesa")) + else if (sversion.find("Mesa") != std::string::npos) { vendor = DriverDetails::VENDOR_MESA; } - else if (std::string::npos != svendor.find("Intel")) + else if (svendor.find("Intel") != std::string::npos) { vendor = DriverDetails::VENDOR_INTEL; } @@ -186,10 +193,6 @@ static void InitDriverInfo() { vendor = DriverDetails::VENDOR_IMGTEC; } - else if (svendor == "NVIDIA Corporation" && srenderer == "NVIDIA Tegra") - { - vendor = DriverDetails::VENDOR_TEGRA; - } else if (svendor == "Vivante Corporation") { vendor = DriverDetails::VENDOR_VIVANTE; @@ -238,8 +241,8 @@ static void InitDriverInfo() else if (srenderer.find("Ivybridge") != std::string::npos) family = DriverDetails::Family::INTEL_IVY; } - else if (std::string::npos != srenderer.find("AMD") || - std::string::npos != srenderer.find("ATI")) + else if (srenderer.find("AMD") != std::string::npos || + srenderer.find("ATI") != std::string::npos) { driver = DriverDetails::DRIVER_R600; } From a23b3d26f407ee9647e49f2802c5da5d26e752ad Mon Sep 17 00:00:00 2001 From: David Korth Date: Thu, 12 Sep 2019 00:21:29 -0400 Subject: [PATCH 06/10] GLExtensions.cpp: Use arrays of `const char *const` instead of `std::string`. The strings end up being copied, so we might as well initialize the std::string in the unordered_map directly. --- .../Common/GL/GLExtensions/GLExtensions.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp b/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp index 641559a29a..37cea21ebd 100644 --- a/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp +++ b/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp @@ -2198,7 +2198,7 @@ static void InitExtensionList(GLContext* context) default: case 450: { - std::string gl450exts[] = { + static const char* const gl450exts[] = { "GL_ARB_ES3_1_compatibility", "GL_ARB_clip_control", "GL_ARB_conditional_render_inverted", @@ -2216,7 +2216,7 @@ static void InitExtensionList(GLContext* context) } case 440: { - std::string gl440exts[] = { + static const char* const gl440exts[] = { "GL_ARB_buffer_storage", "GL_ARB_clear_texture", "GL_ARB_enhanced_layouts", @@ -2232,7 +2232,7 @@ static void InitExtensionList(GLContext* context) } case 430: { - std::string gl430exts[] = { + static const char* const gl430exts[] = { "GL_ARB_ES3_compatibility", "GL_ARB_arrays_of_arrays", "GL_ARB_clear_buffer_object", @@ -2260,7 +2260,7 @@ static void InitExtensionList(GLContext* context) } case 420: { - std::string gl420exts[] = { + static const char* const gl420exts[] = { "GL_ARB_base_instance", "GL_ARB_compressed_texture_pixel_storage", "GL_ARB_conservative_depth", @@ -2280,7 +2280,7 @@ static void InitExtensionList(GLContext* context) } case 410: { - std::string gl410exts[] = { + static const char* const gl410exts[] = { "GL_ARB_ES2_compatibility", "GL_ARB_get_program_binary", "GL_ARB_separate_shader_objects", @@ -2294,7 +2294,7 @@ static void InitExtensionList(GLContext* context) } case 400: { - std::string gl400exts[] = { + static const char* const gl400exts[] = { "GL_ARB_draw_indirect", "GL_ARB_gpu_shader5", "GL_ARB_gpu_shader_fp64", @@ -2314,7 +2314,7 @@ static void InitExtensionList(GLContext* context) } case 330: { - std::string gl330exts[] = { + static const char* const gl330exts[] = { "GL_ARB_shader_bit_encoding", "GL_ARB_blend_func_extended", "GL_ARB_explicit_attrib_location", @@ -2332,7 +2332,7 @@ static void InitExtensionList(GLContext* context) } case 320: { - std::string gl320exts[] = { + static const char* const gl320exts[] = { "GL_ARB_geometry_shader4", "GL_ARB_sync", "GL_ARB_vertex_array_bgra", @@ -2350,7 +2350,7 @@ static void InitExtensionList(GLContext* context) case 310: { // Can't add NV_primitive_restart since function name changed - std::string gl310exts[] = { + static const char* const gl310exts[] = { "GL_ARB_draw_instanced", "GL_ARB_copy_buffer", "GL_ARB_texture_buffer_object", @@ -2366,7 +2366,7 @@ static void InitExtensionList(GLContext* context) { // Quite a lot of these had their names changed when merged in to core // Disable the ones that have - std::string gl300exts[] = { + static const char* const gl300exts[] = { "GL_ARB_map_buffer_range", "GL_ARB_color_buffer_float", "GL_ARB_texture_float", From 6e549bb6689d967edf4e16f061500f696f35906c Mon Sep 17 00:00:00 2001 From: David Korth Date: Tue, 24 Sep 2019 00:32:43 -0400 Subject: [PATCH 07/10] InputConfig::LoadConfig(): Convert num[] to an array of std::string_view. NOTE: The explicit std::string() conversions later are needed. Otherwise, gcc-9.2.0 throws all sorts of errors because it can't find a matching operator+() function. --- Source/Core/InputCommon/InputConfig.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/InputCommon/InputConfig.cpp b/Source/Core/InputCommon/InputConfig.cpp index a1826f46d1..24330575e1 100644 --- a/Source/Core/InputCommon/InputConfig.cpp +++ b/Source/Core/InputCommon/InputConfig.cpp @@ -30,7 +30,7 @@ bool InputConfig::LoadConfig(bool isGC) { IniFile inifile; bool useProfile[MAX_BBMOTES] = {false, false, false, false, false}; - std::string num[MAX_BBMOTES] = {"1", "2", "3", "4", "BB"}; + static constexpr std::array num = {"1", "2", "3", "4", "BB"}; std::string profile[MAX_BBMOTES]; std::string path; @@ -58,10 +58,10 @@ bool InputConfig::LoadConfig(bool isGC) for (int i = 0; i < 4; i++) { - if (control_section->Exists(type + "Profile" + num[i])) + if (control_section->Exists(type + "Profile" + std::string(num[i]))) { std::string profile_setting; - if (control_section->Get(type + "Profile" + num[i], &profile_setting)) + if (control_section->Get(type + "Profile" + std::string(num[i]), &profile_setting)) { auto profiles = InputProfile::GetProfilesFromSetting( profile_setting, File::GetUserPath(D_CONFIG_IDX) + path); From c2dd2e8a2e202b3cb63023306569d4f26e293adb Mon Sep 17 00:00:00 2001 From: David Korth Date: Sat, 14 Sep 2019 16:40:34 -0400 Subject: [PATCH 08/10] Use std::istringstream or std::ostringstream instead of std::stringstream where possible. This removes std::iostream from the inheritance chain, which reduces overhead slightly. --- Source/Core/AudioCommon/WaveFile.cpp | 2 +- Source/Core/Common/Debug/Watches.cpp | 2 +- Source/Core/Common/StringUtil.cpp | 2 +- Source/Core/Core/HW/SI/SI.cpp | 2 +- Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp | 2 +- Source/Core/Core/IOS/USB/OH0/OH0Device.cpp | 2 +- Source/Core/Core/MemoryWatcher.cpp | 4 ++-- Source/Core/Core/Movie.cpp | 2 +- Source/Core/Core/PowerPC/BreakPoints.cpp | 4 ++-- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 2 +- Source/Core/UICommon/UICommon.cpp | 2 +- Source/Core/VideoCommon/PostProcessing.cpp | 6 +++--- Source/Core/VideoCommon/TextureConversionShader.cpp | 4 ++-- Source/Core/VideoCommon/VertexManagerBase.cpp | 4 ++-- 14 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Source/Core/AudioCommon/WaveFile.cpp b/Source/Core/AudioCommon/WaveFile.cpp index 42ca8cd3b3..70cdc5aee9 100644 --- a/Source/Core/AudioCommon/WaveFile.cpp +++ b/Source/Core/AudioCommon/WaveFile.cpp @@ -147,7 +147,7 @@ void WaveFileWriter::AddStereoSamplesBE(const short* sample_data, u32 count, int { Stop(); file_index++; - std::stringstream filename; + std::ostringstream filename; filename << File::GetUserPath(D_DUMPAUDIO_IDX) << basename << file_index << ".wav"; Start(filename.str(), sample_rate); current_sample_rate = sample_rate; diff --git a/Source/Core/Common/Debug/Watches.cpp b/Source/Core/Common/Debug/Watches.cpp index 9114f2e83d..a17551f77c 100644 --- a/Source/Core/Common/Debug/Watches.cpp +++ b/Source/Core/Common/Debug/Watches.cpp @@ -104,7 +104,7 @@ std::vector Watches::SaveToStrings() const std::vector watches; for (const auto& watch : m_watches) { - std::stringstream ss; + std::ostringstream ss; ss << std::hex << watch.address << " " << watch.name; watches.push_back(ss.str()); } diff --git a/Source/Core/Common/StringUtil.cpp b/Source/Core/Common/StringUtil.cpp index 7955c81fdf..3eeb6d04fe 100644 --- a/Source/Core/Common/StringUtil.cpp +++ b/Source/Core/Common/StringUtil.cpp @@ -398,7 +398,7 @@ std::string JoinStrings(const std::vector& strings, const std::stri if (strings.empty()) return ""; - std::stringstream res; + std::ostringstream res; std::copy(strings.begin(), strings.end(), std::ostream_iterator(res, delimiter.c_str())); diff --git a/Source/Core/Core/HW/SI/SI.cpp b/Source/Core/Core/HW/SI/SI.cpp index af72b2c545..89b1724bb9 100644 --- a/Source/Core/Core/HW/SI/SI.cpp +++ b/Source/Core/Core/HW/SI/SI.cpp @@ -307,7 +307,7 @@ static void RunSIBuffer(u64 user_data, s64 cycles_late) s_com_csr.CHANNEL, request_length, expected_response_length, actual_response_length); if (expected_response_length != actual_response_length) { - std::stringstream ss; + std::ostringstream ss; for (u8 b : request_copy) { ss << std::hex << std::setw(2) << std::setfill('0') << (int)b << ' '; diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp index 0f7fa8c5a8..2247ba000e 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp @@ -512,7 +512,7 @@ void BluetoothReal::LoadLinkKeys() for (size_t i = 0; i < key_string.length(); i = i + 2) { int value; - std::stringstream(key_string.substr(i, 2)) >> std::hex >> value; + std::istringstream(key_string.substr(i, 2)) >> std::hex >> value; key[pos++] = value; } diff --git a/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp b/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp index 86dccb041f..79504f3d98 100644 --- a/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp +++ b/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp @@ -18,7 +18,7 @@ namespace IOS::HLE::Device { static void GetVidPidFromDevicePath(const std::string& device_path, u16& vid, u16& pid) { - std::stringstream stream{device_path}; + std::istringstream stream{device_path}; std::string segment; std::vector list; while (std::getline(stream, segment, '/')) diff --git a/Source/Core/Core/MemoryWatcher.cpp b/Source/Core/Core/MemoryWatcher.cpp index 3e6e61c227..656ea6b0e3 100644 --- a/Source/Core/Core/MemoryWatcher.cpp +++ b/Source/Core/Core/MemoryWatcher.cpp @@ -50,7 +50,7 @@ void MemoryWatcher::ParseLine(const std::string& line) m_values[line] = 0; m_addresses[line] = std::vector(); - std::stringstream offsets(line); + std::istringstream offsets(line); offsets >> std::hex; u32 offset; while (offsets >> offset) @@ -76,7 +76,7 @@ u32 MemoryWatcher::ChasePointer(const std::string& line) std::string MemoryWatcher::ComposeMessages() { - std::stringstream message_stream; + std::ostringstream message_stream; message_stream << std::hex; for (auto& entry : m_values) diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index 3096d963d7..4563ca9dfd 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -185,7 +185,7 @@ std::string GetRTCDisplay() const time_t current_time = CEXIIPL::GetEmulatedTime(CEXIIPL::UNIX_EPOCH); const tm* const gm_time = gmtime(¤t_time); - std::stringstream format_time; + std::ostringstream format_time; format_time << std::put_time(gm_time, "Date/Time: %c\n"); return format_time.str(); } diff --git a/Source/Core/Core/PowerPC/BreakPoints.cpp b/Source/Core/Core/PowerPC/BreakPoints.cpp index 6366762fcd..a8dc9c5a6e 100644 --- a/Source/Core/Core/PowerPC/BreakPoints.cpp +++ b/Source/Core/Core/PowerPC/BreakPoints.cpp @@ -37,7 +37,7 @@ BreakPoints::TBreakPointsStr BreakPoints::GetStrings() const { if (!bp.is_temporary) { - std::stringstream ss; + std::ostringstream ss; ss << std::hex << bp.address << " " << (bp.is_enabled ? "n" : ""); bp_strings.push_back(ss.str()); } @@ -130,7 +130,7 @@ MemChecks::TMemChecksStr MemChecks::GetStrings() const TMemChecksStr mc_strings; for (const TMemCheck& mc : m_mem_checks) { - std::stringstream ss; + std::ostringstream ss; ss << std::hex << mc.start_address; ss << " " << (mc.is_ranged ? mc.end_address : mc.start_address) << " " << (mc.is_ranged ? "n" : "") << (mc.is_break_on_read ? "r" : "") diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index db5c2711a9..c1330446f4 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -1193,7 +1193,7 @@ void LogGeneratedX86(size_t size, const PPCAnalyst::CodeBuffer& code_buffer, con if (b->codeSize <= 250) { - std::stringstream ss; + std::ostringstream ss; ss << std::hex; for (u8 i = 0; i <= b->codeSize; i++) { diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp index fc2a25bc0f..5b4c1b487c 100644 --- a/Source/Core/UICommon/UICommon.cpp +++ b/Source/Core/UICommon/UICommon.cpp @@ -464,7 +464,7 @@ std::string FormatSize(u64 bytes) // Don't need exact values, only 5 most significant digits const double unit_size = std::pow(2, unit * 10); - std::stringstream ss; + std::ostringstream ss; ss << std::fixed << std::setprecision(2); ss << bytes / unit_size << ' ' << Common::GetStringT(unit_symbols[unit]); return ss.str(); diff --git a/Source/Core/VideoCommon/PostProcessing.cpp b/Source/Core/VideoCommon/PostProcessing.cpp index 4d7b033f4e..03f913eaaa 100644 --- a/Source/Core/VideoCommon/PostProcessing.cpp +++ b/Source/Core/VideoCommon/PostProcessing.cpp @@ -434,7 +434,7 @@ void PostProcessing::BlitFromTexture(const MathUtil::Rectangle& dst, std::string PostProcessing::GetUniformBufferHeader() const { - std::stringstream ss; + std::ostringstream ss; u32 unused_counter = 1; if (g_ActiveConfig.backend_info.api_type == APIType::D3D) ss << "cbuffer PSBlock : register(b0) {\n"; @@ -493,7 +493,7 @@ std::string PostProcessing::GetUniformBufferHeader() const std::string PostProcessing::GetHeader() const { - std::stringstream ss; + std::ostringstream ss; ss << GetUniformBufferHeader(); if (g_ActiveConfig.backend_info.api_type == APIType::D3D) { @@ -602,7 +602,7 @@ void main(in float3 v_tex0_ : TEXCOORD0, out float4 ocol0_ : SV_Target) bool PostProcessing::CompileVertexShader() { - std::stringstream ss; + std::ostringstream ss; ss << GetUniformBufferHeader(); if (g_ActiveConfig.backend_info.api_type == APIType::D3D) diff --git a/Source/Core/VideoCommon/TextureConversionShader.cpp b/Source/Core/VideoCommon/TextureConversionShader.cpp index 9348413fd1..5862d45ac7 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.cpp +++ b/Source/Core/VideoCommon/TextureConversionShader.cpp @@ -1392,7 +1392,7 @@ std::string GenerateDecodingShader(TextureFormat format, TLUTFormat palette_form if (!info) return ""; - std::stringstream ss; + std::ostringstream ss; switch (palette_format) { case TLUTFormat::IA8: @@ -1414,7 +1414,7 @@ std::string GenerateDecodingShader(TextureFormat format, TLUTFormat palette_form std::string GeneratePaletteConversionShader(TLUTFormat palette_format, APIType api_type) { - std::stringstream ss; + std::ostringstream ss; ss << R"( int Convert3To8(int v) diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp index 5addf803d5..7fcd4935c0 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/VertexManagerBase.cpp @@ -768,12 +768,12 @@ void VertexManagerBase::OnEndFrame() #if 0 { - std::stringstream ss; + std::ostringstream ss; std::for_each(m_cpu_accesses_this_frame.begin(), m_cpu_accesses_this_frame.end(), [&ss](u32 idx) { ss << idx << ","; }); WARN_LOG(VIDEO, "CPU EFB accesses in last frame: %s", ss.str().c_str()); } { - std::stringstream ss; + std::ostringstream ss; std::for_each(m_scheduled_command_buffer_kicks.begin(), m_scheduled_command_buffer_kicks.end(), [&ss](u32 idx) { ss << idx << ","; }); WARN_LOG(VIDEO, "Scheduled command buffer kicks: %s", ss.str().c_str()); } From f5fe69284200553e1890e55d82c53a60e9ed2ae3 Mon Sep 17 00:00:00 2001 From: David Korth Date: Sat, 14 Sep 2019 16:48:48 -0400 Subject: [PATCH 09/10] Use pre-increment for iterators instead of post-increment. Pre-increment is more efficient, since it doesn't have to return the old iterator. --- Source/Core/UICommon/ResourcePack/Manager.cpp | 4 ++-- Source/Core/VideoBackends/D3D12/StreamBuffer.cpp | 2 +- Source/Core/VideoBackends/Vulkan/StreamBuffer.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Core/UICommon/ResourcePack/Manager.cpp b/Source/Core/UICommon/ResourcePack/Manager.cpp index 1be409f6e6..d2e7c8fc25 100644 --- a/Source/Core/UICommon/ResourcePack/Manager.cpp +++ b/Source/Core/UICommon/ResourcePack/Manager.cpp @@ -76,7 +76,7 @@ std::vector& GetPacks() std::vector GetLowerPriorityPacks(ResourcePack& pack) { std::vector list; - for (auto it = std::find(packs.begin(), packs.end(), pack) + 1; it != packs.end(); it++) + for (auto it = std::find(packs.begin(), packs.end(), pack) + 1; it != packs.end(); ++it) { auto& entry = *it; if (!IsInstalled(pack)) @@ -93,7 +93,7 @@ std::vector GetHigherPriorityPacks(ResourcePack& pack) std::vector list; auto end = std::find(packs.begin(), packs.end(), pack); - for (auto it = packs.begin(); it != end; it++) + for (auto it = packs.begin(); it != end; ++it) { auto& entry = *it; if (!IsInstalled(entry)) diff --git a/Source/Core/VideoBackends/D3D12/StreamBuffer.cpp b/Source/Core/VideoBackends/D3D12/StreamBuffer.cpp index a3702a7256..d8f0699f77 100644 --- a/Source/Core/VideoBackends/D3D12/StreamBuffer.cpp +++ b/Source/Core/VideoBackends/D3D12/StreamBuffer.cpp @@ -178,7 +178,7 @@ bool StreamBuffer::WaitForClearSpace(u32 num_bytes) u32 new_gpu_position = 0; auto iter = m_tracked_fences.begin(); - for (; iter != m_tracked_fences.end(); iter++) + for (; iter != m_tracked_fences.end(); ++iter) { // Would this fence bring us in line with the GPU? // This is the "last resort" case, where a command buffer execution has been forced diff --git a/Source/Core/VideoBackends/Vulkan/StreamBuffer.cpp b/Source/Core/VideoBackends/Vulkan/StreamBuffer.cpp index aa635e4d41..9582093c89 100644 --- a/Source/Core/VideoBackends/Vulkan/StreamBuffer.cpp +++ b/Source/Core/VideoBackends/Vulkan/StreamBuffer.cpp @@ -254,7 +254,7 @@ bool StreamBuffer::WaitForClearSpace(u32 num_bytes) u32 new_gpu_position = 0; auto iter = m_tracked_fences.begin(); - for (; iter != m_tracked_fences.end(); iter++) + for (; iter != m_tracked_fences.end(); ++iter) { // Would this fence bring us in line with the GPU? // This is the "last resort" case, where a command buffer execution has been forced From 11339d77c6835dd908b86a92412686c46435e006 Mon Sep 17 00:00:00 2001 From: David Korth Date: Tue, 24 Sep 2019 00:42:39 -0400 Subject: [PATCH 10/10] IsSettingSaveable.cpp: Significant code size reduction. - Refactor the Config::System::Main check so we check system once, then we check for the section. - Use an std::array<> instead of std::vector<>. - Use an array of pointers instead of an array of ConfigLocation. The latter contains two std::string objects, whereas pointers are only 8 bytes (on 64-bit). Code size comparison: (64-bit Linux, gcc-9.2.0, release build) text data bss dec hex filename 16136 0 40 16176 3f30 IsSettingSaveable.cpp.o [before] 3933 720 0 4653 122d IsSettingSaveable.cpp.o [after] -12203 +720 -40 -11523 -2d03 Difference --- .../Core/ConfigLoaders/IsSettingSaveable.cpp | 202 +++++++++--------- 1 file changed, 102 insertions(+), 100 deletions(-) diff --git a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp index 629bba3a2d..5f17e6cac1 100644 --- a/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp +++ b/Source/Core/Core/ConfigLoaders/IsSettingSaveable.cpp @@ -22,134 +22,136 @@ bool IsSettingSaveable(const Config::ConfigLocation& config_location) if (config_location.system == Config::System::Logger) return true; - if (config_location.system == Config::System::Main && config_location.section == "NetPlay") - return true; + if (config_location.system == Config::System::Main) + { + if (config_location.section == "NetPlay" || config_location.section == "General") + return true; + } - if (config_location.system == Config::System::Main && config_location.section == "General") - return true; - - const static std::vector s_setting_saveable{ + static constexpr std::array s_setting_saveable = { // Main.Core - Config::MAIN_DEFAULT_ISO.location, - Config::MAIN_MEMCARD_A_PATH.location, - Config::MAIN_MEMCARD_B_PATH.location, - Config::MAIN_AUTO_DISC_CHANGE.location, - Config::MAIN_DPL2_DECODER.location, - Config::MAIN_DPL2_QUALITY.location, + &Config::MAIN_DEFAULT_ISO.location, + &Config::MAIN_MEMCARD_A_PATH.location, + &Config::MAIN_MEMCARD_B_PATH.location, + &Config::MAIN_AUTO_DISC_CHANGE.location, + &Config::MAIN_DPL2_DECODER.location, + &Config::MAIN_DPL2_QUALITY.location, // Main.Display - Config::MAIN_FULLSCREEN_DISPLAY_RES.location, - Config::MAIN_FULLSCREEN.location, - Config::MAIN_RENDER_TO_MAIN.location, - Config::MAIN_RENDER_WINDOW_AUTOSIZE.location, - Config::MAIN_KEEP_WINDOW_ON_TOP.location, - Config::MAIN_DISABLE_SCREENSAVER.location, + &Config::MAIN_FULLSCREEN_DISPLAY_RES.location, + &Config::MAIN_FULLSCREEN.location, + &Config::MAIN_RENDER_TO_MAIN.location, + &Config::MAIN_RENDER_WINDOW_AUTOSIZE.location, + &Config::MAIN_KEEP_WINDOW_ON_TOP.location, + &Config::MAIN_DISABLE_SCREENSAVER.location, // Graphics.Hardware - Config::GFX_VSYNC.location, - Config::GFX_ADAPTER.location, + &Config::GFX_VSYNC.location, + &Config::GFX_ADAPTER.location, // Graphics.Settings - Config::GFX_WIDESCREEN_HACK.location, - Config::GFX_ASPECT_RATIO.location, - Config::GFX_CROP.location, - Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES.location, - Config::GFX_SHOW_FPS.location, - Config::GFX_SHOW_NETPLAY_PING.location, - Config::GFX_SHOW_NETPLAY_MESSAGES.location, - Config::GFX_LOG_RENDER_TIME_TO_FILE.location, - Config::GFX_OVERLAY_STATS.location, - Config::GFX_OVERLAY_PROJ_STATS.location, - Config::GFX_DUMP_TEXTURES.location, - Config::GFX_HIRES_TEXTURES.location, - Config::GFX_CACHE_HIRES_TEXTURES.location, - Config::GFX_DUMP_EFB_TARGET.location, - Config::GFX_DUMP_FRAMES_AS_IMAGES.location, - Config::GFX_FREE_LOOK.location, - Config::GFX_USE_FFV1.location, - Config::GFX_DUMP_FORMAT.location, - Config::GFX_DUMP_CODEC.location, - Config::GFX_DUMP_ENCODER.location, - Config::GFX_DUMP_PATH.location, - Config::GFX_BITRATE_KBPS.location, - Config::GFX_INTERNAL_RESOLUTION_FRAME_DUMPS.location, - Config::GFX_ENABLE_GPU_TEXTURE_DECODING.location, - Config::GFX_ENABLE_PIXEL_LIGHTING.location, - Config::GFX_FAST_DEPTH_CALC.location, - Config::GFX_MSAA.location, - Config::GFX_SSAA.location, - Config::GFX_EFB_SCALE.location, - Config::GFX_TEXFMT_OVERLAY_ENABLE.location, - Config::GFX_TEXFMT_OVERLAY_CENTER.location, - Config::GFX_ENABLE_WIREFRAME.location, - Config::GFX_DISABLE_FOG.location, - Config::GFX_BORDERLESS_FULLSCREEN.location, - Config::GFX_ENABLE_VALIDATION_LAYER.location, - Config::GFX_BACKEND_MULTITHREADING.location, - Config::GFX_COMMAND_BUFFER_EXECUTE_INTERVAL.location, - Config::GFX_SHADER_CACHE.location, - Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING.location, - Config::GFX_SHADER_COMPILATION_MODE.location, - Config::GFX_SHADER_COMPILER_THREADS.location, - Config::GFX_SHADER_PRECOMPILER_THREADS.location, - Config::GFX_SAVE_TEXTURE_CACHE_TO_STATE.location, + &Config::GFX_WIDESCREEN_HACK.location, + &Config::GFX_ASPECT_RATIO.location, + &Config::GFX_CROP.location, + &Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES.location, + &Config::GFX_SHOW_FPS.location, + &Config::GFX_SHOW_NETPLAY_PING.location, + &Config::GFX_SHOW_NETPLAY_MESSAGES.location, + &Config::GFX_LOG_RENDER_TIME_TO_FILE.location, + &Config::GFX_OVERLAY_STATS.location, + &Config::GFX_OVERLAY_PROJ_STATS.location, + &Config::GFX_DUMP_TEXTURES.location, + &Config::GFX_HIRES_TEXTURES.location, + &Config::GFX_CACHE_HIRES_TEXTURES.location, + &Config::GFX_DUMP_EFB_TARGET.location, + &Config::GFX_DUMP_FRAMES_AS_IMAGES.location, + &Config::GFX_FREE_LOOK.location, + &Config::GFX_USE_FFV1.location, + &Config::GFX_DUMP_FORMAT.location, + &Config::GFX_DUMP_CODEC.location, + &Config::GFX_DUMP_ENCODER.location, + &Config::GFX_DUMP_PATH.location, + &Config::GFX_BITRATE_KBPS.location, + &Config::GFX_INTERNAL_RESOLUTION_FRAME_DUMPS.location, + &Config::GFX_ENABLE_GPU_TEXTURE_DECODING.location, + &Config::GFX_ENABLE_PIXEL_LIGHTING.location, + &Config::GFX_FAST_DEPTH_CALC.location, + &Config::GFX_MSAA.location, + &Config::GFX_SSAA.location, + &Config::GFX_EFB_SCALE.location, + &Config::GFX_TEXFMT_OVERLAY_ENABLE.location, + &Config::GFX_TEXFMT_OVERLAY_CENTER.location, + &Config::GFX_ENABLE_WIREFRAME.location, + &Config::GFX_DISABLE_FOG.location, + &Config::GFX_BORDERLESS_FULLSCREEN.location, + &Config::GFX_ENABLE_VALIDATION_LAYER.location, + &Config::GFX_BACKEND_MULTITHREADING.location, + &Config::GFX_COMMAND_BUFFER_EXECUTE_INTERVAL.location, + &Config::GFX_SHADER_CACHE.location, + &Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING.location, + &Config::GFX_SHADER_COMPILATION_MODE.location, + &Config::GFX_SHADER_COMPILER_THREADS.location, + &Config::GFX_SHADER_PRECOMPILER_THREADS.location, + &Config::GFX_SAVE_TEXTURE_CACHE_TO_STATE.location, - Config::GFX_SW_ZCOMPLOC.location, - Config::GFX_SW_ZFREEZE.location, - Config::GFX_SW_DUMP_OBJECTS.location, - Config::GFX_SW_DUMP_TEV_STAGES.location, - Config::GFX_SW_DUMP_TEV_TEX_FETCHES.location, - Config::GFX_SW_DRAW_START.location, - Config::GFX_SW_DRAW_END.location, + &Config::GFX_SW_ZCOMPLOC.location, + &Config::GFX_SW_ZFREEZE.location, + &Config::GFX_SW_DUMP_OBJECTS.location, + &Config::GFX_SW_DUMP_TEV_STAGES.location, + &Config::GFX_SW_DUMP_TEV_TEX_FETCHES.location, + &Config::GFX_SW_DRAW_START.location, + &Config::GFX_SW_DRAW_END.location, // Graphics.Enhancements - Config::GFX_ENHANCE_FORCE_FILTERING.location, - Config::GFX_ENHANCE_MAX_ANISOTROPY.location, - Config::GFX_ENHANCE_POST_SHADER.location, - Config::GFX_ENHANCE_FORCE_TRUE_COLOR.location, - Config::GFX_ENHANCE_DISABLE_COPY_FILTER.location, - Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION.location, + &Config::GFX_ENHANCE_FORCE_FILTERING.location, + &Config::GFX_ENHANCE_MAX_ANISOTROPY.location, + &Config::GFX_ENHANCE_POST_SHADER.location, + &Config::GFX_ENHANCE_FORCE_TRUE_COLOR.location, + &Config::GFX_ENHANCE_DISABLE_COPY_FILTER.location, + &Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION.location, // Graphics.Stereoscopy - Config::GFX_STEREO_MODE.location, - Config::GFX_STEREO_DEPTH.location, - Config::GFX_STEREO_CONVERGENCE_PERCENTAGE.location, - Config::GFX_STEREO_SWAP_EYES.location, - Config::GFX_STEREO_CONVERGENCE.location, - Config::GFX_STEREO_EFB_MONO_DEPTH.location, - Config::GFX_STEREO_DEPTH_PERCENTAGE.location, + &Config::GFX_STEREO_MODE.location, + &Config::GFX_STEREO_DEPTH.location, + &Config::GFX_STEREO_CONVERGENCE_PERCENTAGE.location, + &Config::GFX_STEREO_SWAP_EYES.location, + &Config::GFX_STEREO_CONVERGENCE.location, + &Config::GFX_STEREO_EFB_MONO_DEPTH.location, + &Config::GFX_STEREO_DEPTH_PERCENTAGE.location, // Graphics.Hacks - Config::GFX_HACK_EFB_ACCESS_ENABLE.location, - Config::GFX_HACK_EFB_DEFER_INVALIDATION.location, - Config::GFX_HACK_EFB_ACCESS_TILE_SIZE.location, - Config::GFX_HACK_BBOX_ENABLE.location, - Config::GFX_HACK_FORCE_PROGRESSIVE.location, - Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM.location, - Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM.location, - Config::GFX_HACK_DISABLE_COPY_TO_VRAM.location, - Config::GFX_HACK_DEFER_EFB_COPIES.location, - Config::GFX_HACK_IMMEDIATE_XFB.location, - Config::GFX_HACK_COPY_EFB_SCALED.location, - Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES.location, - Config::GFX_HACK_VERTEX_ROUDING.location, + &Config::GFX_HACK_EFB_ACCESS_ENABLE.location, + &Config::GFX_HACK_EFB_DEFER_INVALIDATION.location, + &Config::GFX_HACK_EFB_ACCESS_TILE_SIZE.location, + &Config::GFX_HACK_BBOX_ENABLE.location, + &Config::GFX_HACK_FORCE_PROGRESSIVE.location, + &Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM.location, + &Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM.location, + &Config::GFX_HACK_DISABLE_COPY_TO_VRAM.location, + &Config::GFX_HACK_DEFER_EFB_COPIES.location, + &Config::GFX_HACK_IMMEDIATE_XFB.location, + &Config::GFX_HACK_COPY_EFB_SCALED.location, + &Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES.location, + &Config::GFX_HACK_VERTEX_ROUDING.location, // Graphics.GameSpecific - Config::GFX_PERF_QUERIES_ENABLE.location, + &Config::GFX_PERF_QUERIES_ENABLE.location, // UI.General - Config::MAIN_USE_DISCORD_PRESENCE.location, + &Config::MAIN_USE_DISCORD_PRESENCE.location, }; - return std::find(s_setting_saveable.begin(), s_setting_saveable.end(), config_location) != - s_setting_saveable.end(); + return std::any_of(s_setting_saveable.cbegin(), s_setting_saveable.cend(), + [&config_location](const Config::ConfigLocation* location) { + return *location == config_location; + }); } } // namespace ConfigLoaders