Add disk archive serialization (fix crash in driver renegade etc.)
This commit is contained in:
parent
a210e7e2bd
commit
e9ab8f82d4
|
@ -16,6 +16,7 @@
|
|||
#include <vector>
|
||||
#include <boost/serialization/split_member.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include <boost/serialization/wrapper.hpp>
|
||||
#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<const Path> {
|
||||
std::string& str;
|
||||
|
||||
explicit Path(std::string& _str) : str(_str) {}
|
||||
|
||||
static const Path make(std::string& str) {
|
||||
return Path(str);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void save(Archive& ar, const unsigned int) const {
|
||||
auto s_path = SerializePath(str, true);
|
||||
ar << s_path;
|
||||
}
|
||||
template <class Archive>
|
||||
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<FSTEntry> children;
|
||||
|
||||
private:
|
||||
template <class Archive>
|
||||
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 <class Archive>
|
||||
void save(Archive& ar, const unsigned int) const {
|
||||
auto s_filename = SerializePath(filename, true);
|
||||
ar << s_filename;
|
||||
ar << openmode;
|
||||
ar << flags;
|
||||
ar << Tell();
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
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;
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#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<std::size_t> DiskFile::Read(const u64 offset, const std::size_t length,
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <vector>
|
||||
#include <boost/serialization/base_object.hpp>
|
||||
#include <boost/serialization/unique_ptr.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#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<FileUtil::IOFile> file;
|
||||
|
||||
private:
|
||||
DiskFile() = default;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& boost::serialization::base_object<FileBackend>(*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<FileUtil::FSTEntry>::iterator children_iterator;
|
||||
|
||||
private:
|
||||
DiskDirectory() = default;
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int) {
|
||||
ar& boost::serialization::base_object<DirectoryBackend>(*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)
|
||||
|
|
Reference in New Issue