From 93ac8d0feadc129fdfdbaccd0c4e444b34ce2f15 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 9 Oct 2018 13:34:38 -0400 Subject: [PATCH 1/4] ips_layer: std::move data within PatchIPS() and Apply() We don't need to make a copy of the read data, so we can std::move it into the make_shared call here. --- src/core/file_sys/ips_layer.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/core/file_sys/ips_layer.cpp b/src/core/file_sys/ips_layer.cpp index 0cadbc375..b7a3df1b0 100644 --- a/src/core/file_sys/ips_layer.cpp +++ b/src/core/file_sys/ips_layer.cpp @@ -90,7 +90,9 @@ VirtualFile PatchIPS(const VirtualFile& in, const VirtualFile& ips) { if (temp != std::vector{'E', 'E', 'O', 'F'} && temp != std::vector{'E', 'O', 'F'}) return nullptr; - return std::make_shared(in_data, in->GetName(), in->GetContainingDirectory()); + + return std::make_shared(std::move(in_data), in->GetName(), + in->GetContainingDirectory()); } IPSwitchCompiler::IPSwitchCompiler(VirtualFile patch_text_) : patch_text(std::move(patch_text_)) { @@ -291,7 +293,8 @@ VirtualFile IPSwitchCompiler::Apply(const VirtualFile& in) const { } } - return std::make_shared(in_data, in->GetName(), in->GetContainingDirectory()); + return std::make_shared(std::move(in_data), in->GetName(), + in->GetContainingDirectory()); } } // namespace FileSys From f7d2889fb46bf5589b53952c656fdc090334b9de Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 9 Oct 2018 13:39:23 -0400 Subject: [PATCH 2/4] ips_layer: Add missing includes Adds missing includes to prevent potential compilation issues in the future. Also moves the definition of a struct into the cpp file, so that some includes don't need to be introduced within the header. --- src/core/file_sys/ips_layer.cpp | 13 ++++++++++++- src/core/file_sys/ips_layer.h | 11 +++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/core/file_sys/ips_layer.cpp b/src/core/file_sys/ips_layer.cpp index b7a3df1b0..f832bf8e6 100644 --- a/src/core/file_sys/ips_layer.cpp +++ b/src/core/file_sys/ips_layer.cpp @@ -2,9 +2,14 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include #include -#include "common/assert.h" +#include +#include + #include "common/hex_util.h" +#include "common/logging/log.h" #include "common/swap.h" #include "core/file_sys/ips_layer.h" #include "core/file_sys/vfs_vector.h" @@ -95,6 +100,12 @@ VirtualFile PatchIPS(const VirtualFile& in, const VirtualFile& ips) { in->GetContainingDirectory()); } +struct IPSwitchCompiler::IPSwitchPatch { + std::string name; + bool enabled; + std::map> records; +}; + IPSwitchCompiler::IPSwitchCompiler(VirtualFile patch_text_) : patch_text(std::move(patch_text_)) { Parse(); } diff --git a/src/core/file_sys/ips_layer.h b/src/core/file_sys/ips_layer.h index 57da00da8..450b2f71e 100644 --- a/src/core/file_sys/ips_layer.h +++ b/src/core/file_sys/ips_layer.h @@ -4,8 +4,11 @@ #pragma once +#include #include +#include +#include "common/common_types.h" #include "core/file_sys/vfs.h" namespace FileSys { @@ -22,17 +25,13 @@ public: VirtualFile Apply(const VirtualFile& in) const; private: + struct IPSwitchPatch; + void ParseFlag(const std::string& flag); void Parse(); bool valid = false; - struct IPSwitchPatch { - std::string name; - bool enabled; - std::map> records; - }; - VirtualFile patch_text; std::vector patches; std::array nso_build_id{}; From 9ff743bc0acb63a176cd7c823aa63f5602c41299 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 9 Oct 2018 13:42:34 -0400 Subject: [PATCH 3/4] ips_layer: Remove unnecessary explicit std::pair constructor in std::array Makes the layout of the array consistent, by making all elements match, instead of special-casing the first one. --- src/core/file_sys/ips_layer.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/core/file_sys/ips_layer.cpp b/src/core/file_sys/ips_layer.cpp index f832bf8e6..90f91f230 100644 --- a/src/core/file_sys/ips_layer.cpp +++ b/src/core/file_sys/ips_layer.cpp @@ -22,11 +22,19 @@ enum class IPSFileType { Error, }; -constexpr std::array, 11> ESCAPE_CHARACTER_MAP{ - std::pair{"\\a", "\a"}, {"\\b", "\b"}, {"\\f", "\f"}, {"\\n", "\n"}, - {"\\r", "\r"}, {"\\t", "\t"}, {"\\v", "\v"}, {"\\\\", "\\"}, - {"\\\'", "\'"}, {"\\\"", "\""}, {"\\\?", "\?"}, -}; +constexpr std::array, 11> ESCAPE_CHARACTER_MAP{{ + {"\\a", "\a"}, + {"\\b", "\b"}, + {"\\f", "\f"}, + {"\\n", "\n"}, + {"\\r", "\r"}, + {"\\t", "\t"}, + {"\\v", "\v"}, + {"\\\\", "\\"}, + {"\\\'", "\'"}, + {"\\\"", "\""}, + {"\\\?", "\?"}, +}}; static IPSFileType IdentifyMagic(const std::vector& magic) { if (magic.size() != 5) From 465175cdf58fecf9098c702feaf8d000f0952973 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 9 Oct 2018 13:47:59 -0400 Subject: [PATCH 4/4] ips_layer: Avoid constructing std::vector instances where not necessary We can just compare the existing std::vector instance with a constexpr std::array containing the desired match. This is lighter resource-wise, as we don't need to allocate on the heap. --- src/core/file_sys/ips_layer.cpp | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/core/file_sys/ips_layer.cpp b/src/core/file_sys/ips_layer.cpp index 90f91f230..6c072d0a3 100644 --- a/src/core/file_sys/ips_layer.cpp +++ b/src/core/file_sys/ips_layer.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include #include #include @@ -37,15 +38,33 @@ constexpr std::array, 11> ESCAPE_CHARACTER_M }}; static IPSFileType IdentifyMagic(const std::vector& magic) { - if (magic.size() != 5) + if (magic.size() != 5) { return IPSFileType::Error; - if (magic == std::vector{'P', 'A', 'T', 'C', 'H'}) + } + + constexpr std::array patch_magic{{'P', 'A', 'T', 'C', 'H'}}; + if (std::equal(magic.begin(), magic.end(), patch_magic.begin())) { return IPSFileType::IPS; - if (magic == std::vector{'I', 'P', 'S', '3', '2'}) + } + + constexpr std::array ips32_magic{{'I', 'P', 'S', '3', '2'}}; + if (std::equal(magic.begin(), magic.end(), ips32_magic.begin())) { return IPSFileType::IPS32; + } + return IPSFileType::Error; } +static bool IsEOF(IPSFileType type, const std::vector& data) { + constexpr std::array eof{{'E', 'O', 'F'}}; + if (type == IPSFileType::IPS && std::equal(data.begin(), data.end(), eof.begin())) { + return true; + } + + constexpr std::array eeof{{'E', 'E', 'O', 'F'}}; + return type == IPSFileType::IPS32 && std::equal(data.begin(), data.end(), eeof.begin()); +} + VirtualFile PatchIPS(const VirtualFile& in, const VirtualFile& ips) { if (in == nullptr || ips == nullptr) return nullptr; @@ -60,8 +79,7 @@ VirtualFile PatchIPS(const VirtualFile& in, const VirtualFile& ips) { u64 offset = 5; // After header while (ips->Read(temp.data(), temp.size(), offset) == temp.size()) { offset += temp.size(); - if (type == IPSFileType::IPS32 && temp == std::vector{'E', 'E', 'O', 'F'} || - type == IPSFileType::IPS && temp == std::vector{'E', 'O', 'F'}) { + if (IsEOF(type, temp)) { break; } @@ -101,8 +119,9 @@ VirtualFile PatchIPS(const VirtualFile& in, const VirtualFile& ips) { } } - if (temp != std::vector{'E', 'E', 'O', 'F'} && temp != std::vector{'E', 'O', 'F'}) + if (!IsEOF(type, temp)) { return nullptr; + } return std::make_shared(std::move(in_data), in->GetName(), in->GetContainingDirectory());