Boot: Make BootExecutableReader's constructor take a std::vector by value

This allows avoiding two copies of the executable data being created in
the following scenario (using pseudocode):

some_function()
{
  std::vector<u8> data = ...;
  DolReader reader{data};

  ...
}

In this scenario, if we only use the data for passing it to DolReader,
then we have to perform a copy, as the constructor takes the std::vector
as a constant reference -- you cannot move from a constant reference,
and so we copy data into the DolReader, and perform another copy in the
constructor itself when assigning the data to the m_bytes member
variable. However, we can do better.

Now, the following is allowable as well:

some_function()
{
  std::vector<u8> data = ...;
  DolReader reader{std::move(data)};

  ...
}

and now we perform no copy at any point in the reader's construction, as
we just std::move the data all the way through to m_bytes.

In the case where we *do* want to keep the executable data around after
constructing the reader, then we can just pass the vector without
std::move-ing it, and we only perform a copy once (as we'll std::move
said copy into m_bytes). Therefore, we get a more flexible interface
resource-wise out of it.
This commit is contained in:
Lioncash 2018-05-12 17:10:03 -04:00
parent f91b729b61
commit f7bc75ae6d
6 changed files with 8 additions and 7 deletions

View File

@ -12,6 +12,7 @@
#include <optional>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
#include <zlib.h>
@ -456,7 +457,7 @@ BootExecutableReader::BootExecutableReader(File::IOFile file)
file.ReadBytes(m_bytes.data(), m_bytes.size());
}
BootExecutableReader::BootExecutableReader(const std::vector<u8>& bytes) : m_bytes(bytes)
BootExecutableReader::BootExecutableReader(std::vector<u8> bytes) : m_bytes(std::move(bytes))
{
}

View File

@ -124,7 +124,7 @@ class BootExecutableReader
public:
explicit BootExecutableReader(const std::string& file_name);
explicit BootExecutableReader(File::IOFile file);
explicit BootExecutableReader(const std::vector<u8>& buffer);
explicit BootExecutableReader(std::vector<u8> buffer);
virtual ~BootExecutableReader();
virtual u32 GetEntryPoint() const = 0;

View File

@ -14,9 +14,9 @@
#include "Common/Swap.h"
#include "Core/HW/Memmap.h"
DolReader::DolReader(const std::vector<u8>& buffer) : BootExecutableReader(buffer)
DolReader::DolReader(std::vector<u8> buffer) : BootExecutableReader(std::move(buffer))
{
m_is_valid = Initialize(buffer);
m_is_valid = Initialize(m_bytes);
}
DolReader::DolReader(File::IOFile file) : BootExecutableReader(std::move(file))

View File

@ -20,7 +20,7 @@ class DolReader final : public BootExecutableReader
public:
explicit DolReader(const std::string& filename);
explicit DolReader(File::IOFile file);
explicit DolReader(const std::vector<u8>& buffer);
explicit DolReader(std::vector<u8> buffer);
~DolReader();
bool IsValid() const override { return m_is_valid; }

View File

@ -68,7 +68,7 @@ static void byteswapSection(Elf32_Shdr& sec)
bswap(sec.sh_type);
}
ElfReader::ElfReader(const std::vector<u8>& buffer) : BootExecutableReader(buffer)
ElfReader::ElfReader(std::vector<u8> buffer) : BootExecutableReader(std::move(buffer))
{
Initialize(m_bytes.data());
}

View File

@ -28,7 +28,7 @@ class ElfReader final : public BootExecutableReader
public:
explicit ElfReader(const std::string& filename);
explicit ElfReader(File::IOFile file);
explicit ElfReader(const std::vector<u8>& buffer);
explicit ElfReader(std::vector<u8> buffer);
~ElfReader();
u32 Read32(int off) const { return base32[off >> 2]; }
// Quick accessors