feat/update_config #10

Merged
tqcq merged 26 commits from feat/update_config into master 2024-10-14 10:15:01 +08:00
8 changed files with 17581 additions and 9 deletions
Showing only changes of commit eda5a20286 - Show all commits

View File

@ -219,6 +219,7 @@ set(TILE_SRCS
"tile/base/config/ini_file_configuration.cc"
"tile/base/config/json_configuration.cc"
"tile/base/config/layered_configuration.cc"
"tile/base/config/toml_configuration.cc"
)
if((NOT TILE_HAVE_GETIFADDRS) OR (NOT TILE_HAVE_FREEIFADDRS))
@ -243,6 +244,7 @@ target_include_directories(
"${CMAKE_CURRENT_SOURCE_DIR}"
${THIRD_PARTY_INCLUDE_DIRS}
RPIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/third_party/header_only/"
"${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include")
target_link_libraries(

3
third_party/README.md vendored Normal file
View File

@ -0,0 +1,3 @@
# Library
- [toml11](https://github.com/ToruNiina/toml11/archive/refs/tags/v4.2.0.tar.gz)

17241
third_party/header_only/toml.hpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
#include "tile/base/config/json_configuration.h"
#include "gmock/gmock-matchers.h"
#include "gtest/gtest.h"
namespace tile {
@ -85,16 +86,11 @@ TEST(json_configuration, Enumerate)
ASSERT_TRUE(config.load(istr));
auto keys = config.keys("");
ASSERT_EQ(5, keys.size());
ASSERT_EQ("key1", keys[0]);
ASSERT_EQ("key2", keys[1]);
ASSERT_EQ("key3", keys[2]);
ASSERT_EQ("key4", keys[3]);
ASSERT_EQ("key5", keys[4]);
ASSERT_THAT(keys, ::testing::UnorderedElementsAre("key1", "key2", "key3", "key4", "key5"));
keys = config.keys("key5");
ASSERT_EQ(2, keys.size());
ASSERT_EQ("key5.key51", keys[0]);
ASSERT_EQ("key5.key52", keys[1]);
ASSERT_THAT(keys, ::testing::UnorderedElementsAre("key5.key51", "key5.key52"));
config.Remove("key5.key51");
keys = config.keys("key5");

View File

@ -0,0 +1,219 @@
#include "tile/base/config/toml_configuration.h"
#include "tile/base/logging.h"
#include "tile/base/string.h"
#include "toml.hpp"
namespace tile {
class TomlConfiguration::Impl {
public:
Impl() {}
~Impl() = default;
bool load(std::istream &istr)
{
try {
value_ = toml::parse(istr);
return true;
} catch (...) {
return false;
}
}
bool load(const std::string &path)
{
try {
value_ = toml::parse(path);
return true;
} catch (...) {
return false;
}
}
toml::value *operator->() { return &value_; }
toml::value &operator*() { return value_; }
private:
toml::value value_;
};
TomlConfiguration::TomlConfiguration() : impl_(new Impl) {}
TomlConfiguration::~TomlConfiguration() {}
bool
TomlConfiguration::load(std::istream &istr)
{
return impl_->load(istr);
}
bool
TomlConfiguration::load(const std::string &path)
{
return impl_->load(path);
}
void
TomlConfiguration::SetInt(const Slice &key, int value)
{
Configuration::SetInt(key, value);
}
void
TomlConfiguration::SetBool(const Slice &key, bool value)
{
Configuration::SetBool(key, value);
}
void
TomlConfiguration::SetDouble(const Slice &key, double value)
{
Configuration::SetDouble(key, value);
}
void
TomlConfiguration::SetString(const Slice &key, const std::string &value)
{
Configuration::SetString(key, value);
}
std::string
TomlConfiguration::Dump() const
{
try {
return toml::format(**impl_);
} catch (const std::exception &e) {
TILE_LOG_WARNING_EVERY_SECOND("{}", e.what());
return "";
}
}
bool
TomlConfiguration::GetRaw(const Slice &key, std::string *value) const
{
if (key.empty()) { return false; }
auto keys = Split(key, '.');
try {
auto cur = **impl_;
for (const auto &k : keys) {
auto next = toml::find(cur, k);
cur = next;
}
std::stringstream ss;
if (cur.is_string()) {
ss << cur.as_string();
} else if (cur.is_integer()) {
ss << cur.as_integer();
} else if (cur.is_boolean()) {
ss << cur.as_boolean();
} else if (cur.is_floating()) {
ss << cur.as_floating();
} else if (cur.is_empty()) {
ss << "";
} else {
ss << toml::format(cur);
}
*value = ss.str();
return true;
} catch (const std::exception &e) {
TILE_LOG_WARNING_EVERY_SECOND("{}", e.what());
return false;
}
}
bool
TomlConfiguration::SetRaw(const Slice &key, const Slice &value)
{
if (key.empty()) { return false; }
auto keys = Split(key, '.');
try {
auto &root = **impl_;
for (size_t i = 0; i < keys.size() - 1; ++i) {
auto &next = toml::find(root, keys[i]);
root = next;
}
root[keys.back()] = value.ToString();
return true;
} catch (const std::exception &e) {
TILE_LOG_WARNING_EVERY_SECOND("{}", e.what());
return false;
}
}
void
TomlConfiguration::RemoveRaw(const Slice &key)
{
if (key.empty()) { return; }
auto keys = Split(key, '.');
while (!keys.empty() && keys.back() == "") { keys.pop_back(); }
try {
if (keys.empty()) {
auto &root = **impl_;
root = toml::table();
return;
}
auto root = **impl_;
for (size_t i = 0; i + 1 < keys.size(); ++i) {
if (!root.contains(keys[i])) { return; }
root = root.at(keys[i]);
}
if (!root.contains(keys.back())) { return; }
auto last_root = root.at(key.back());
// remove the last key
toml::value new_node = toml::table();
for (const auto &p : last_root.as_table()) {
if (p.first != keys.back()) { new_node[p.first] = p.second; }
}
last_root = new_node;
} catch (...) {}
}
Configuration::Keys
TomlConfiguration::Enumerate(const Slice &range) const
{
Configuration::Keys keys;
auto split_keys = Split(range, '.');
auto last_key = split_keys.empty() ? "" : split_keys.back();
std::string prefix = range;
if (!prefix.empty() && prefix.back() != '.') { prefix += "."; }
auto root = **impl_;
try {
// if (!root.is_empty()) {
for (int i = 0; i < split_keys.size(); ++i) {
auto next = toml::find(root, split_keys[i]);
root = next;
}
// }
// if (root.is_empty()) { return keys; }
// for (const auto &k : keys_) {
// auto next = toml::find(root, k);
// root = next;
// }
auto visitor = [&](const toml::value &node) {
if (node.is_table()) {
for (const auto &p : node.as_table()) {
/*if (EndsWith(p.first, prefix)) */ {
keys.push_back(prefix + p.first);
}
}
}
};
toml::visit(visitor, root);
// TILE_LOG_INFO("{}", toml::format(root));
} catch (const std::exception &e) {
TILE_LOG_WARNING_EVERY_SECOND("{}\n{}\n", e.what(), Dump());
}
return keys;
}
}// namespace tile

View File

@ -0,0 +1,40 @@
#ifndef TILE_BASE_CONFIG_TOML_CONFIGURATION_H
#define TILE_BASE_CONFIG_TOML_CONFIGURATION_H
#pragma once
#include "tile/base/config/configuration.h"
#include <map>
namespace tile {
class TomlConfiguration : public Configuration {
public:
using Ptr = RefPtr<TomlConfiguration>;
TomlConfiguration();
~TomlConfiguration() override;
bool load(std::istream &istr);
bool load(const std::string &path);
void SetInt(const Slice &key, int value) override;
void SetBool(const Slice &key, bool value) override;
void SetDouble(const Slice &key, double value) override;
void SetString(const Slice &key, const std::string &value) override;
void RemoveRaw(const Slice &key) override;
std::string Dump() const;
protected:
bool GetRaw(const Slice &key, std::string *value) const override;
bool SetRaw(const Slice &key, const Slice &value) override;
Keys Enumerate(const Slice &range) const override;
private:
class Impl;
std::unique_ptr<Impl> impl_;
};
}// namespace tile
#endif// TILE_BASE_CONFIG_TOML_CONFIGURATION_H

View File

@ -0,0 +1,71 @@
#include "tile/base/config/toml_configuration.h"
#include "gmock/gmock-matchers.h"
#include "gtest/gtest.h"
namespace tile {
namespace {
const char *kTomlConfig = R"(
key1=1
key2=2
key3=1.9
key4=true
[key5]
key51="value51"
key52=52
)";
}
TEST(TomlConfiguration, Load)
{
TomlConfiguration config;
std::istringstream istr(kTomlConfig);
ASSERT_TRUE(config.load(istr));
}
TEST(TomlConfiguration, Has)
{
TomlConfiguration config;
std::istringstream istr(kTomlConfig);
ASSERT_TRUE(config.load(istr));
ASSERT_TRUE(config.Has("key1"));
ASSERT_TRUE(config.Has("key2"));
ASSERT_TRUE(config.Has("key3"));
ASSERT_TRUE(config.Has("key4"));
ASSERT_TRUE(config.Has("key5"));
ASSERT_TRUE(config.Has("key5.key51"));
ASSERT_TRUE(config.Has("key5.key52"));
}
TEST(TomlConfiguration, SampleSet)
{
TomlConfiguration config;
std::istringstream istr(kTomlConfig);
ASSERT_TRUE(config.load(istr));
ASSERT_TRUE(config.GetInt32("key2"));
ASSERT_EQ(*config.GetInt32("key2"), 2);
config.SetInt("key2", 20);
}
TEST(TomlConfiguration, Enumerate)
{
TomlConfiguration config;
std::istringstream istr(kTomlConfig);
ASSERT_TRUE(config.load(istr));
auto keys = config.keys("");
ASSERT_EQ(5, keys.size());
ASSERT_THAT(keys, ::testing::UnorderedElementsAre("key1", "key2", "key3", "key4", "key5"));
keys = config.keys("key5");
// for (const auto &key : keys) { TILE_LOG_INFO("key5: {}", key); }
ASSERT_EQ(2, keys.size());
ASSERT_THAT(keys, ::testing::UnorderedElementsAre("key5.key51", "key5.key52"));
config.Remove("key5.key51");
keys = config.keys("key5");
ASSERT_EQ("key5.key52", keys[0]);
}
}// namespace tile

View File

@ -175,8 +175,8 @@ public:
inline operator string_t() const { return ToString(); }
private:
const char *data_;
size_t len_;
const char *data_{nullptr};
size_t len_{0};
};
inline bool