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()
* Simplifies libusb context usage and allows us to set options for
all contexts easily. Notably, this lets us enable usbdk support
in libusb, which is now opt-in in the latest version.
* Moves the libusb config descriptor wrapper class to LibusbUtils too
since that could easily be reused.
* Moves device listing to LibusbUtils too and add a lock around it
as some libusb backends are not thread safe.
* Consequences: only a single context and a single event handling
thread is used now, which is more efficient.
In some cases, this is required to avoid eventually getting a
USBD_STATUS_BAD_START_FRAME error back from the Windows USB stack.
This makes the libusbK code match the behaviour of the Linux backend.
It appears that the libusbK backend tried to get this behaviour by
setting StartFrame to 0. However, libusbK docs state that:
"Specifing 0 for KISO_CONTEXT::StartFrame (start transfer ASAP) is
restricted to the first transaction on a newly opened or reset pipe."
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.
The previous implementation of cheat search would reconvert the input
string for every single memory value. Now we do it once and construct
a comparison lambda which we pass to the search code.
In addition, I also added input validation. So, for example, if you've
selected Decimal input and you try to compare against "FF",
it won't search and will instead let the user know they've entered an
invalid value. Similar logic for if you enter "1.2" in a search for
bytes. Before, it would just use 0 if it failed to convert the value.