Stays consistent in our code with using Qt's provided mechanisms, and
also properly handles Unicode paths (which file streams on Windows don't
do very well).
Similarly, here we can avoid doing unnecessary work twice by retrieving
the file type only once and comparing it against relevant operands,
avoiding potential unnecessary object construction/destruction.
While GetFileType() is indeed a getter function, that doesn't mean it's
a trivial function, given some case require reading from the data or
constructing other objects in the background. Instead, only do necessary
work once.
We can just return a new instance of this when it's requested. This only
ever holds pointers to the existing registed caches, so it's not a large
object. Plus, this also gets rid of the need to keep around a separate
member function just to properly clear out the union.
Gets rid of one of five globals in the filesystem code.
We don't need to call out to our own file handling functions when we're
going to construct a QFileInfo instance right after it. We also don't
need to convert to a std::string again just to compare the file
extension.
As the add-ons column takes the most processing time out of any (as it needs to search registration for updates/dlc, patch control NCAs, search for mods, etc.), an option was added to disable it. This does not affect the application of add-ons. In large game collections, this decreases game list refresh time by as much as 70%.
Using fmt here requires unnecessary string conversions back into
QString. Instead, we can just use QString's formatting and get the end
result of the formatting operation in the proper type.
The data retrieved in these cases are ultimately chiefly owned by either
the RegisteredCache instance itself, or the filesystem factories. Both
these should live throughout the use of their contained data. If they
don't, it should be considered an interface/design issue, and using
shared_ptr instances here would mask that, as the data would always be
prolonged after the main owner's lifetime ended.
This makes the lifetime of the data explicit and makes it harder to
accidentally create cyclic references. It also makes the interface
slightly more flexible than the previous API, as a shared_ptr can be
created from a unique_ptr, but not the other way around, so this allows
for that use-case if it ever becomes necessary in some form.
Neither of these functions require the use of shared ownership of the
returned pointer. This makes it more difficult to create reference
cycles with, and makes the interface more generic, as std::shared_ptr
instances can be created from a std::unique_ptr, but the vice-versa
isn't possible. This also alters relevant functions to take NCA
arguments by const reference rather than a const reference to a
std::shared_ptr. These functions don't alter the ownership of the memory
used by the NCA instance, so we can make the interface more generic by
not assuming anything about the type of smart pointer the NCA is
contained within and make it the caller's responsibility to ensure the
supplied NCA is valid.
Lets us keep the generic portions of the compatibility list code
together, and allows us to introduce a type alias that makes it so we
don't need to type out a very long type declaration anymore, making the
immediate readability of some code better.
This has gotten sufficiently large enough to warrant moving it to its
own source files. Especially given it dumps the file_sys headers around
code that doesn't use it for the most part.
This'll also make it easier to introduce a type alias for the
compatibility list, so a large unordered_map type declaration doesn't
need to be specified all the time (we don't want to propagate the
game_list_p.h include via the main game_list.h header).