memcard: update ryml parsing for folder memory cards

also make the file handling safer
This commit is contained in:
Tyler Wilding 2022-02-17 23:07:50 -05:00 committed by refractionpcsx2
parent 624dff1b96
commit ddfe6ac5c1
1 changed files with 27 additions and 23 deletions

View File

@ -37,14 +37,7 @@
bool RemoveDirectory(const wxString& dirname); bool RemoveDirectory(const wxString& dirname);
const ryml::Tree treeFromString(const std::string& s) ryml::Tree parseYamlStr(const std::string& str) {
{
return ryml::parse(c4::to_csubstr(s));
}
// A helper function to parse the YAML file
std::optional<ryml::Tree> loadYamlFile(const wxString& filePath)
{
ryml::Callbacks rymlCallbacks = ryml::get_callbacks(); ryml::Callbacks rymlCallbacks = ryml::get_callbacks();
rymlCallbacks.m_error = [](const char* msg, size_t msg_len, ryml::Location loc, void*) { rymlCallbacks.m_error = [](const char* msg, size_t msg_len, ryml::Location loc, void*) {
throw std::runtime_error(fmt::format("[YAML] Parsing error at {}:{} (bufpos={}): {}", throw std::runtime_error(fmt::format("[YAML] Parsing error at {}:{} (bufpos={}): {}",
@ -55,14 +48,29 @@ std::optional<ryml::Tree> loadYamlFile(const wxString& filePath)
throw std::runtime_error(fmt::format("[YAML] Internal Parsing error: {}", throw std::runtime_error(fmt::format("[YAML] Internal Parsing error: {}",
msg)); msg));
}); });
ryml::Tree tree = ryml::parse_in_arena(c4::to_csubstr(str));
ryml::reset_callbacks();
return tree;
}
// A helper function to parse the YAML file
std::optional<ryml::Tree> loadYamlFile(const wxString& filePath)
{
try try
{ {
std::optional<std::string> buffer = FileSystem::ReadFileToString(StringUtil::wxStringToUTF8String(filePath).c_str()); auto file = FileSystem::OpenManagedCFile(StringUtil::wxStringToUTF8String(filePath).c_str(), "rb");
if (!buffer.has_value()) if (!file)
{
return std::nullopt; return std::nullopt;
const ryml::Tree tree = treeFromString(buffer.value()); }
std::optional<std::string> buffer = FileSystem::ReadFileToString(file.get());
ryml::reset_callbacks(); std::fclose(file.get());
if (!buffer.has_value())
{
return std::nullopt;
}
ryml::Tree tree = parseYamlStr(buffer.value());
return std::make_optional(tree); return std::make_optional(tree);
} }
catch (const std::exception& e) catch (const std::exception& e)
@ -76,15 +84,10 @@ std::optional<ryml::Tree> loadYamlFile(const wxString& filePath)
/// A helper function to write a YAML file /// A helper function to write a YAML file
void SaveYAMLToFile(const wxString& filename, const ryml::NodeRef& node) void SaveYAMLToFile(const wxString& filename, const ryml::NodeRef& node)
{ {
wxFFile file; auto file = FileSystem::OpenCFile(StringUtil::wxStringToUTF8String(filename).c_str(), "w");
if (file.Open(filename, L"w")) ryml::emit(node, file);
{ std::fflush(file);
// Make sure WX doesn't do anything funny with encoding std::fclose(file);
std::stringstream ss;
ss << node;
std::string yaml = ss.str();
file.Write(yaml.data(), yaml.length());
}
} }
FolderMemoryCard::FolderMemoryCard() FolderMemoryCard::FolderMemoryCard()
@ -1282,7 +1285,7 @@ void FolderMemoryCard::FlushFileEntries(const u32 dirCluster, const u32 remainin
if (!yaml.has_value()) if (!yaml.has_value())
{ {
char initialData[] = "{$ROOT: {timeCreated: 0, timeModified: 0}}"; char initialData[] = "{$ROOT: {timeCreated: 0, timeModified: 0}}";
ryml::Tree newYaml = ryml::parse(ryml::substr(initialData)); ryml::Tree newYaml = ryml::parse_in_arena(c4::to_csubstr(initialData));
ryml::NodeRef newNode = newYaml.rootref()["$ROOT"]; ryml::NodeRef newNode = newYaml.rootref()["$ROOT"];
newNode["timeCreated"] << entry->entry.data.timeCreated.ToTime(); newNode["timeCreated"] << entry->entry.data.timeCreated.ToTime();
newNode["timeModified"] << entry->entry.data.timeModified.ToTime(); newNode["timeModified"] << entry->entry.data.timeModified.ToTime();
@ -1297,6 +1300,7 @@ void FolderMemoryCard::FlushFileEntries(const u32 dirCluster, const u32 remainin
// NOTE - working around a rapidyaml issue that needs to get resolved upstream // NOTE - working around a rapidyaml issue that needs to get resolved upstream
// '%' is a directive in YAML and it's not being quoted, this makes the memcards backwards compatible // '%' is a directive in YAML and it's not being quoted, this makes the memcards backwards compatible
// switched from '%' to '$' // switched from '%' to '$'
// NOTE - this issue has now been resolved, but should be preserved for backwards compatibility
entryNode = index["%ROOT"]; entryNode = index["%ROOT"];
entryNode.set_key("$ROOT"); entryNode.set_key("$ROOT");
} }