kaliber/src/engine/persistent_data.cc

105 lines
2.6 KiB
C++

#include "engine/persistent_data.h"
#include <memory>
#include "base/file.h"
#include "engine/engine.h"
#include "engine/platform/asset_file.h"
using namespace base;
namespace eng {
bool PersistentData::Load(const std::string& file_name, StorageType type) {
file_name_ = file_name;
type_ = type;
size_t size = 0;
std::unique_ptr<char[]> buffer;
if (type == kAsset) {
buffer = AssetFile::ReadWholeFile(file_name, Engine::Get().GetRootPath(),
&size, true);
} else {
std::string file_path = type == kShared ? Engine::Get().GetSharedDataPath()
: Engine::Get().GetDataPath();
file_path += file_name;
ScopedFILE file;
file.reset(fopen(file_path.c_str(), "r"));
if (!file) {
LOG << "Failed to open file " << file_path;
return false;
}
if (file) {
if (!fseek(file.get(), 0, SEEK_END)) {
size = ftell(file.get());
rewind(file.get());
}
}
buffer = std::make_unique<char[]>(size + 1);
size_t bytes_read = fread(buffer.get(), 1, size, file.get());
if (!bytes_read) {
LOG << "Failed to read a buffer of size: " << size << " from file "
<< file_path;
return false;
}
buffer[size] = 0;
}
std::string err;
Json::CharReaderBuilder builder;
const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
if (!reader->parse(buffer.get(), buffer.get() + size, &root_, &err)) {
LOG << "Failed to parse save file. Json parser error: " << err;
return false;
}
dirty_ = false;
return true;
}
bool PersistentData::Save(bool force) {
if (!force && !dirty_)
return true;
DCHECK(!file_name_.empty());
return SaveAs(file_name_, type_);
}
bool PersistentData::SaveAs(const std::string& file_name, StorageType type) {
DCHECK(type != kAsset);
file_name_ = file_name;
Json::StreamWriterBuilder builder;
std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
std::ostringstream stream;
writer->write(root_, &stream);
std::string file_path = type == kShared ? Engine::Get().GetSharedDataPath()
: Engine::Get().GetDataPath();
file_path += file_name;
ScopedFILE file;
file.reset(fopen(file_path.c_str(), "w"));
if (!file) {
LOG << "Failed to create file " << file_path;
return false;
}
std::string data = stream.str();
if (fwrite(data.c_str(), data.size(), 1, file.get()) != 1) {
LOG << "Failed to write to file " << file_path;
return false;
}
dirty_ = false;
return true;
}
} // namespace eng