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

This commit is contained in:
tqcq 2024-04-09 12:32:23 +00:00
parent 56068d35dc
commit 09beed9d2a
9 changed files with 426 additions and 21 deletions

View File

@ -53,6 +53,7 @@ target_include_directories(sled PUBLIC src/ 3party/eigen 3party/inja
target_sources( target_sources(
sled sled
PRIVATE src/sled/async/async.cc PRIVATE src/sled/async/async.cc
src/sled/config.cc
src/sled/debugging/demangle.cc src/sled/debugging/demangle.cc
src/sled/debugging/symbolize.cc src/sled/debugging/symbolize.cc
src/sled/event_bus/event_bus.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 sled_add_test(NAME sled_string_view_test SRCS
src/sled/nonstd/string_view_test.cc) 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_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) endif(SLED_BUILD_TESTS)
if(SLED_BUILD_FUZZ) if(SLED_BUILD_FUZZ)

228
src/sled/config.cc Normal file
View 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
View 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
View 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
View 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"

View File

@ -10,6 +10,7 @@
#include "sled/nonstd/string_view.h" #include "sled/nonstd/string_view.h"
#include "toml.hpp" #include "toml.hpp"
#include "sled/config.h"
// experimental // experimental
#include "sled/experimental/design_patterns/dispatcher.h" #include "sled/experimental/design_patterns/dispatcher.h"

View File

@ -17,7 +17,7 @@ ToUpper(char c)
} }
std::string std::string
ToLower(const std::string &str) ToLower(sled::string_view str)
{ {
std::stringstream ss; std::stringstream ss;
for (auto &ch : str) { ss << ToLower(ch); } for (auto &ch : str) { ss << ToLower(ch); }
@ -25,7 +25,7 @@ ToLower(const std::string &str)
} }
std::string std::string
ToUpper(const std::string &str) ToUpper(sled::string_view str)
{ {
std::stringstream ss; std::stringstream ss;
for (auto &ch : str) { ss << ToUpper(ch); } 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); 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 bool
EndsWith(const std::string &str, const std::string &suffix) StartsWith(sled::string_view str, sled::string_view prefix)
{
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; return str.size() >= prefix.size() && str.compare(0, prefix.size(), prefix) == 0;
} }
bool 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 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 bool

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#ifndef SLED_STRINGS_UTILS_H #ifndef SLED_STRINGS_UTILS_H
#define SLED_STRINGS_UTILS_H #define SLED_STRINGS_UTILS_H
#include "sled/nonstd/string_view.h"
#include <string> #include <string>
#include <vector> #include <vector>
@ -8,21 +9,41 @@ namespace sled {
char ToLower(char c); char ToLower(char c);
char ToUpper(char c); char ToUpper(char c);
std::string ToLower(const std::string &str); // std::string ToLower(const std::string &str);
std::string ToUpper(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 ToHex(const std::string &str);
std::string StrJoin(const std::vector<std::string> &strings, const std::string &delim, bool skip_empty = false); 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::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 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 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"); 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 EndsWithIgnoreCase(const std::string &str, const std::string &suffix);
bool StartsWithIgnoreCase(const std::string &str, const std::string &prefix); // 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 }// namespace sled
#endif// SLED_STRINGS_UTILS_H #endif// SLED_STRINGS_UTILS_H

View File

@ -33,7 +33,7 @@ URI::ParseURI(const std::string &uri_str)
if (!std::regex_match(uri_str, match, uri_regex)) { if (!std::regex_match(uri_str, match, uri_regex)) {
return sled::MakeStatusOr<URI>(sled::StatusCode::kInvalidArgument, "Invalid URI format"); 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; int counter = 0;
// for (auto res : match) { LOGD("match", "{}:{}", counter++, res); } // for (auto res : match) { LOGD("match", "{}:{}", counter++, res); }