feat/update_config #10
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@ out/
|
||||
build/
|
||||
.cache/
|
||||
compile_commands.json
|
||||
.gdb_history
|
||||
|
@ -302,6 +302,9 @@ function(add_test_group prefix group_name)
|
||||
# convert to relative path message(STATUS "${prefix} -> ${TEST_FILE}")
|
||||
file(RELATIVE_PATH TEST_NAME "${prefix}" "${SRC_FILE}")
|
||||
string(REPLACE "/" "_" TEST_NAME "${TEST_NAME}")
|
||||
string(REPLACE ".cpp" "" TEST_NAME "${TEST_NAME}")
|
||||
string(REPLACE ".cc" "" TEST_NAME "${TEST_NAME}")
|
||||
string(REPLACE ".c" "" TEST_NAME "${TEST_NAME}")
|
||||
# if group_name is not empty, add suffix _
|
||||
if (NOT group_name STREQUAL "")
|
||||
set(TEST_NAME "${group_name}_${TEST_NAME}")
|
||||
|
@ -22,33 +22,39 @@ bool JSONConfiguration::load(std::istream &istr) {
|
||||
}
|
||||
|
||||
void JSONConfiguration::SetInt(const Slice &key, int value) {
|
||||
Configuration::ScopedLock _(*this);
|
||||
SetValue(key, value);
|
||||
}
|
||||
|
||||
void JSONConfiguration::SetBool(const Slice &key, bool value) {
|
||||
Configuration::ScopedLock _(*this);
|
||||
SetValue(key, value);
|
||||
}
|
||||
|
||||
void JSONConfiguration::SetDouble(const Slice &key, double value) {
|
||||
Configuration::ScopedLock _(*this);
|
||||
SetValue(key, value);
|
||||
}
|
||||
|
||||
void JSONConfiguration::SetString(const Slice &key, const std::string &value) {
|
||||
Configuration::ScopedLock _(*this);
|
||||
SetValue(key, value);
|
||||
}
|
||||
|
||||
void JSONConfiguration::RemoveRaw(const Slice &key) {
|
||||
Configuration::ScopedLock _(*this);
|
||||
Json::Value root;
|
||||
Json::Value *root;
|
||||
Slice last_part;
|
||||
if (!FindStart(key, &last_part, &root)) {
|
||||
return;
|
||||
}
|
||||
root.removeMember(last_part.ToString());
|
||||
root->removeMember(last_part.ToString());
|
||||
}
|
||||
std::string JSONConfiguration::Dump() const {
|
||||
Configuration::ScopedLock _(*this);
|
||||
return object_.toStyledString();
|
||||
}
|
||||
|
||||
bool JSONConfiguration::GetRaw(const Slice &key, std::string *value) const {
|
||||
Configuration::ScopedLock _(*this);
|
||||
auto keys = Split(key, '.');
|
||||
auto root = object_;
|
||||
for (std::size_t i = 0; i < keys.size(); ++i) {
|
||||
@ -57,13 +63,17 @@ bool JSONConfiguration::GetRaw(const Slice &key, std::string *value) const {
|
||||
TILE_LOG_ERROR("Invalid key: {}", key);
|
||||
return false;
|
||||
}
|
||||
if (!object_.isMember(cur_key)) {
|
||||
if (!root.isMember(cur_key)) {
|
||||
return false;
|
||||
}
|
||||
root = root[cur_key];
|
||||
}
|
||||
|
||||
if (root.isConvertibleTo(Json::stringValue)) {
|
||||
*value = root.asString();
|
||||
} else {
|
||||
*value = root.toStyledString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -83,7 +93,7 @@ Configuration::Keys JSONConfiguration::Enumerate(const Slice &range) const {
|
||||
TILE_LOG_ERROR("Invalid range: {}", range);
|
||||
return key_set;
|
||||
}
|
||||
if (!object_.isMember(cur_key)) {
|
||||
if (!root.isMember(cur_key)) {
|
||||
return key_set;
|
||||
}
|
||||
root = root[cur_key];
|
||||
@ -96,13 +106,13 @@ Configuration::Keys JSONConfiguration::Enumerate(const Slice &range) const {
|
||||
}
|
||||
|
||||
bool JSONConfiguration::FindStart(const Slice &key, Slice *last_part,
|
||||
Json::Value *parent_obj) {
|
||||
Json::Value **parent_obj) {
|
||||
auto keys = Split(key, '.');
|
||||
if (keys.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto root = object_;
|
||||
Json::Value *root = &object_;
|
||||
for (std::size_t i = 0; i < keys.size() - 1; ++i) {
|
||||
const auto &cur_key = keys[i];
|
||||
if (cur_key.empty()) {
|
||||
@ -110,14 +120,14 @@ bool JSONConfiguration::FindStart(const Slice &key, Slice *last_part,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!root.isMember(cur_key)) {
|
||||
root[cur_key] = Json::Value(Json::objectValue);
|
||||
} else if (!root[cur_key].isObject()) {
|
||||
if (!root->isMember(cur_key)) {
|
||||
(*root)[cur_key] = Json::Value(Json::objectValue);
|
||||
} else if (!(*root)[cur_key].isObject()) {
|
||||
TILE_LOG_ERROR("only leaf nodes can be set: key: {}, cur_key(idx={}): {}",
|
||||
key, i, cur_key);
|
||||
return false;
|
||||
}
|
||||
root = root[cur_key];
|
||||
root = &(*root)[cur_key];
|
||||
}
|
||||
|
||||
*last_part = keys.back();
|
||||
|
@ -21,13 +21,15 @@ public:
|
||||
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:
|
||||
bool FindStart(const Slice &key, Slice *last_prt, Json::Value *parent_obj);
|
||||
bool FindStart(const Slice &key, Slice *last_prt, Json::Value **parent_obj);
|
||||
template <typename T> bool SetValue(const Slice &key, T value);
|
||||
Json::Value object_;
|
||||
};
|
||||
@ -35,12 +37,11 @@ private:
|
||||
template <typename T>
|
||||
bool JSONConfiguration::SetValue(const Slice &key, T value) {
|
||||
Slice last_part;
|
||||
Json::Value root;
|
||||
Configuration::ScopedLock _(*this);
|
||||
Json::Value *root;
|
||||
if (!FindStart(key, &last_part, &root)) {
|
||||
return false;
|
||||
}
|
||||
root[last_part] = Json::Value(value);
|
||||
(*root)[last_part] = Json::Value(value);
|
||||
return true;
|
||||
}
|
||||
} // namespace tile
|
||||
|
76
tile/base/config/json_configuration_test.cc
Normal file
76
tile/base/config/json_configuration_test.cc
Normal file
@ -0,0 +1,76 @@
|
||||
#include "tile/base/config/json_configuration.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace tile {
|
||||
namespace {
|
||||
const char *kJsonConfig = R"(
|
||||
{
|
||||
"key1": "value1",
|
||||
"key2": 2,
|
||||
"key3": 3.0,
|
||||
"key4": true,
|
||||
"key5": {
|
||||
"key51": "value51",
|
||||
"key52": 52
|
||||
}
|
||||
}
|
||||
)";
|
||||
}
|
||||
|
||||
TEST(JSONConfiguration, Load) {
|
||||
JSONConfiguration config;
|
||||
std::istringstream istr(kJsonConfig);
|
||||
ASSERT_TRUE(config.load(istr));
|
||||
}
|
||||
TEST(JSONConfiguration, Has) {
|
||||
JSONConfiguration config;
|
||||
std::istringstream istr(kJsonConfig);
|
||||
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(JSONConfiguration, SampleSet) {
|
||||
JSONConfiguration config;
|
||||
std::istringstream istr(kJsonConfig);
|
||||
ASSERT_TRUE(config.load(istr));
|
||||
ASSERT_TRUE(config.GetInt32("key2"));
|
||||
ASSERT_EQ(*config.GetInt32("key2"), 2);
|
||||
|
||||
config.SetInt("key2", 20);
|
||||
ASSERT_TRUE(config.GetInt32("key2"));
|
||||
ASSERT_EQ(20, *config.GetInt32("key2")) << config.Dump();
|
||||
|
||||
config.SetDouble("key3", 30.0);
|
||||
ASSERT_TRUE(config.GetDouble("key3"));
|
||||
ASSERT_NEAR(30.0, *config.GetDouble("key3"), 0.0001) << config.Dump();
|
||||
|
||||
config.SetBool("key4", false);
|
||||
ASSERT_TRUE(config.GetBool("key4"));
|
||||
ASSERT_FALSE(*config.GetBool("key4")) << config.Dump();
|
||||
}
|
||||
|
||||
TEST(JSONConfiguration, LayeredSet) {
|
||||
JSONConfiguration config;
|
||||
std::istringstream istr(kJsonConfig);
|
||||
ASSERT_TRUE(config.load(istr));
|
||||
|
||||
// ASSERT_TRUE(config.GetInt32("key5.key52"));
|
||||
config.SetInt("key5.key52", 520);
|
||||
ASSERT_TRUE(config.GetInt32("key5.key52")) << config.Dump();
|
||||
ASSERT_EQ(520, *config.GetInt32("key5.key52")) << config.Dump();
|
||||
|
||||
// override by other type
|
||||
config.SetBool("key5.key52", false);
|
||||
ASSERT_TRUE(config.GetBool("key5.key52")) << config.Dump();
|
||||
ASSERT_FALSE(*config.GetBool("key5.key52")) << config.Dump();
|
||||
}
|
||||
|
||||
} // namespace tile
|
Loading…
Reference in New Issue
Block a user