99 lines
2.9 KiB
C++
99 lines
2.9 KiB
C++
#pragma once
|
|
|
|
#include "ccl/tools/JSON.h"
|
|
#include "xtr/doc/FileVersions.hpp"
|
|
|
|
#include "CArchiveAdapter.hpp"
|
|
|
|
using JSON = nlohmann::ordered_json;
|
|
|
|
inline void to_json(JSON& object, const CString str) {
|
|
object = xtr::mfc::ToSTL(str);
|
|
}
|
|
|
|
inline void from_json(const JSON& object, CString& str) {
|
|
const auto result = object.get<std::string>();
|
|
str = xtr::mfc::ToMFC(result);
|
|
}
|
|
|
|
namespace xtr::io {
|
|
|
|
//! MFC serializable abstract base
|
|
template<typename Version>
|
|
class MFCSerializable {
|
|
inline static const std::string jsonDocumentName = "document.json";
|
|
|
|
public:
|
|
void Serialize(CArchive& ar) {
|
|
CArchiveAdapter adapter{ ar };
|
|
ASSERT(!ar.IsStoring());
|
|
if (!LegacyLoad(adapter)) {
|
|
AfxThrowArchiveException(CArchiveException::genericException);
|
|
}
|
|
}
|
|
|
|
bool SaveJSON(const std::u8string& path) {
|
|
auto json = ExtractData();
|
|
json["version"] = static_cast<uint16_t>(Version::Latest());
|
|
json["versionInfo"] = Version::LastestInfo();
|
|
return WriteToFile(json.dump(4), path);
|
|
}
|
|
|
|
bool LoadJSON(const std::u8string& path) {
|
|
const auto data = ReadFromFile(path);
|
|
if (!data.has_value()) {
|
|
return false;
|
|
}
|
|
const Version versionID = static_cast<Version::VersionID>(data->at("version").get<uint16_t>());
|
|
return Version::Latest() >= versionID && LoadData(data.value());
|
|
}
|
|
|
|
private:
|
|
virtual JSON ExtractData() const = 0;
|
|
virtual bool LoadData(const JSON& object) = 0;
|
|
virtual bool LegacyLoad(CArchiveAdapter& ar) = 0;
|
|
|
|
bool WriteToFile(std::string_view data, const std::u8string& path) {
|
|
try {
|
|
std::ofstream outputFile(std::filesystem::path(path), std::ios::binary);
|
|
Poco::Zip::Compress archive(outputFile, true);
|
|
Poco::MemoryInputStream inputStream(data.data(), size(data));
|
|
archive.addFile(inputStream, Poco::DateTime(), jsonDocumentName);
|
|
archive.close();
|
|
outputFile.close();
|
|
} catch (const Poco::Exception& /*error*/) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
std::optional<JSON> ReadFromFile(const std::u8string& path) {
|
|
namespace fs = std::filesystem;
|
|
auto tmpDirectory = fs::temp_directory_path() / "exteor" / fs::path(path).filename().replace_extension("");
|
|
std::ifstream inputFile(fs::path(path), std::ios::binary);
|
|
if (!inputFile) {
|
|
return std::nullopt;
|
|
}
|
|
try {
|
|
const auto u8folder = tmpDirectory.u8string();
|
|
const auto outputFolder = Poco::Path(std::string{ begin(u8folder), end(u8folder) });
|
|
Poco::Zip::Decompress(inputFile, outputFolder).decompressAllFiles();
|
|
inputFile.close();
|
|
} catch (const Poco::Exception& /*error*/) {
|
|
return std::nullopt;
|
|
}
|
|
|
|
std::ifstream jsonFile(tmpDirectory / jsonDocumentName);
|
|
if (!jsonFile) {
|
|
fs::remove_all(tmpDirectory);
|
|
return std::nullopt;
|
|
} else {
|
|
auto jsonData = JSON::parse(jsonFile);
|
|
jsonFile.close();
|
|
fs::remove_all(tmpDirectory);
|
|
return jsonData;
|
|
}
|
|
}
|
|
};
|
|
|
|
} // namespace xtr::io
|