Add disk archive serialization (fix crash in driver renegade etc.)
This commit is contained in:
parent
a210e7e2bd
commit
e9ab8f82d4
3 changed files with 83 additions and 23 deletions
|
@ -16,6 +16,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/serialization/split_member.hpp>
|
#include <boost/serialization/split_member.hpp>
|
||||||
#include <boost/serialization/string.hpp>
|
#include <boost/serialization/string.hpp>
|
||||||
|
#include <boost/serialization/wrapper.hpp>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
@ -41,6 +42,34 @@ enum class UserPath {
|
||||||
UserDir,
|
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/
|
// FileSystem tree node/
|
||||||
struct FSTEntry {
|
struct FSTEntry {
|
||||||
bool isDirectory;
|
bool isDirectory;
|
||||||
|
@ -48,6 +77,17 @@ struct FSTEntry {
|
||||||
std::string physicalName; // name on disk
|
std::string physicalName; // name on disk
|
||||||
std::string virtualName; // name in FST names table
|
std::string virtualName; // name in FST names table
|
||||||
std::vector<FSTEntry> children;
|
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
|
// 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).
|
// directory. To be used in "multi-user" mode (that is, installed).
|
||||||
const std::string& GetUserPath(UserPath path);
|
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
|
// Returns the path to where the sys file are
|
||||||
std::string GetSysDirectory();
|
std::string GetSysDirectory();
|
||||||
|
|
||||||
|
@ -322,27 +359,20 @@ private:
|
||||||
u32 flags;
|
u32 flags;
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void save(Archive& ar, const unsigned int) const {
|
void serialize(Archive& ar, const unsigned int) {
|
||||||
auto s_filename = SerializePath(filename, true);
|
ar& Path::make(filename);
|
||||||
ar << s_filename;
|
ar& openmode;
|
||||||
ar << openmode;
|
ar& flags;
|
||||||
ar << flags;
|
|
||||||
ar << Tell();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Archive>
|
|
||||||
void load(Archive& ar, const unsigned int) {
|
|
||||||
ar >> filename;
|
|
||||||
filename = SerializePath(filename, false);
|
|
||||||
ar >> openmode;
|
|
||||||
ar >> flags;
|
|
||||||
u64 pos;
|
u64 pos;
|
||||||
ar >> pos;
|
if (Archive::is_saving::value) {
|
||||||
Open();
|
pos = Tell();
|
||||||
Seek(pos, SEEK_SET);
|
}
|
||||||
|
ar& pos;
|
||||||
|
if (Archive::is_loading::value) {
|
||||||
|
Open();
|
||||||
|
Seek(pos, SEEK_SET);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include "common/archives.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
@ -14,6 +15,9 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// FileSys namespace
|
// FileSys namespace
|
||||||
|
|
||||||
|
SERIALIZE_EXPORT_IMPL(FileSys::DiskFile)
|
||||||
|
SERIALIZE_EXPORT_IMPL(FileSys::DiskDirectory)
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
ResultVal<std::size_t> DiskFile::Read(const u64 offset, const std::size_t length,
|
ResultVal<std::size_t> DiskFile::Read(const u64 offset, const std::size_t length,
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/serialization/base_object.hpp>
|
#include <boost/serialization/base_object.hpp>
|
||||||
#include <boost/serialization/unique_ptr.hpp>
|
#include <boost/serialization/unique_ptr.hpp>
|
||||||
|
#include <boost/serialization/vector.hpp>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
#include "core/file_sys/archive_backend.h"
|
#include "core/file_sys/archive_backend.h"
|
||||||
|
@ -46,12 +47,16 @@ protected:
|
||||||
Mode mode;
|
Mode mode;
|
||||||
std::unique_ptr<FileUtil::IOFile> file;
|
std::unique_ptr<FileUtil::IOFile> file;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DiskFile() = default;
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int) {
|
void serialize(Archive& ar, const unsigned int) {
|
||||||
ar& boost::serialization::base_object<FileBackend>(*this);
|
ar& boost::serialization::base_object<FileBackend>(*this);
|
||||||
ar& mode;
|
ar& mode.hex;
|
||||||
ar& file;
|
ar& file;
|
||||||
}
|
}
|
||||||
|
friend class boost::serialization::access;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DiskDirectory : public DirectoryBackend {
|
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
|
// 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.
|
// from the next one. This iterator will always point to the next unread entry.
|
||||||
std::vector<FileUtil::FSTEntry>::iterator children_iterator;
|
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
|
} // namespace FileSys
|
||||||
|
|
||||||
|
BOOST_CLASS_EXPORT_KEY(FileSys::DiskFile)
|
||||||
|
BOOST_CLASS_EXPORT_KEY(FileSys::DiskDirectory)
|
||||||
|
|
Loading…
Reference in a new issue