feat add config
All checks were successful
linux-x64-gcc / linux-gcc (Release) (push) Successful in 1m54s
linux-mips64-gcc / linux-gcc-mips64el (Debug) (push) Successful in 2m1s
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (push) Successful in 2m5s
linux-arm-gcc / linux-gcc-armhf (push) Successful in 2m6s
linux-x64-gcc / linux-gcc (Debug) (push) Successful in 2m1s
linux-mips64-gcc / linux-gcc-mips64el (Release) (push) Successful in 2m13s
All checks were successful
linux-x64-gcc / linux-gcc (Release) (push) Successful in 1m54s
linux-mips64-gcc / linux-gcc-mips64el (Debug) (push) Successful in 2m1s
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (push) Successful in 2m5s
linux-arm-gcc / linux-gcc-armhf (push) Successful in 2m6s
linux-x64-gcc / linux-gcc (Debug) (push) Successful in 2m1s
linux-mips64-gcc / linux-gcc-mips64el (Release) (push) Successful in 2m13s
This commit is contained in:
parent
56068d35dc
commit
09beed9d2a
@ -53,6 +53,7 @@ target_include_directories(sled PUBLIC src/ 3party/eigen 3party/inja
|
||||
target_sources(
|
||||
sled
|
||||
PRIVATE src/sled/async/async.cc
|
||||
src/sled/config.cc
|
||||
src/sled/debugging/demangle.cc
|
||||
src/sled/debugging/symbolize.cc
|
||||
src/sled/event_bus/event_bus.cc
|
||||
@ -194,6 +195,7 @@ if(SLED_BUILD_TESTS)
|
||||
sled_add_test(NAME sled_string_view_test SRCS
|
||||
src/sled/nonstd/string_view_test.cc)
|
||||
sled_add_test(NAME sled_expected_test SRCS src/sled/nonstd/expected_test.cc)
|
||||
sled_add_test(NAME sled_config_test SRCS src/sled//config_test.cc)
|
||||
endif(SLED_BUILD_TESTS)
|
||||
|
||||
if(SLED_BUILD_FUZZ)
|
||||
|
228
src/sled/config.cc
Normal file
228
src/sled/config.cc
Normal file
@ -0,0 +1,228 @@
|
||||
#include "sled/config.h"
|
||||
#include "sled/log/log.h"
|
||||
#include "sled/strings/utils.h"
|
||||
#include <fstream>
|
||||
|
||||
namespace sled {
|
||||
Config::Config() = default;
|
||||
|
||||
Config::Config(sled::string_view name) : Config(name, "") {}
|
||||
|
||||
Config::Config(sled::string_view name, sled::string_view path) : config_name_(name)
|
||||
{
|
||||
config_paths_.emplace_back(path.to_string());
|
||||
}
|
||||
|
||||
void
|
||||
Config::SetConfigName(sled::string_view name)
|
||||
{
|
||||
config_name_ = name.to_string();
|
||||
}
|
||||
|
||||
void
|
||||
Config::AddConfigPath(sled::string_view path)
|
||||
{
|
||||
config_paths_.emplace_back(path.to_string());
|
||||
}
|
||||
|
||||
bool
|
||||
Config::ReadInConfig()
|
||||
{
|
||||
const static std::vector<std::string> extensions = {".toml"};
|
||||
for (const auto &path : config_paths_) {
|
||||
auto name = path + config_name_;
|
||||
for (const auto &ext : extensions) {
|
||||
const std::ifstream file(name + ext);
|
||||
if (file.good()) {
|
||||
try {
|
||||
std::stringstream ss;
|
||||
ss << file.rdbuf();
|
||||
|
||||
std::istringstream stream_data(ss.str(), std::ios_base::binary | std::ios_base::in);
|
||||
toml_ = toml::parse(stream_data, "string");
|
||||
return true;
|
||||
// goto config_read_success;
|
||||
} catch (...) {
|
||||
LOGD("Failed to parse config file: {}", name + ext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// config_read_success:
|
||||
// // pair<key, value>
|
||||
// for (auto &pair : default_values_) {
|
||||
// toml::value value;
|
||||
// if (!GetNode(pair.first, value)) { AddDefaultNode(pair.first, pair.second); }
|
||||
// }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Config::IsSet(sled::string_view key) const
|
||||
{
|
||||
toml::value value;
|
||||
return GetNode(key, value);
|
||||
}
|
||||
|
||||
bool
|
||||
Config::GetBoolOr(sled::string_view key, const bool &def) const
|
||||
{
|
||||
toml::value value;
|
||||
try {
|
||||
if (GetNode(key, value) && value.is_boolean()) { return value.as_boolean(); }
|
||||
} catch (...) {}
|
||||
return def;
|
||||
}
|
||||
|
||||
int
|
||||
Config::GetIntOr(sled::string_view key, const int &def) const
|
||||
{
|
||||
toml::value value;
|
||||
try {
|
||||
if (GetNode(key, value)) {
|
||||
if (value.is_integer()) {
|
||||
return value.as_integer();
|
||||
} else if (value.is_boolean()) {
|
||||
return value.as_boolean() ? 1 : 0;
|
||||
} else if (value.is_floating()) {
|
||||
return static_cast<int>(value.as_floating());
|
||||
}
|
||||
}
|
||||
} catch (...) {}
|
||||
return def;
|
||||
}
|
||||
|
||||
double
|
||||
Config::GetDoubleOr(sled::string_view key, const double &def) const
|
||||
{
|
||||
toml::value value;
|
||||
try {
|
||||
if (GetNode(key, value)) {
|
||||
if (value.is_floating()) {
|
||||
return value.as_floating();
|
||||
} else if (value.is_integer()) {
|
||||
return static_cast<double>(value.as_integer());
|
||||
}
|
||||
}
|
||||
} catch (...) {}
|
||||
return def;
|
||||
}
|
||||
|
||||
std::string
|
||||
Config::GetStringOr(sled::string_view key, sled::string_view def) const
|
||||
{
|
||||
toml::value value;
|
||||
try {
|
||||
if (GetNode(key, value) && value.is_string()) { return value.as_string(); }
|
||||
} catch (...) {}
|
||||
return def.to_string();
|
||||
}
|
||||
|
||||
void
|
||||
Config::SetDefault(sled::string_view key, const bool &value)
|
||||
{
|
||||
default_values_.insert({key.to_string(), value});
|
||||
}
|
||||
|
||||
void
|
||||
Config::SetDefault(sled::string_view key, const char *value)
|
||||
{
|
||||
SetDefault(key, std::string(value));
|
||||
}
|
||||
|
||||
void
|
||||
Config::SetDefault(sled::string_view key, const std::string &value)
|
||||
{
|
||||
default_values_.insert({key.to_string(), value});
|
||||
}
|
||||
|
||||
void
|
||||
Config::SetDefault(sled::string_view key, sled::string_view value)
|
||||
{
|
||||
SetDefault(key, std::string(value));
|
||||
}
|
||||
|
||||
void
|
||||
Config::SetDefault(sled::string_view key, const int &value)
|
||||
{
|
||||
default_values_.insert({key.to_string(), value});
|
||||
}
|
||||
|
||||
void
|
||||
Config::SetDefault(sled::string_view key, const double &value)
|
||||
{
|
||||
default_values_.insert({key.to_string(), value});
|
||||
}
|
||||
|
||||
bool
|
||||
Config::GetNode(sled::string_view key, toml::value &value) const
|
||||
{
|
||||
auto keys = StrSplit(key.to_string(), ".");
|
||||
auto cur = toml_;
|
||||
for (const auto &k : keys) {
|
||||
try {
|
||||
auto next = toml::find(cur, k);
|
||||
cur = next;
|
||||
} catch (...) {
|
||||
if (GetDefaultNode(key, value)) { return true; }
|
||||
return false;
|
||||
}
|
||||
}
|
||||
value = cur;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Config::AddDefaultNode(sled::string_view key, ValueType value)
|
||||
{
|
||||
auto keys = StrSplit(key.to_string(), ".");
|
||||
if (keys.size() == 1) {
|
||||
auto first_key = keys[0];
|
||||
switch (value.index()) {
|
||||
case 0:
|
||||
toml_[first_key] = sled::get<bool>(value);
|
||||
break;
|
||||
case 1:
|
||||
toml_[first_key] = sled::get<std::string>(value);
|
||||
break;
|
||||
case 2:
|
||||
toml_[first_key] = sled::get<int>(value);
|
||||
break;
|
||||
case 3:
|
||||
toml_[first_key] = sled::get<double>(value);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Config::GetDefaultNode(sled::string_view key, toml::value &value) const
|
||||
{
|
||||
auto iter = default_values_.find(key.to_string());
|
||||
if (iter == default_values_.end()) { return false; }
|
||||
auto &default_value = iter->second;
|
||||
switch (default_value.index()) {
|
||||
case 0:
|
||||
value = sled::get<bool>(default_value);
|
||||
break;
|
||||
case 1:
|
||||
value = sled::get<std::string>(default_value);
|
||||
break;
|
||||
case 2:
|
||||
value = sled::get<int>(default_value);
|
||||
break;
|
||||
case 3:
|
||||
value = sled::get<double>(default_value);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}// namespace sled
|
49
src/sled/config.h
Normal file
49
src/sled/config.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef SLED_CONFIG_H
|
||||
#define SLED_CONFIG_H
|
||||
|
||||
#include "sled/nonstd/string_view.h"
|
||||
#include "sled/variant.h"
|
||||
#include "toml.hpp"
|
||||
|
||||
namespace sled {
|
||||
class Config {
|
||||
public:
|
||||
using ValueType = sled::variant<bool, std::string, int, double>;
|
||||
Config();
|
||||
Config(sled::string_view name);
|
||||
Config(sled::string_view name, sled::string_view path);
|
||||
Config(const Config &lhs) = delete;
|
||||
Config(Config &&rhs) noexcept = delete;
|
||||
Config &operator=(const Config &lhs) = delete;
|
||||
Config &operator=(Config &&rhs) noexcept = delete;
|
||||
|
||||
void SetConfigName(sled::string_view name);
|
||||
void AddConfigPath(sled::string_view path);
|
||||
|
||||
bool ReadInConfig();
|
||||
|
||||
bool IsSet(sled::string_view key) const;
|
||||
bool GetBoolOr(sled::string_view key, const bool &def = false) const;
|
||||
int GetIntOr(sled::string_view key, const int &def = 0) const;
|
||||
double GetDoubleOr(sled::string_view key, const double &def = 0.0) const;
|
||||
std::string GetStringOr(sled::string_view key, const sled::string_view def = "") const;
|
||||
|
||||
void SetDefault(sled::string_view key, const bool &value);
|
||||
void SetDefault(sled::string_view key, const char *value);
|
||||
void SetDefault(sled::string_view key, const std::string &value);
|
||||
void SetDefault(sled::string_view key, sled::string_view value);
|
||||
void SetDefault(sled::string_view key, const int &value);
|
||||
void SetDefault(sled::string_view key, const double &value);
|
||||
|
||||
private:
|
||||
bool GetNode(sled::string_view key, toml::value &value) const;
|
||||
bool AddDefaultNode(sled::string_view, ValueType value);
|
||||
bool GetDefaultNode(sled::string_view key, toml::value &value) const;
|
||||
|
||||
std::unordered_map<std::string, ValueType> default_values_;
|
||||
std::vector<std::string> config_paths_;
|
||||
std::string config_name_;
|
||||
toml::value toml_;
|
||||
};
|
||||
}// namespace sled
|
||||
#endif// SLED_CONFIG_H
|
33
src/sled/config_test.cc
Normal file
33
src/sled/config_test.cc
Normal file
@ -0,0 +1,33 @@
|
||||
#include <sled/config.h>
|
||||
#include <sled/strings/utils.h>
|
||||
|
||||
static std::string test_config_name = "config_test";
|
||||
static std::string test_config_path = sled::StripSuffix(__FILE__, "config_test.cc").to_string();
|
||||
|
||||
TEST_SUITE("Config")
|
||||
{
|
||||
TEST_CASE("config")
|
||||
{
|
||||
sled::Config config;
|
||||
config.SetConfigName(test_config_name);
|
||||
config.AddConfigPath(test_config_path);
|
||||
config.SetDefault("top-string", "no effect");
|
||||
config.SetDefault("top-kk", "kk");
|
||||
CHECK(config.ReadInConfig());
|
||||
|
||||
CHECK(config.IsSet("top-string"));
|
||||
CHECK_EQ(config.GetStringOr("top-string"), "bob");
|
||||
|
||||
CHECK(config.IsSet("top-kk"));
|
||||
CHECK_EQ(config.GetStringOr("top-kk"), "kk");
|
||||
|
||||
CHECK(config.IsSet("top-int"));
|
||||
CHECK(config.IsSet("top-bool"));
|
||||
CHECK_EQ(config.GetIntOr("top-int"), 10);
|
||||
CHECK_EQ(config.GetBoolOr("top-bool"), true);
|
||||
CHECK_EQ(config.GetIntOr("top-bool"), 1);
|
||||
|
||||
CHECK(config.IsSet("top-table.key1"));
|
||||
CHECK_EQ(config.GetStringOr("top-table.key1"), "value1");
|
||||
}
|
||||
}
|
24
src/sled/config_test.toml
Normal file
24
src/sled/config_test.toml
Normal file
@ -0,0 +1,24 @@
|
||||
top-string = "bob"
|
||||
top-int = 10
|
||||
top-bool = true
|
||||
top-array = [ "item1", "item2", "item3" ]
|
||||
nested-array = [
|
||||
[ "nested-item1-subitem1", "nested-item1-subitem2"],
|
||||
[ "nested-item2-subitem1", "nested-item2-subitem2"]
|
||||
]
|
||||
|
||||
[top-table]
|
||||
key1 = "value1"
|
||||
key2 = "value2"
|
||||
key3 = "value3"
|
||||
|
||||
# Nested table
|
||||
[nested-table.key1]
|
||||
|
||||
key1-subkey1 = "value1-1"
|
||||
key1-subkey2 = "value1-2"
|
||||
|
||||
[nested-table.key2]
|
||||
|
||||
key2-subkey1 = "value2-1"
|
||||
key2-subkey2 = "value2-2"
|
@ -10,6 +10,7 @@
|
||||
#include "sled/nonstd/string_view.h"
|
||||
#include "toml.hpp"
|
||||
|
||||
#include "sled/config.h"
|
||||
// experimental
|
||||
#include "sled/experimental/design_patterns/dispatcher.h"
|
||||
|
||||
|
@ -17,7 +17,7 @@ ToUpper(char c)
|
||||
}
|
||||
|
||||
std::string
|
||||
ToLower(const std::string &str)
|
||||
ToLower(sled::string_view str)
|
||||
{
|
||||
std::stringstream ss;
|
||||
for (auto &ch : str) { ss << ToLower(ch); }
|
||||
@ -25,7 +25,7 @@ ToLower(const std::string &str)
|
||||
}
|
||||
|
||||
std::string
|
||||
ToUpper(const std::string &str)
|
||||
ToUpper(sled::string_view str)
|
||||
{
|
||||
std::stringstream ss;
|
||||
for (auto &ch : str) { ss << ToUpper(ch); }
|
||||
@ -102,28 +102,75 @@ TrimRight(const std::string &str, const std::string &chars)
|
||||
return end == std::string::npos ? "" : str.substr(0, end + 1);
|
||||
}
|
||||
|
||||
// bool
|
||||
// EndsWith(const std::string &str, const std::string &suffix)
|
||||
// {
|
||||
// return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
|
||||
// }
|
||||
//
|
||||
// bool
|
||||
// StartsWith(const std::string &str, const std::string &prefix)
|
||||
// {
|
||||
// return str.size() >= prefix.size() && str.compare(0, prefix.size(), prefix) == 0;
|
||||
// }
|
||||
bool
|
||||
EndsWith(const std::string &str, const std::string &suffix)
|
||||
{
|
||||
return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
StartsWith(const std::string &str, const std::string &prefix)
|
||||
StartsWith(sled::string_view str, sled::string_view prefix)
|
||||
{
|
||||
return str.size() >= prefix.size() && str.compare(0, prefix.size(), prefix) == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
EndsWithIgnoreCase(const std::string &str, const std::string &suffix)
|
||||
EndsWith(sled::string_view str, sled::string_view suffix)
|
||||
{
|
||||
return EndsWith(ToLower(str), ToLower(suffix));
|
||||
return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
|
||||
}
|
||||
|
||||
// bool
|
||||
// EndsWithIgnoreCase(const std::string &str, const std::string &suffix)
|
||||
// {
|
||||
// return EndsWith(ToLower(str), ToLower(suffix));
|
||||
// }
|
||||
//
|
||||
// bool
|
||||
// StartsWithIgnoreCase(const std::string &str, const std::string &prefix)
|
||||
// {
|
||||
// return StartsWith(ToLower(str), ToLower(prefix));
|
||||
// }
|
||||
|
||||
bool
|
||||
EndsWithIgnoreCase(sled::string_view str, sled::string_view suffix)
|
||||
{
|
||||
if (str.size() < suffix.size()) { return false; }
|
||||
|
||||
auto str_iter = str.rbegin();
|
||||
auto suffix_iter = suffix.rbegin();
|
||||
|
||||
for (; suffix_iter != suffix.rend(); ++str_iter, ++suffix_iter) {
|
||||
if (ToLower(*str_iter) != ToLower(*suffix_iter)) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
StartsWithIgnoreCase(const std::string &str, const std::string &prefix)
|
||||
StartsWithIgnoreCase(sled::string_view str, sled::string_view prefix)
|
||||
{
|
||||
return StartsWith(ToLower(str), ToLower(prefix));
|
||||
if (str.size() < prefix.size()) { return false; }
|
||||
auto str_iter = str.begin();
|
||||
auto prefix_iter = prefix.begin();
|
||||
for (; prefix_iter != prefix.end(); ++str_iter, ++prefix_iter) {
|
||||
if (ToLower(*str_iter) != ToLower(*prefix_iter)) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
EqualsIgnoreCase(sled::string_view lhs, sled::string_view rhs)
|
||||
{
|
||||
if (lhs.size() != rhs.size()) { return false; }
|
||||
for (size_t i = 0; i < lhs.size(); ++i) {
|
||||
if (ToLower(lhs[i]) != ToLower(rhs[i])) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#ifndef SLED_STRINGS_UTILS_H
|
||||
#define SLED_STRINGS_UTILS_H
|
||||
#include "sled/nonstd/string_view.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -8,21 +9,41 @@ namespace sled {
|
||||
|
||||
char ToLower(char c);
|
||||
char ToUpper(char c);
|
||||
std::string ToLower(const std::string &str);
|
||||
std::string ToUpper(const std::string &str);
|
||||
// std::string ToLower(const std::string &str);
|
||||
// std::string ToUpper(const std::string &str);
|
||||
std::string ToLower(sled::string_view str);
|
||||
std::string ToUpper(sled::string_view str);
|
||||
std::string ToHex(const std::string &str);
|
||||
std::string StrJoin(const std::vector<std::string> &strings, const std::string &delim, bool skip_empty = false);
|
||||
std::vector<std::string> StrSplit(const std::string &str, const std::string &delim, bool skip_empty = false);
|
||||
std::string Trim(const std::string &str, const std::string &chars = " \t\n\r");
|
||||
std::string TrimLeft(const std::string &str, const std::string &chars = " \t\n\r");
|
||||
std::string TrimRight(const std::string &str, const std::string &chars = " \t\n\r");
|
||||
bool EndsWith(const std::string &str, const std::string &suffix);
|
||||
bool StartsWith(const std::string &str, const std::string &prefix);
|
||||
// bool StartsWith(const std::string &str, const std::string &prefix);
|
||||
// bool EndsWith(const std::string &str, const std::string &suffix);
|
||||
bool StartsWith(sled::string_view str, sled::string_view prefix);
|
||||
bool EndsWith(sled::string_view str, sled::string_view suffix);
|
||||
|
||||
bool EndsWithIgnoreCase(const std::string &str, const std::string &suffix);
|
||||
bool StartsWithIgnoreCase(const std::string &str, const std::string &prefix);
|
||||
// bool EndsWithIgnoreCase(const std::string &str, const std::string &suffix);
|
||||
// bool StartsWithIgnoreCase(const std::string &str, const std::string &prefix);
|
||||
bool EndsWithIgnoreCase(sled::string_view str, sled::string_view suffix);
|
||||
bool StartsWithIgnoreCase(sled::string_view str, sled::string_view prefix);
|
||||
|
||||
bool EqualsIgnoreCase(const std::string &lhs, const std::string &rhs);
|
||||
// bool EqualsIgnoreCase(const std::string &lhs, const std::string &rhs);
|
||||
bool EqualsIgnoreCase(sled::string_view lhs, sled::string_view rhs);
|
||||
|
||||
inline sled::string_view
|
||||
StripPrefix(sled::string_view str, sled::string_view prefix)
|
||||
{
|
||||
if (sled::StartsWith(str, prefix)) str.remove_prefix(prefix.size());
|
||||
return str;
|
||||
}
|
||||
|
||||
inline sled::string_view
|
||||
StripSuffix(sled::string_view str, sled::string_view suffix)
|
||||
{
|
||||
if (sled::EndsWith(str, suffix)) str.remove_suffix(suffix.size());
|
||||
return str;
|
||||
}
|
||||
}// namespace sled
|
||||
#endif// SLED_STRINGS_UTILS_H
|
||||
|
@ -33,7 +33,7 @@ URI::ParseURI(const std::string &uri_str)
|
||||
if (!std::regex_match(uri_str, match, uri_regex)) {
|
||||
return sled::MakeStatusOr<URI>(sled::StatusCode::kInvalidArgument, "Invalid URI format");
|
||||
}
|
||||
uri.set_scheme(sled::ToLower(match[2]));
|
||||
uri.set_scheme(sled::ToLower(match[2].str()));
|
||||
|
||||
int counter = 0;
|
||||
// for (auto res : match) { LOGD("match", "{}:{}", counter++, res); }
|
||||
|
Loading…
Reference in New Issue
Block a user