diff --git a/src/common/file_util.h b/src/common/file_util.h index 9eafa2416..d5915b8b7 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "common/common_types.h" #ifdef _MSC_VER #include "common/string_util.h" @@ -41,6 +42,34 @@ enum class UserPath { UserDir, }; +// Replaces install-specific paths with standard placeholders, and back again +std::string SerializePath(const std::string& input, bool is_saving); + +// A serializable path string +struct Path : public boost::serialization::wrapper_traits { + std::string& str; + + explicit Path(std::string& _str) : str(_str) {} + + static const Path make(std::string& str) { + return Path(str); + } + + template + void save(Archive& ar, const unsigned int) const { + auto s_path = SerializePath(str, true); + ar << s_path; + } + template + void load(Archive& ar, const unsigned int) const { + ar >> str; + str = SerializePath(str, false); + } + + BOOST_SERIALIZATION_SPLIT_MEMBER(); + friend class boost::serialization::access; +}; + // FileSystem tree node/ struct FSTEntry { bool isDirectory; @@ -48,6 +77,17 @@ struct FSTEntry { std::string physicalName; // name on disk std::string virtualName; // name in FST names table std::vector children; + +private: + template + void serialize(Archive& ar, const unsigned int) { + ar& isDirectory; + ar& size; + ar& Path::make(physicalName); + ar& Path::make(virtualName); + ar& children; + } + friend class boost::serialization::access; }; // Returns true if file filename exists @@ -146,9 +186,6 @@ void SetCurrentRomPath(const std::string& path); // directory. To be used in "multi-user" mode (that is, installed). const std::string& GetUserPath(UserPath path); -// Replaces install-specific paths with standard placeholders, and back again -std::string SerializePath(const std::string& input, bool is_saving); - // Returns the path to where the sys file are std::string GetSysDirectory(); @@ -322,27 +359,20 @@ private: u32 flags; template - void save(Archive& ar, const unsigned int) const { - auto s_filename = SerializePath(filename, true); - ar << s_filename; - ar << openmode; - ar << flags; - ar << Tell(); - } - - template - void load(Archive& ar, const unsigned int) { - ar >> filename; - filename = SerializePath(filename, false); - ar >> openmode; - ar >> flags; + void serialize(Archive& ar, const unsigned int) { + ar& Path::make(filename); + ar& openmode; + ar& flags; u64 pos; - ar >> pos; - Open(); - Seek(pos, SEEK_SET); + if (Archive::is_saving::value) { + pos = Tell(); + } + ar& pos; + if (Archive::is_loading::value) { + Open(); + Seek(pos, SEEK_SET); + } } - - BOOST_SERIALIZATION_SPLIT_MEMBER() friend class boost::serialization::access; }; diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp index 061460546..6ace314bf 100644 --- a/src/core/file_sys/disk_archive.cpp +++ b/src/core/file_sys/disk_archive.cpp @@ -5,6 +5,7 @@ #include #include #include +#include "common/archives.h" #include "common/common_types.h" #include "common/file_util.h" #include "common/logging/log.h" @@ -14,6 +15,9 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// // FileSys namespace +SERIALIZE_EXPORT_IMPL(FileSys::DiskFile) +SERIALIZE_EXPORT_IMPL(FileSys::DiskDirectory) + namespace FileSys { ResultVal DiskFile::Read(const u64 offset, const std::size_t length, diff --git a/src/core/file_sys/disk_archive.h b/src/core/file_sys/disk_archive.h index 9251749ce..2f0e5691a 100644 --- a/src/core/file_sys/disk_archive.h +++ b/src/core/file_sys/disk_archive.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "common/common_types.h" #include "common/file_util.h" #include "core/file_sys/archive_backend.h" @@ -46,12 +47,16 @@ protected: Mode mode; std::unique_ptr file; +private: + DiskFile() = default; + template void serialize(Archive& ar, const unsigned int) { ar& boost::serialization::base_object(*this); - ar& mode; + ar& mode.hex; ar& file; } + friend class boost::serialization::access; }; class DiskDirectory : public DirectoryBackend { @@ -74,6 +79,27 @@ protected: // We need to remember the last entry we returned, so a subsequent call to Read will continue // from the next one. This iterator will always point to the next unread entry. std::vector::iterator children_iterator; + +private: + DiskDirectory() = default; + + template + void serialize(Archive& ar, const unsigned int) { + ar& boost::serialization::base_object(*this); + ar& directory; + u64 child_index; + if (Archive::is_saving::value) { + child_index = children_iterator - directory.children.begin(); + } + ar& child_index; + if (Archive::is_loading::value) { + children_iterator = directory.children.begin() + child_index; + } + } + friend class boost::serialization::access; }; } // namespace FileSys + +BOOST_CLASS_EXPORT_KEY(FileSys::DiskFile) +BOOST_CLASS_EXPORT_KEY(FileSys::DiskDirectory)