File xenia_PR2250.patch of Package xenia

From 20f3ffbe134aa5594d0dac6ea97a5742f25a6f0d Mon Sep 17 00:00:00 2001
From: Gliniak <Gliniak93@gmail.com>
Date: Mon, 26 Feb 2024 09:30:54 +0100
Subject: [PATCH] [3PP] Replace cpptoml with tomlplusplus

---
 .gitmodules                                   |  6 +--
 premake5.lua                                  |  2 +-
 src/xenia/base/cvar.cc                        |  9 ++--
 src/xenia/base/cvar.h                         | 32 ++++++-------
 src/xenia/config.cc                           | 48 ++++++++-----------
 third_party/cpptoml                           |  1 -
 third_party/tomlplusplus                      |  1 +
 third_party/{cpptoml.lua => tomlplusplus.lua} |  4 +-
 8 files changed, 47 insertions(+), 56 deletions(-)
 create mode 160000 third_party/tomlplusplus
 rename third_party/{cpptoml.lua => tomlplusplus.lua} (78%)

diff --git a/.gitmodules b/.gitmodules
index c27065533d..ef1e15bf7b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -31,9 +31,9 @@
 [submodule "third_party/capstone"]
 	path = third_party/capstone
 	url = https://github.com/xenia-project/capstone.git
-[submodule "third_party/cpptoml"]
-	path = third_party/cpptoml
-	url = https://github.com/skystrife/cpptoml.git
+[submodule "third_party/tomlplusplus"]
+	path = third_party/tomlplusplus
+	url = https://github.com/marzer/tomlplusplus.git
 [submodule "third_party/cxxopts"]
 	path = third_party/cxxopts
 	url = https://github.com/jarro2783/cxxopts.git
diff --git a/premake5.lua b/premake5.lua
index 6739d6dba1..a4a720a83f 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -246,7 +246,7 @@ workspace("xenia")
   include("third_party/dxbc.lua")
   include("third_party/discord-rpc.lua")
   include("third_party/cxxopts.lua")
-  include("third_party/cpptoml.lua")
+  include("third_party/tomlplusplus.lua")
   include("third_party/FFmpeg/premake5.lua")
   include("third_party/fmt.lua")
   include("third_party/glslang-spirv.lua")
diff --git a/src/xenia/base/cvar.cc b/src/xenia/base/cvar.cc
index 219f033aea..d5d3685c45 100644
--- a/src/xenia/base/cvar.cc
+++ b/src/xenia/base/cvar.cc
@@ -101,7 +101,7 @@ void ParseLaunchArguments(int& argc, char**& argv,
   }
 }
 
-namespace toml {
+namespace toml_internal {
 
 std::string EscapeBasicString(const std::string_view view) {
   std::string result;
@@ -202,7 +202,7 @@ std::string EscapeString(const std::string_view view) {
     if (xe::utf8::find_any_of(view, escape_chars) == std::string_view::npos) {
       return "'" + std::string(view) + "'";
     } else {
-      return "\"" + toml::EscapeBasicString(view) + "\"";
+      return "\"" + toml_internal::EscapeBasicString(view) + "\"";
     }
   } else {
     // multi line
@@ -210,11 +210,12 @@ std::string EscapeString(const std::string_view view) {
         xe::utf8::find_first_of(view, u8"'''") == std::string_view::npos) {
       return "'''\n" + std::string(view) + "'''";
     } else {
-      return u8"\"\"\"\n" + toml::EscapeMultilineBasicString(view) + u8"\"\"\"";
+      return u8"\"\"\"\n" + toml_internal::EscapeMultilineBasicString(view) +
+             u8"\"\"\"";
     }
   }
 }
 
-}  // namespace toml
+}  // namespace toml_internal
 
 }  // namespace cvar
diff --git a/src/xenia/base/cvar.h b/src/xenia/base/cvar.h
index 61b8faf113..710efc5b39 100644
--- a/src/xenia/base/cvar.h
+++ b/src/xenia/base/cvar.h
@@ -15,9 +15,9 @@
 #include <string>
 #include <vector>
 
-#include "third_party/cpptoml/include/cpptoml.h"
 #include "third_party/cxxopts/include/cxxopts.hpp"
 #include "third_party/fmt/include/fmt/format.h"
+#include "third_party/tomlplusplus/include/toml++/toml.hpp"
 #include "xenia/base/assert.h"
 #include "xenia/base/filesystem.h"
 #include "xenia/base/platform.h"
@@ -29,7 +29,7 @@
 
 namespace cvar {
 
-namespace toml {
+namespace toml_internal {
 std::string EscapeString(const std::string_view str);
 }
 
@@ -48,8 +48,8 @@ class IConfigVar : virtual public ICommandVar {
   virtual const std::string& category() const = 0;
   virtual bool is_transient() const = 0;
   virtual std::string config_value() const = 0;
-  virtual void LoadConfigValue(std::shared_ptr<cpptoml::base> result) = 0;
-  virtual void LoadGameConfigValue(std::shared_ptr<cpptoml::base> result) = 0;
+  virtual void LoadConfigValue(const toml::node* result) = 0;
+  virtual void LoadGameConfigValue(const toml::node* result) = 0;
   virtual void ResetConfigValueToDefault() = 0;
 };
 
@@ -87,8 +87,8 @@ class ConfigVar : public CommandVar<T>, virtual public IConfigVar {
   const std::string& category() const override;
   bool is_transient() const override;
   void AddToLaunchOptions(cxxopts::Options* options) override;
-  void LoadConfigValue(std::shared_ptr<cpptoml::base> result) override;
-  void LoadGameConfigValue(std::shared_ptr<cpptoml::base> result) override;
+  void LoadConfigValue(const toml::node* result) override;
+  void LoadGameConfigValue(const toml::node* result) override;
   void SetConfigValue(T val);
   void SetGameConfigValue(T val);
   // Changes the actual value used to the one specified, and also makes it the
@@ -146,24 +146,24 @@ inline void CommandVar<std::filesystem::path>::LoadFromLaunchOptions(
   SetCommandLineValue(value);
 }
 template <class T>
-void ConfigVar<T>::LoadConfigValue(std::shared_ptr<cpptoml::base> result) {
-  SetConfigValue(*cpptoml::get_impl<T>(result));
+void ConfigVar<T>::LoadConfigValue(const toml::node* result) {
+  SetConfigValue(result->value<T>().value());
 }
 template <>
 inline void ConfigVar<std::filesystem::path>::LoadConfigValue(
-    std::shared_ptr<cpptoml::base> result) {
+    const toml::node* result) {
   SetConfigValue(
-      xe::utf8::fix_path_separators(*cpptoml::get_impl<std::string>(result)));
+      xe::utf8::fix_path_separators(result->as_string()->value_or("")));
 }
 template <class T>
-void ConfigVar<T>::LoadGameConfigValue(std::shared_ptr<cpptoml::base> result) {
-  SetGameConfigValue(*cpptoml::get_impl<T>(result));
+void ConfigVar<T>::LoadGameConfigValue(const toml::node* result) {
+  SetGameConfigValue(result->value<T>().value());
 }
 template <>
 inline void ConfigVar<std::filesystem::path>::LoadGameConfigValue(
-    std::shared_ptr<cpptoml::base> result) {
+    const toml::node* result) {
   SetGameConfigValue(
-      xe::utf8::fix_path_separators(*cpptoml::get_impl<std::string>(result)));
+      xe::utf8::fix_path_separators(result->as_string()->value_or("")));
 }
 template <class T>
 CommandVar<T>::CommandVar(const char* name, T* default_value,
@@ -215,12 +215,12 @@ inline std::string CommandVar<bool>::ToString(bool val) {
 }
 template <>
 inline std::string CommandVar<std::string>::ToString(std::string val) {
-  return toml::EscapeString(val);
+  return toml_internal::EscapeString(val);
 }
 template <>
 inline std::string CommandVar<std::filesystem::path>::ToString(
     std::filesystem::path val) {
-  return toml::EscapeString(
+  return toml_internal::EscapeString(
       xe::utf8::fix_path_separators(xe::path_to_utf8(val), '/'));
 }
 
diff --git a/src/xenia/config.cc b/src/xenia/config.cc
index dcdc5ac2b5..d3a641cde8 100644
--- a/src/xenia/config.cc
+++ b/src/xenia/config.cc
@@ -9,8 +9,8 @@
 
 #include "config.h"
 
-#include "third_party/cpptoml/include/cpptoml.h"
 #include "third_party/fmt/include/fmt/format.h"
+#include "third_party/tomlplusplus/include/toml++/toml.hpp"
 #include "xenia/base/assert.h"
 #include "xenia/base/cvar.h"
 #include "xenia/base/filesystem.h"
@@ -18,23 +18,8 @@
 #include "xenia/base/string.h"
 #include "xenia/base/string_buffer.h"
 
-std::shared_ptr<cpptoml::table> ParseFile(
-    const std::filesystem::path& filename) {
-  std::ifstream file(filename);
-  if (!file.is_open()) {
-    throw cpptoml::parse_exception(xe::path_to_utf8(filename) +
-                                   " could not be opened for parsing");
-  }
-  // since cpptoml can't parse files with a UTF-8 BOM we need to skip them
-  char bom[3];
-  file.read(bom, sizeof(bom));
-  if (file.fail() || bom[0] != '\xEF' || bom[1] != '\xBB' || bom[2] != '\xBF') {
-    file.clear();
-    file.seekg(0);
-  }
-
-  cpptoml::parser p(file);
-  return p.parse();
+toml::parse_result ParseFile(const std::filesystem::path& filename) {
+  return toml::parse_file(xe::path_to_utf8(filename));
 }
 
 CmdVar(config, "", "Specifies the target config to load.");
@@ -51,14 +36,13 @@ std::filesystem::path config_folder;
 std::filesystem::path config_path;
 std::string game_config_suffix = ".config.toml";
 
-std::shared_ptr<cpptoml::table> ParseConfig(
-    const std::filesystem::path& config_path) {
+toml::parse_result ParseConfig(const std::filesystem::path& config_path) {
   try {
     return ParseFile(config_path);
-  } catch (cpptoml::parse_exception e) {
+  } catch (toml::parse_error& e) {
     xe::FatalError(fmt::format("Failed to parse config file '{}':\n\n{}",
                                xe::path_to_utf8(config_path), e.what()));
-    return nullptr;
+    return toml::parse_result();
   }
 }
 
@@ -67,7 +51,7 @@ void ReadConfig(const std::filesystem::path& file_path,
   if (!cvar::ConfigVars) {
     return;
   }
-  const auto config = ParseConfig(file_path);
+  const toml::table config = ParseConfig(file_path);
   // Loading an actual global config file that exists - if there's no
   // defaults_date in it, it's very old (before updating was added at all, thus
   // all defaults need to be updated).
@@ -77,9 +61,12 @@ void ReadConfig(const std::filesystem::path& file_path,
   defaults_date_cvar->SetConfigValue(0);
   for (auto& it : *cvar::ConfigVars) {
     auto config_var = static_cast<cvar::IConfigVar*>(it.second);
-    auto config_key = config_var->category() + "." + config_var->name();
-    if (config->contains_qualified(config_key)) {
-      config_var->LoadConfigValue(config->get_qualified(config_key));
+    toml::path config_key =
+        toml::path(config_var->category() + "." + config_var->name());
+
+    const auto config_key_node = config.at_path(config_key);
+    if (config_key_node) {
+      config_var->LoadConfigValue(config_key_node.node());
     }
   }
   uint32_t config_defaults_date = defaults_date_cvar->GetTypedConfigValue();
@@ -96,9 +83,12 @@ void ReadGameConfig(const std::filesystem::path& file_path) {
   const auto config = ParseConfig(file_path);
   for (auto& it : *cvar::ConfigVars) {
     auto config_var = static_cast<cvar::IConfigVar*>(it.second);
-    auto config_key = config_var->category() + "." + config_var->name();
-    if (config->contains_qualified(config_key)) {
-      config_var->LoadGameConfigValue(config->get_qualified(config_key));
+    toml::path config_key =
+        toml::path(config_var->category() + "." + config_var->name());
+
+    const auto config_key_node = config.at_path(config_key);
+    if (config_key_node) {
+      config_var->LoadConfigValue(config_key_node.node());
     }
   }
   XELOGI("Loaded game config: {}", xe::path_to_utf8(file_path));
diff --git a/third_party/tomlplusplus b/third_party/tomlplusplus
new file mode 160000
index 0000000000..30172438ce
--- /dev/null
+++ b/third_party/tomlplusplus
@@ -0,0 +1 @@
+Subproject commit 30172438cee64926dc41fdd9c11fb3ba5b2ba9de
diff --git a/third_party/cpptoml.lua b/third_party/tomlplusplus.lua
similarity index 78%
rename from third_party/cpptoml.lua
rename to third_party/tomlplusplus.lua
index 5e7d6d74a5..25860b01c5 100644
--- a/third_party/cpptoml.lua
+++ b/third_party/tomlplusplus.lua
@@ -1,5 +1,5 @@
 group("third_party")
-project("cpptoml")
+project("tomlplusplus")
   uuid("1e86cc51-3f8b-476d-9249-3b200424846b")
   if os.istarget("android") then
     -- ndk-build only supports StaticLib and SharedLib.
@@ -9,5 +9,5 @@ project("cpptoml")
   end
   language("C++")
   files({
-    "cpptoml/include/cpptoml.h",
+    "tomlplusplus/include/toml++/toml.hpp"
   })
openSUSE Build Service is sponsored by