Ensures that the destruction logic is kept local to the translation unit
(making it nicer when it comes to forward declaring non-trivial types).
It also doesn't really do much to define it in the header.
Given we're simply storing the std::string into a deque. We can emplace
it and move it. Completely avoiding copies with the current usage of the
function.
The pack is already has its validity checked at the beginning of the
function, so we don't need to check this again after inserting it.
Also resolves a use-after-move case.
Same behavior but doesn't take up 8 bytes in the executable to store a
pointer. While we're at it, move it into an anonymous namespace within
the UICommon namespace.
We already check ahead of time if the optional contains a value within
it before accessing it, so we don't need to use the throwing value()
accessor. We can just directly use operator->
Rather than construct strings twice, we can just construct it once and
reuse it. While we're at it, we can move variables closer to where
they're actually used within DownloadDefaultCover()
This allows the same code to be used to read into a std::string, which
allows for eliminating the vector->string transfer when reading the
manifest file.
A ContiguousContainer is a concept that includes std::array,
std::string, and std::vector.
Makes it way harder to introduce resource leaks, and plugs the existing
resource leaks in the constructor and Install() where the file wouldn't
be closed in some error cases.
Now that we assume C++17, the in-file definition of the std::array can
be removed. This is all that's necessary, as constexpr used on a static
member variable implies inline (and so, automatically has C++17's static
inline behavior).
Removes redundant initializers from the constructor and provides
initializers for all members that don't already have one for consistency
(and deterministic initial state).
Given the volume verifier has quite a few non-trivial object within it,
it's best to default the destructor within the cpp file to prevent
inlining complex destruction logic elsewhere, while also making it nicer
if a forward-declared type is ever used in a member variable.
std::call_once is guaranteed to execute the given callable object
exactly once. This guarantee holds even if the function is called
concurrently from several threads.
Given that, we can replace the mutex and boolean flag with
std::call_once and a std::once_flag to perform the same behavior.
Previously, every entry pair within the map would be copied. The reason
for this is subtle.
A std::map's internal entry type is defined as:
std::pair<const Key, Value>
but the loop was declaring it as:
std::pair<Key, Value>
These two types aren't synonymous with one another and so the compiler
is required to always perform a copy.
Using structured bindings avoids this (as would plain auto or correcting
the explicit type), while also allowing the use of more appropriate
names compared to first and second.
std::function is allowed to heap allocate in order to hold any necessary
bound data in order to execute properly (e.g. lambdas with captures), so
this avoids unnecessary reallocating.
While current usages of ParseLine aren't problematic, this is still a
public function that can be used for other purposes. Essentially makes
the function handle potential external inputs a little nicer.
We can just utilize map's insert_or_assign() function and check the
return value to determine whether or not we need to insert the key into
the keys_order vector.
In terms of order of operations, the move would occur first before the
construction of the relevant reader would occur. However, given the
local variable 'path' was declared const, this bug actually wouldn't
occur, as std::move on a const variable does nothing (in a non-mutable
context), resulting in a copy instead, masking this issue.
Given this is a bug waiting to happen, we correct the code.
Adds the Hardware Implementation-Dependent registers to the register
pane, which makes it much nicer to see which hardware-specific features
are enabled or disabled.
Previously, PowerPC.h had four macros in it like so:
\#define rPS0(i) (*(double*)(&PowerPC::ppcState.ps[i][0]))
\#define rPS1(i) (*(double*)(&PowerPC::ppcState.ps[i][1]))
\#define riPS0(i) (*(u64*)(&PowerPC::ppcState.ps[i][0]))
\#define riPS1(i) (*(u64*)(&PowerPC::ppcState.ps[i][1]))
Casting between object representations like this is undefined behavior.
Given this is used heavily with the interpreter (that is, the most
accurate, but slowest CPU backend), we don't exactly want to allow
undefined behavior to creep into it.
Instead, this adds a helper struct for operating with the paired singles,
and replaces the four macros with a single macro for accessing the
paired-singles/floating-point registers.
This way, it's left up to the caller to explicitly decide how it wants to interpret
the data (and makes it more obvious where different interpretations of
the same data are occurring at, as there'll be a call to one of the
[x]AsDouble() functions).
These bits enable or disable paired-single execution based on how
they're set. If PSE isn't set, then all paired-single instructions are
illegal. If PSE is set, but LSQE isn't set, then psq_l, psq_lu, psq_st
and psq_stu are illegal to execute.
Also thanks go out to my roommate @Veegie for letting me use his Wii as
a blasting ground for tests, since mine isn't on hand right now. It only
caught on fire twice and only burned down half of the house through the
process; what a team player.