diff options
| author | Stefan Boberg <[email protected]> | 2023-10-06 10:45:48 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-10-06 10:45:48 +0200 |
| commit | fb70324d37282910d7fa3047f4ec290d0c5a94b1 (patch) | |
| tree | a1bc82fcfdb96eb5b461742b613fcbb63f816a54 /src/zenserver/config.cpp | |
| parent | reject known bad bucket names in structured cache (#452) (diff) | |
| download | zen-fb70324d37282910d7fa3047f4ec290d0c5a94b1.tar.xz zen-fb70324d37282910d7fa3047f4ec290d0c5a94b1.zip | |
zenserver project restructuring (#442)
Diffstat (limited to 'src/zenserver/config.cpp')
| -rw-r--r-- | src/zenserver/config.cpp | 894 |
1 files changed, 441 insertions, 453 deletions
diff --git a/src/zenserver/config.cpp b/src/zenserver/config.cpp index b7699900f..435b66a83 100644 --- a/src/zenserver/config.cpp +++ b/src/zenserver/config.cpp @@ -32,6 +32,8 @@ ZEN_THIRD_PARTY_INCLUDES_END # pragma comment(lib, "shell32.lib") # pragma comment(lib, "ole32.lib") +namespace zen { + std::filesystem::path PickDefaultStateDirectory() { @@ -51,8 +53,12 @@ PickDefaultStateDirectory() return L""; } +} // namespace zen + #else +namespace zen { + std::filesystem::path PickDefaultStateDirectory() { @@ -61,8 +67,12 @@ PickDefaultStateDirectory() return std::filesystem::path(Passwd->pw_dir) / ".zen"; } +} // namespace zen + #endif +namespace zen { + void ValidateOptions(ZenServerOptions& ServerOptions) { @@ -159,409 +169,385 @@ MakeSafePath(const std::string_view Path) namespace LuaConfig { -void -EscapeBackslash(std::string& InOutString) -{ - std::size_t BackslashPos = InOutString.find('\\'); - if (BackslashPos != std::string::npos) + void EscapeBackslash(std::string& InOutString) { - std::size_t Offset = 0; - zen::ExtendableStringBuilder<512> PathBuilder; - while (BackslashPos != std::string::npos) + std::size_t BackslashPos = InOutString.find('\\'); + if (BackslashPos != std::string::npos) { - PathBuilder.Append(InOutString.substr(Offset, BackslashPos + 1 - Offset)); - PathBuilder.Append('\\'); - Offset = BackslashPos + 1; - BackslashPos = InOutString.find('\\', Offset); + std::size_t Offset = 0; + zen::ExtendableStringBuilder<512> PathBuilder; + while (BackslashPos != std::string::npos) + { + PathBuilder.Append(InOutString.substr(Offset, BackslashPos + 1 - Offset)); + PathBuilder.Append('\\'); + Offset = BackslashPos + 1; + BackslashPos = InOutString.find('\\', Offset); + } + PathBuilder.Append(InOutString.substr(Offset, BackslashPos)); + InOutString = PathBuilder.ToString(); } - PathBuilder.Append(InOutString.substr(Offset, BackslashPos)); - InOutString = PathBuilder.ToString(); } -} -class OptionValue -{ -public: - virtual void Print(std::string_view Indent, zen::StringBuilderBase& StringBuilder) = 0; - virtual void Parse(sol::object Object) = 0; + class OptionValue + { + public: + virtual void Print(std::string_view Indent, zen::StringBuilderBase& StringBuilder) = 0; + virtual void Parse(sol::object Object) = 0; - virtual ~OptionValue() {} -}; + virtual ~OptionValue() {} + }; -typedef std::shared_ptr<OptionValue> TOptionValue; + typedef std::shared_ptr<OptionValue> TOptionValue; -class StringOption : public OptionValue -{ -public: - StringOption(std::string& Value) : Value(Value) {} - virtual void Print(std::string_view, zen::StringBuilderBase& StringBuilder) override + class StringOption : public OptionValue { - StringBuilder.Append(fmt::format("\"{}\"", Value)); - } - virtual void Parse(sol::object Object) override { Value = Object.as<std::string>(); } - std::string& Value; -}; - -class FilePathOption : public OptionValue -{ -public: - FilePathOption(std::filesystem::path& Value) : Value(Value) {} - virtual void Print(std::string_view, zen::StringBuilderBase& StringBuilder) override - { - std::string Path = Value.string(); - EscapeBackslash(Path); - StringBuilder.Append(fmt::format("\"{}\"", Path)); - } - virtual void Parse(sol::object Object) override - { - std::string Str = Object.as<std::string>(); - if (!Str.empty()) + public: + StringOption(std::string& Value) : Value(Value) {} + virtual void Print(std::string_view, zen::StringBuilderBase& StringBuilder) override { - Value = MakeSafePath(Str); + StringBuilder.Append(fmt::format("\"{}\"", Value)); } - } - std::filesystem::path& Value; -}; - -class BoolOption : public OptionValue -{ -public: - BoolOption(bool& Value) : Value(Value) {} - virtual void Print(std::string_view, zen::StringBuilderBase& StringBuilder) override { StringBuilder.Append(Value ? "true" : "false"); } - virtual void Parse(sol::object Object) override { Value = Object.as<bool>(); } - bool& Value; -}; + virtual void Parse(sol::object Object) override { Value = Object.as<std::string>(); } + std::string& Value; + }; -class CachePolicyOption : public OptionValue -{ -public: - CachePolicyOption(UpstreamCachePolicy& Value) : Value(Value) {} - virtual void Print(std::string_view, zen::StringBuilderBase& StringBuilder) override + class FilePathOption : public OptionValue { - switch (Value) + public: + FilePathOption(std::filesystem::path& Value) : Value(Value) {} + virtual void Print(std::string_view, zen::StringBuilderBase& StringBuilder) override { - case UpstreamCachePolicy::Read: - StringBuilder.Append("readonly"); - break; - case UpstreamCachePolicy::Write: - StringBuilder.Append("writeonly"); - break; - case UpstreamCachePolicy::Disabled: - StringBuilder.Append("disabled"); - break; - case UpstreamCachePolicy::ReadWrite: - StringBuilder.Append("readwrite"); - break; - default: - ZEN_ASSERT(false); + std::string Path = Value.string(); + EscapeBackslash(Path); + StringBuilder.Append(fmt::format("\"{}\"", Path)); } - } - virtual void Parse(sol::object Object) override - { - std::string PolicyString = Object.as<std::string>(); - if (PolicyString == "readonly") + virtual void Parse(sol::object Object) override { - Value = UpstreamCachePolicy::Read; + std::string Str = Object.as<std::string>(); + if (!Str.empty()) + { + Value = MakeSafePath(Str); + } } - else if (PolicyString == "writeonly") + std::filesystem::path& Value; + }; + + class BoolOption : public OptionValue + { + public: + BoolOption(bool& Value) : Value(Value) {} + virtual void Print(std::string_view, zen::StringBuilderBase& StringBuilder) override { - Value = UpstreamCachePolicy::Write; + StringBuilder.Append(Value ? "true" : "false"); } - else if (PolicyString == "disabled") + virtual void Parse(sol::object Object) override { Value = Object.as<bool>(); } + bool& Value; + }; + + class CachePolicyOption : public OptionValue + { + public: + CachePolicyOption(UpstreamCachePolicy& Value) : Value(Value) {} + virtual void Print(std::string_view, zen::StringBuilderBase& StringBuilder) override { - Value = UpstreamCachePolicy::Disabled; + switch (Value) + { + case UpstreamCachePolicy::Read: + StringBuilder.Append("readonly"); + break; + case UpstreamCachePolicy::Write: + StringBuilder.Append("writeonly"); + break; + case UpstreamCachePolicy::Disabled: + StringBuilder.Append("disabled"); + break; + case UpstreamCachePolicy::ReadWrite: + StringBuilder.Append("readwrite"); + break; + default: + ZEN_ASSERT(false); + } } - else if (PolicyString == "readwrite") + virtual void Parse(sol::object Object) override { - Value = UpstreamCachePolicy::ReadWrite; + std::string PolicyString = Object.as<std::string>(); + if (PolicyString == "readonly") + { + Value = UpstreamCachePolicy::Read; + } + else if (PolicyString == "writeonly") + { + Value = UpstreamCachePolicy::Write; + } + else if (PolicyString == "disabled") + { + Value = UpstreamCachePolicy::Disabled; + } + else if (PolicyString == "readwrite") + { + Value = UpstreamCachePolicy::ReadWrite; + } } - } - UpstreamCachePolicy& Value; -}; - -template<Integral T> -class NumberOption : public OptionValue -{ -public: - NumberOption(T& Value) : Value(Value) {} - virtual void Print(std::string_view, zen::StringBuilderBase& StringBuilder) override { StringBuilder.Append(fmt::format("{}", Value)); } - virtual void Parse(sol::object Object) override { Value = Object.as<T>(); } - T& Value; -}; - -class LuaContainerWriter -{ -public: - LuaContainerWriter(zen::StringBuilderBase& StringBuilder, std::string_view Indent) - : StringBuilder(StringBuilder) - , InitialIndent(Indent.length()) - , LocalIndent(Indent) - { - StringBuilder.Append("{\n"); - LocalIndent.push_back('\t'); - } - ~LuaContainerWriter() - { - LocalIndent.pop_back(); - StringBuilder.Append(LocalIndent); - StringBuilder.Append("}"); - } + UpstreamCachePolicy& Value; + }; - void BeginContainer(std::string_view Name) + template<Integral T> + class NumberOption : public OptionValue { - StringBuilder.Append(LocalIndent); - if (!Name.empty()) - { - StringBuilder.Append(Name); - StringBuilder.Append(" = {\n"); - } - else + public: + NumberOption(T& Value) : Value(Value) {} + virtual void Print(std::string_view, zen::StringBuilderBase& StringBuilder) override { - StringBuilder.Append("{\n"); + StringBuilder.Append(fmt::format("{}", Value)); } - LocalIndent.push_back('\t'); - } - void WriteValue(std::string_view Name, std::string_view Value) + virtual void Parse(sol::object Object) override { Value = Object.as<T>(); } + T& Value; + }; + + class LuaContainerWriter { - if (Name.empty()) + public: + LuaContainerWriter(zen::StringBuilderBase& StringBuilder, std::string_view Indent) + : StringBuilder(StringBuilder) + , InitialIndent(Indent.length()) + , LocalIndent(Indent) { - StringBuilder.Append(fmt::format("{}\"{}\",\n", LocalIndent, Value)); + StringBuilder.Append("{\n"); + LocalIndent.push_back('\t'); } - else + ~LuaContainerWriter() { - StringBuilder.Append(fmt::format("{}{} = \"{}\",\n", LocalIndent, Name, Value)); + LocalIndent.pop_back(); + StringBuilder.Append(LocalIndent); + StringBuilder.Append("}"); } - } - void EndContainer() - { - LocalIndent.pop_back(); - StringBuilder.Append(LocalIndent); - StringBuilder.Append("}"); - StringBuilder.Append(",\n"); - } -private: - zen::StringBuilderBase& StringBuilder; - const std::size_t InitialIndent; - std::string LocalIndent; -}; - -class StringArrayOption : public OptionValue -{ -public: - StringArrayOption(std::vector<std::string>& Value) : Value(Value) {} - virtual void Print(std::string_view Indent, zen::StringBuilderBase& StringBuilder) override - { - if (Value.empty()) + void BeginContainer(std::string_view Name) { - StringBuilder.Append("{}"); - } - if (Value.size() == 1) - { - StringBuilder.Append(fmt::format("\"{}\"", Value[0])); + StringBuilder.Append(LocalIndent); + if (!Name.empty()) + { + StringBuilder.Append(Name); + StringBuilder.Append(" = {\n"); + } + else + { + StringBuilder.Append("{\n"); + } + LocalIndent.push_back('\t'); } - else + void WriteValue(std::string_view Name, std::string_view Value) { - LuaContainerWriter Writer(StringBuilder, Indent); - for (std::string String : Value) + if (Name.empty()) + { + StringBuilder.Append(fmt::format("{}\"{}\",\n", LocalIndent, Value)); + } + else { - Writer.WriteValue("", String); + StringBuilder.Append(fmt::format("{}{} = \"{}\",\n", LocalIndent, Name, Value)); } } - } - virtual void Parse(sol::object Object) override + void EndContainer() + { + LocalIndent.pop_back(); + StringBuilder.Append(LocalIndent); + StringBuilder.Append("}"); + StringBuilder.Append(",\n"); + } + + private: + zen::StringBuilderBase& StringBuilder; + const std::size_t InitialIndent; + std::string LocalIndent; + }; + + class StringArrayOption : public OptionValue { - if (Object.get_type() == sol::type::string) + public: + StringArrayOption(std::vector<std::string>& Value) : Value(Value) {} + virtual void Print(std::string_view Indent, zen::StringBuilderBase& StringBuilder) override { - Value.push_back(Object.as<std::string>()); + if (Value.empty()) + { + StringBuilder.Append("{}"); + } + if (Value.size() == 1) + { + StringBuilder.Append(fmt::format("\"{}\"", Value[0])); + } + else + { + LuaContainerWriter Writer(StringBuilder, Indent); + for (std::string String : Value) + { + Writer.WriteValue("", String); + } + } } - else if (Object.get_type() == sol::type::table) + virtual void Parse(sol::object Object) override { - for (const auto& Kv : Object.as<sol::table>()) + if (Object.get_type() == sol::type::string) { - Value.push_back(Kv.second.as<std::string>()); + Value.push_back(Object.as<std::string>()); + } + else if (Object.get_type() == sol::type::table) + { + for (const auto& Kv : Object.as<sol::table>()) + { + Value.push_back(Kv.second.as<std::string>()); + } } } - } -private: - std::vector<std::string>& Value; -}; + private: + std::vector<std::string>& Value; + }; -class ZenAuthConfigOption : public OptionValue -{ -public: - ZenAuthConfigOption(ZenAuthConfig& Value) : Value(Value) {} - virtual void Print(std::string_view Indent, zen::StringBuilderBase& StringBuilder) override + class ZenAuthConfigOption : public OptionValue { - if (Value.OpenIdProviders.empty()) + public: + ZenAuthConfigOption(ZenAuthConfig& Value) : Value(Value) {} + virtual void Print(std::string_view Indent, zen::StringBuilderBase& StringBuilder) override { - StringBuilder.Append("{}"); - return; - } - LuaContainerWriter Writer(StringBuilder, Indent); - for (const ZenOpenIdProviderConfig& Config : Value.OpenIdProviders) - { - Writer.BeginContainer(""); + if (Value.OpenIdProviders.empty()) { - Writer.WriteValue("name", Config.Name); - Writer.WriteValue("url", Config.Url); - Writer.WriteValue("clientid", Config.ClientId); + StringBuilder.Append("{}"); + return; + } + LuaContainerWriter Writer(StringBuilder, Indent); + for (const ZenOpenIdProviderConfig& Config : Value.OpenIdProviders) + { + Writer.BeginContainer(""); + { + Writer.WriteValue("name", Config.Name); + Writer.WriteValue("url", Config.Url); + Writer.WriteValue("clientid", Config.ClientId); + } + Writer.EndContainer(); } - Writer.EndContainer(); } - } - virtual void Parse(sol::object Object) override - { - if (sol::optional<sol::table> OpenIdProviders = Object.as<sol::table>()) + virtual void Parse(sol::object Object) override { - for (const auto& Kv : OpenIdProviders.value()) + if (sol::optional<sol::table> OpenIdProviders = Object.as<sol::table>()) { - if (sol::optional<sol::table> OpenIdProvider = Kv.second.as<sol::table>()) + for (const auto& Kv : OpenIdProviders.value()) { - std::string Name = OpenIdProvider.value().get_or("name", std::string("Default")); - std::string Url = OpenIdProvider.value().get_or("url", std::string()); - std::string ClientId = OpenIdProvider.value().get_or("clientid", std::string()); + if (sol::optional<sol::table> OpenIdProvider = Kv.second.as<sol::table>()) + { + std::string Name = OpenIdProvider.value().get_or("name", std::string("Default")); + std::string Url = OpenIdProvider.value().get_or("url", std::string()); + std::string ClientId = OpenIdProvider.value().get_or("clientid", std::string()); - Value.OpenIdProviders.push_back({.Name = std::move(Name), .Url = std::move(Url), .ClientId = std::move(ClientId)}); + Value.OpenIdProviders.push_back({.Name = std::move(Name), .Url = std::move(Url), .ClientId = std::move(ClientId)}); + } } } } - } - ZenAuthConfig& Value; -}; + ZenAuthConfig& Value; + }; -class ZenObjectStoreConfigOption : public OptionValue -{ -public: - ZenObjectStoreConfigOption(ZenObjectStoreConfig& Value) : Value(Value) {} - virtual void Print(std::string_view Indent, zen::StringBuilderBase& StringBuilder) override + class ZenObjectStoreConfigOption : public OptionValue { - if (Value.Buckets.empty()) + public: + ZenObjectStoreConfigOption(ZenObjectStoreConfig& Value) : Value(Value) {} + virtual void Print(std::string_view Indent, zen::StringBuilderBase& StringBuilder) override { - StringBuilder.Append("{}"); - return; - } - LuaContainerWriter Writer(StringBuilder, Indent); - for (const ZenObjectStoreConfig::BucketConfig& Config : Value.Buckets) - { - Writer.BeginContainer(""); + if (Value.Buckets.empty()) { - Writer.WriteValue("name", Config.Name); - std::string Directory = Config.Directory.string(); - EscapeBackslash(Directory); - Writer.WriteValue("directory", Directory); + StringBuilder.Append("{}"); + return; + } + LuaContainerWriter Writer(StringBuilder, Indent); + for (const ZenObjectStoreConfig::BucketConfig& Config : Value.Buckets) + { + Writer.BeginContainer(""); + { + Writer.WriteValue("name", Config.Name); + std::string Directory = Config.Directory.string(); + EscapeBackslash(Directory); + Writer.WriteValue("directory", Directory); + } + Writer.EndContainer(); } - Writer.EndContainer(); } - } - virtual void Parse(sol::object Object) override - { - if (sol::optional<sol::table> Buckets = Object.as<sol::table>()) + virtual void Parse(sol::object Object) override { - for (const auto& Kv : Buckets.value()) + if (sol::optional<sol::table> Buckets = Object.as<sol::table>()) { - if (sol::optional<sol::table> Bucket = Kv.second.as<sol::table>()) + for (const auto& Kv : Buckets.value()) { - std::string Name = Bucket.value().get_or("name", std::string("Default")); - std::string Directory = Bucket.value().get_or("directory", std::string()); + if (sol::optional<sol::table> Bucket = Kv.second.as<sol::table>()) + { + std::string Name = Bucket.value().get_or("name", std::string("Default")); + std::string Directory = Bucket.value().get_or("directory", std::string()); - Value.Buckets.push_back({.Name = std::move(Name), .Directory = MakeSafePath(Directory)}); + Value.Buckets.push_back({.Name = std::move(Name), .Directory = MakeSafePath(Directory)}); + } } } } - } - ZenObjectStoreConfig& Value; -}; - -std::shared_ptr<OptionValue> -MakeOption(std::string& Value) -{ - return std::make_shared<StringOption>(Value); -}; + ZenObjectStoreConfig& Value; + }; -std::shared_ptr<OptionValue> -MakeOption(std::filesystem::path& Value) -{ - return std::make_shared<FilePathOption>(Value); -}; + std::shared_ptr<OptionValue> MakeOption(std::string& Value) { return std::make_shared<StringOption>(Value); }; -template<Integral T> -std::shared_ptr<OptionValue> -MakeOption(T& Value) -{ - return std::make_shared<NumberOption<T>>(Value); -}; + std::shared_ptr<OptionValue> MakeOption(std::filesystem::path& Value) { return std::make_shared<FilePathOption>(Value); }; -std::shared_ptr<OptionValue> -MakeOption(bool& Value) -{ - return std::make_shared<BoolOption>(Value); -}; + template<Integral T> + std::shared_ptr<OptionValue> MakeOption(T& Value) + { + return std::make_shared<NumberOption<T>>(Value); + }; -std::shared_ptr<OptionValue> -MakeOption(UpstreamCachePolicy& Value) -{ - return std::make_shared<CachePolicyOption>(Value); -}; + std::shared_ptr<OptionValue> MakeOption(bool& Value) { return std::make_shared<BoolOption>(Value); }; -std::shared_ptr<OptionValue> -MakeOption(std::vector<std::string>& Value) -{ - return std::make_shared<StringArrayOption>(Value); -}; + std::shared_ptr<OptionValue> MakeOption(UpstreamCachePolicy& Value) { return std::make_shared<CachePolicyOption>(Value); }; -std::shared_ptr<OptionValue> -MakeOption(ZenAuthConfig& Value) -{ - return std::make_shared<ZenAuthConfigOption>(Value); -}; + std::shared_ptr<OptionValue> MakeOption(std::vector<std::string>& Value) { return std::make_shared<StringArrayOption>(Value); }; -std::shared_ptr<OptionValue> -MakeOption(ZenObjectStoreConfig& Value) -{ - return std::make_shared<ZenObjectStoreConfigOption>(Value); -}; + std::shared_ptr<OptionValue> MakeOption(ZenAuthConfig& Value) { return std::make_shared<ZenAuthConfigOption>(Value); }; -struct Option -{ - std::string CommandLineOptionName; - TOptionValue Value; -}; + std::shared_ptr<OptionValue> MakeOption(ZenObjectStoreConfig& Value) { return std::make_shared<ZenObjectStoreConfigOption>(Value); }; -struct Options -{ -public: - template<typename T> - void AddOption(std::string_view Key, T& Value, std::string_view CommandLineOptionName = "") + struct Option { - OptionMap.insert_or_assign(std::string(Key), - Option{.CommandLineOptionName = std::string(CommandLineOptionName), .Value = MakeOption(Value)}); + std::string CommandLineOptionName; + TOptionValue Value; }; - void Parse(const std::filesystem::path& Path, const cxxopts::ParseResult& CmdLineResult) + struct Options { - zen::IoBuffer LuaScript = zen::IoBufferBuilder::MakeFromFile(Path); + public: + template<typename T> + void AddOption(std::string_view Key, T& Value, std::string_view CommandLineOptionName = "") + { + OptionMap.insert_or_assign(std::string(Key), + Option{.CommandLineOptionName = std::string(CommandLineOptionName), .Value = MakeOption(Value)}); + }; - if (LuaScript) + void Parse(const std::filesystem::path& Path, const cxxopts::ParseResult& CmdLineResult) { - sol::state lua; + zen::IoBuffer LuaScript = zen::IoBufferBuilder::MakeFromFile(Path); + + if (LuaScript) + { + sol::state lua; - lua.open_libraries(sol::lib::base); + lua.open_libraries(sol::lib::base); - lua.set_function("getenv", [&](const std::string env) -> sol::object { + lua.set_function("getenv", [&](const std::string env) -> sol::object { #if ZEN_PLATFORM_WINDOWS - std::wstring EnvVarValue; - size_t RequiredSize = 0; - std::wstring EnvWide = zen::Utf8ToWide(env); - _wgetenv_s(&RequiredSize, nullptr, 0, EnvWide.c_str()); + std::wstring EnvVarValue; + size_t RequiredSize = 0; + std::wstring EnvWide = zen::Utf8ToWide(env); + _wgetenv_s(&RequiredSize, nullptr, 0, EnvWide.c_str()); - if (RequiredSize == 0) - return sol::make_object(lua, sol::lua_nil); + if (RequiredSize == 0) + return sol::make_object(lua, sol::lua_nil); - EnvVarValue.resize(RequiredSize); - _wgetenv_s(&RequiredSize, EnvVarValue.data(), RequiredSize, EnvWide.c_str()); - return sol::make_object(lua, zen::WideToUtf8(EnvVarValue.c_str())); + EnvVarValue.resize(RequiredSize); + _wgetenv_s(&RequiredSize, EnvVarValue.data(), RequiredSize, EnvWide.c_str()); + return sol::make_object(lua, zen::WideToUtf8(EnvVarValue.c_str())); #elif ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC char* EnvVariable = getenv(env.c_str()); if (EnvVariable == nullptr) @@ -573,198 +559,198 @@ public: ZEN_UNUSED(env); return sol::make_object(lua, sol::lua_nil); #endif - }); + }); - try - { - sol::load_result config = lua.load(std::string_view((const char*)LuaScript.Data(), LuaScript.Size()), "zen_cfg"); - - if (!config.valid()) + try { - sol::error err = config; + sol::load_result config = lua.load(std::string_view((const char*)LuaScript.Data(), LuaScript.Size()), "zen_cfg"); + + if (!config.valid()) + { + sol::error err = config; + + std::string ErrorString = sol::to_string(config.status()); - std::string ErrorString = sol::to_string(config.status()); + throw std::runtime_error(fmt::format("{} error: {}", ErrorString, err.what())); + } - throw std::runtime_error(fmt::format("{} error: {}", ErrorString, err.what())); + config(); + } + catch (std::exception& e) + { + throw std::runtime_error(fmt::format("failed to load config script ('{}'): {}", Path, e.what()).c_str()); } - config(); - } - catch (std::exception& e) - { - throw std::runtime_error(fmt::format("failed to load config script ('{}'): {}", Path, e.what()).c_str()); + Parse(lua, CmdLineResult); } - - Parse(lua, CmdLineResult); } - } - void Parse(const sol::state& LuaState, const cxxopts::ParseResult& CmdLineResult) - { - for (auto It : LuaState) + void Parse(const sol::state& LuaState, const cxxopts::ParseResult& CmdLineResult) { - sol::object Key = It.first; - sol::type KeyType = Key.get_type(); - if (KeyType == sol::type::string) + for (auto It : LuaState) { - sol::type ValueType = It.second.get_type(); - switch (ValueType) + sol::object Key = It.first; + sol::type KeyType = Key.get_type(); + if (KeyType == sol::type::string) { - case sol::type::table: - { - std::string Name = Key.as<std::string>(); - if (Name.starts_with("_")) - { - continue; - } - if (Name == "base") + sol::type ValueType = It.second.get_type(); + switch (ValueType) + { + case sol::type::table: { - continue; + std::string Name = Key.as<std::string>(); + if (Name.starts_with("_")) + { + continue; + } + if (Name == "base") + { + continue; + } + Traverse(It.second.as<sol::table>(), Name, CmdLineResult); } - Traverse(It.second.as<sol::table>(), Name, CmdLineResult); - } - break; - default: - break; + break; + default: + break; + } } } } - } - void Touch(std::string_view Key) { UsedKeys.insert(std::string(Key)); } + void Touch(std::string_view Key) { UsedKeys.insert(std::string(Key)); } - void Print(zen::StringBuilderBase& SB, const cxxopts::ParseResult& CmdLineResult) - { - for (auto It : OptionMap) + void Print(zen::StringBuilderBase& SB, const cxxopts::ParseResult& CmdLineResult) { - if (CmdLineResult.count(It.second.CommandLineOptionName) != 0) + for (auto It : OptionMap) { - UsedKeys.insert(It.first); + if (CmdLineResult.count(It.second.CommandLineOptionName) != 0) + { + UsedKeys.insert(It.first); + } } - } - std::vector<std::string> SortedKeys(UsedKeys.begin(), UsedKeys.end()); - std::sort(SortedKeys.begin(), SortedKeys.end()); - auto GetTablePath = [](const std::string& Key) -> std::vector<std::string> { - std::vector<std::string> Path; - zen::ForEachStrTok(Key, '.', [&Path](std::string_view Part) { - Path.push_back(std::string(Part)); - return true; - }); - return Path; - }; - std::vector<std::string> CurrentTablePath; - std::string Indent; - auto It = SortedKeys.begin(); - for (const std::string& Key : SortedKeys) - { - std::vector<std::string> KeyPath = GetTablePath(Key); - std::string Name = KeyPath.back(); - KeyPath.pop_back(); - if (CurrentTablePath != KeyPath) + std::vector<std::string> SortedKeys(UsedKeys.begin(), UsedKeys.end()); + std::sort(SortedKeys.begin(), SortedKeys.end()); + auto GetTablePath = [](const std::string& Key) -> std::vector<std::string> { + std::vector<std::string> Path; + zen::ForEachStrTok(Key, '.', [&Path](std::string_view Part) { + Path.push_back(std::string(Part)); + return true; + }); + return Path; + }; + std::vector<std::string> CurrentTablePath; + std::string Indent; + auto It = SortedKeys.begin(); + for (const std::string& Key : SortedKeys) { - size_t EqualCount = 0; - while (EqualCount < CurrentTablePath.size() && EqualCount < KeyPath.size() && - CurrentTablePath[EqualCount] == KeyPath[EqualCount]) - { - EqualCount++; - } - while (CurrentTablePath.size() > EqualCount) + std::vector<std::string> KeyPath = GetTablePath(Key); + std::string Name = KeyPath.back(); + KeyPath.pop_back(); + if (CurrentTablePath != KeyPath) { - CurrentTablePath.pop_back(); - Indent.pop_back(); - SB.Append(Indent); - SB.Append("}"); - if (CurrentTablePath.size() == EqualCount && !Indent.empty() && KeyPath.size() >= EqualCount) + size_t EqualCount = 0; + while (EqualCount < CurrentTablePath.size() && EqualCount < KeyPath.size() && + CurrentTablePath[EqualCount] == KeyPath[EqualCount]) { - SB.Append(","); + EqualCount++; } - SB.Append("\n"); - if (Indent.empty()) + while (CurrentTablePath.size() > EqualCount) { + CurrentTablePath.pop_back(); + Indent.pop_back(); + SB.Append(Indent); + SB.Append("}"); + if (CurrentTablePath.size() == EqualCount && !Indent.empty() && KeyPath.size() >= EqualCount) + { + SB.Append(","); + } SB.Append("\n"); + if (Indent.empty()) + { + SB.Append("\n"); + } + } + while (EqualCount < KeyPath.size()) + { + SB.Append(Indent); + SB.Append(KeyPath[EqualCount]); + SB.Append(" = {\n"); + Indent.push_back('\t'); + CurrentTablePath.push_back(KeyPath[EqualCount]); + EqualCount++; } } - while (EqualCount < KeyPath.size()) - { - SB.Append(Indent); - SB.Append(KeyPath[EqualCount]); - SB.Append(" = {\n"); - Indent.push_back('\t'); - CurrentTablePath.push_back(KeyPath[EqualCount]); - EqualCount++; - } - } - SB.Append(Indent); - SB.Append(Name); - SB.Append(" = "); - OptionMap[Key].Value->Print(Indent, SB); - SB.Append(",\n"); - } - while (!CurrentTablePath.empty()) - { - Indent.pop_back(); - SB.Append(Indent); - SB.Append("}\n"); - CurrentTablePath.pop_back(); + SB.Append(Indent); + SB.Append(Name); + SB.Append(" = "); + OptionMap[Key].Value->Print(Indent, SB); + SB.Append(",\n"); + } + while (!CurrentTablePath.empty()) + { + Indent.pop_back(); + SB.Append(Indent); + SB.Append("}\n"); + CurrentTablePath.pop_back(); + } } - } -private: - void Traverse(sol::table Table, std::string_view PathPrefix, const cxxopts::ParseResult& CmdLineResult) - { - for (auto It : Table) + private: + void Traverse(sol::table Table, std::string_view PathPrefix, const cxxopts::ParseResult& CmdLineResult) { - sol::object Key = It.first; - sol::type KeyType = Key.get_type(); - if (KeyType == sol::type::string || KeyType == sol::type::number) + for (auto It : Table) { - sol::type ValueType = It.second.get_type(); - switch (ValueType) + sol::object Key = It.first; + sol::type KeyType = Key.get_type(); + if (KeyType == sol::type::string || KeyType == sol::type::number) { - case sol::type::table: - case sol::type::string: - case sol::type::number: - case sol::type::boolean: - { - std::string Name = Key.as<std::string>(); - if (Name.starts_with("_")) - { - continue; - } - Name = std::string(PathPrefix) + "." + Key.as<std::string>(); - auto OptionIt = OptionMap.find(Name); - if (OptionIt != OptionMap.end()) + sol::type ValueType = It.second.get_type(); + switch (ValueType) + { + case sol::type::table: + case sol::type::string: + case sol::type::number: + case sol::type::boolean: { - UsedKeys.insert(Name); - if (CmdLineResult.count(OptionIt->second.CommandLineOptionName) != 0) + std::string Name = Key.as<std::string>(); + if (Name.starts_with("_")) { continue; } - OptionIt->second.Value->Parse(It.second); - continue; - } - if (ValueType == sol::type::table) - { - if (Name == "base") + Name = std::string(PathPrefix) + "." + Key.as<std::string>(); + auto OptionIt = OptionMap.find(Name); + if (OptionIt != OptionMap.end()) { + UsedKeys.insert(Name); + if (CmdLineResult.count(OptionIt->second.CommandLineOptionName) != 0) + { + continue; + } + OptionIt->second.Value->Parse(It.second); continue; } - Traverse(It.second.as<sol::table>(), Name, CmdLineResult); + if (ValueType == sol::type::table) + { + if (Name == "base") + { + continue; + } + Traverse(It.second.as<sol::table>(), Name, CmdLineResult); + } } - } - break; - default: - break; + break; + default: + break; + } } } } - } - std::unordered_map<std::string, Option> OptionMap; - std::unordered_set<std::string> UsedKeys; -}; + std::unordered_map<std::string, Option> OptionMap; + std::unordered_set<std::string> UsedKeys; + }; } // namespace LuaConfig @@ -1508,3 +1494,5 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) ServerOptions.AbsLogFile = ServerOptions.DataDir / "logs" / "zenserver.log"; } } + +} // namespace zen |