feat/update_config #10
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@ out/
|
|||||||
build/
|
build/
|
||||||
.cache/
|
.cache/
|
||||||
compile_commands.json
|
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}")
|
# convert to relative path message(STATUS "${prefix} -> ${TEST_FILE}")
|
||||||
file(RELATIVE_PATH TEST_NAME "${prefix}" "${SRC_FILE}")
|
file(RELATIVE_PATH TEST_NAME "${prefix}" "${SRC_FILE}")
|
||||||
string(REPLACE "/" "_" TEST_NAME "${TEST_NAME}")
|
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 group_name is not empty, add suffix _
|
||||||
if (NOT group_name STREQUAL "")
|
if (NOT group_name STREQUAL "")
|
||||||
set(TEST_NAME "${group_name}_${TEST_NAME}")
|
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) {
|
void JSONConfiguration::SetInt(const Slice &key, int value) {
|
||||||
|
Configuration::ScopedLock _(*this);
|
||||||
SetValue(key, value);
|
SetValue(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSONConfiguration::SetBool(const Slice &key, bool value) {
|
void JSONConfiguration::SetBool(const Slice &key, bool value) {
|
||||||
|
Configuration::ScopedLock _(*this);
|
||||||
SetValue(key, value);
|
SetValue(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSONConfiguration::SetDouble(const Slice &key, double value) {
|
void JSONConfiguration::SetDouble(const Slice &key, double value) {
|
||||||
|
Configuration::ScopedLock _(*this);
|
||||||
SetValue(key, value);
|
SetValue(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSONConfiguration::SetString(const Slice &key, const std::string &value) {
|
void JSONConfiguration::SetString(const Slice &key, const std::string &value) {
|
||||||
|
Configuration::ScopedLock _(*this);
|
||||||
SetValue(key, value);
|
SetValue(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSONConfiguration::RemoveRaw(const Slice &key) {
|
void JSONConfiguration::RemoveRaw(const Slice &key) {
|
||||||
Configuration::ScopedLock _(*this);
|
Json::Value *root;
|
||||||
Json::Value root;
|
|
||||||
Slice last_part;
|
Slice last_part;
|
||||||
if (!FindStart(key, &last_part, &root)) {
|
if (!FindStart(key, &last_part, &root)) {
|
||||||
return;
|
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 {
|
bool JSONConfiguration::GetRaw(const Slice &key, std::string *value) const {
|
||||||
Configuration::ScopedLock _(*this);
|
|
||||||
auto keys = Split(key, '.');
|
auto keys = Split(key, '.');
|
||||||
auto root = object_;
|
auto root = object_;
|
||||||
for (std::size_t i = 0; i < keys.size(); ++i) {
|
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);
|
TILE_LOG_ERROR("Invalid key: {}", key);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!object_.isMember(cur_key)) {
|
if (!root.isMember(cur_key)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
root = root[cur_key];
|
root = root[cur_key];
|
||||||
}
|
}
|
||||||
|
|
||||||
*value = root.asString();
|
if (root.isConvertibleTo(Json::stringValue)) {
|
||||||
|
*value = root.asString();
|
||||||
|
} else {
|
||||||
|
*value = root.toStyledString();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +93,7 @@ Configuration::Keys JSONConfiguration::Enumerate(const Slice &range) const {
|
|||||||
TILE_LOG_ERROR("Invalid range: {}", range);
|
TILE_LOG_ERROR("Invalid range: {}", range);
|
||||||
return key_set;
|
return key_set;
|
||||||
}
|
}
|
||||||
if (!object_.isMember(cur_key)) {
|
if (!root.isMember(cur_key)) {
|
||||||
return key_set;
|
return key_set;
|
||||||
}
|
}
|
||||||
root = root[cur_key];
|
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,
|
bool JSONConfiguration::FindStart(const Slice &key, Slice *last_part,
|
||||||
Json::Value *parent_obj) {
|
Json::Value **parent_obj) {
|
||||||
auto keys = Split(key, '.');
|
auto keys = Split(key, '.');
|
||||||
if (keys.empty()) {
|
if (keys.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto root = object_;
|
Json::Value *root = &object_;
|
||||||
for (std::size_t i = 0; i < keys.size() - 1; ++i) {
|
for (std::size_t i = 0; i < keys.size() - 1; ++i) {
|
||||||
const auto &cur_key = keys[i];
|
const auto &cur_key = keys[i];
|
||||||
if (cur_key.empty()) {
|
if (cur_key.empty()) {
|
||||||
@ -110,14 +120,14 @@ bool JSONConfiguration::FindStart(const Slice &key, Slice *last_part,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!root.isMember(cur_key)) {
|
if (!root->isMember(cur_key)) {
|
||||||
root[cur_key] = Json::Value(Json::objectValue);
|
(*root)[cur_key] = Json::Value(Json::objectValue);
|
||||||
} else if (!root[cur_key].isObject()) {
|
} else if (!(*root)[cur_key].isObject()) {
|
||||||
TILE_LOG_ERROR("only leaf nodes can be set: key: {}, cur_key(idx={}): {}",
|
TILE_LOG_ERROR("only leaf nodes can be set: key: {}, cur_key(idx={}): {}",
|
||||||
key, i, cur_key);
|
key, i, cur_key);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
root = root[cur_key];
|
root = &(*root)[cur_key];
|
||||||
}
|
}
|
||||||
|
|
||||||
*last_part = keys.back();
|
*last_part = keys.back();
|
||||||
|
@ -21,13 +21,15 @@ public:
|
|||||||
void SetString(const Slice &key, const std::string &value) override;
|
void SetString(const Slice &key, const std::string &value) override;
|
||||||
void RemoveRaw(const Slice &key) override;
|
void RemoveRaw(const Slice &key) override;
|
||||||
|
|
||||||
|
std::string Dump() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool GetRaw(const Slice &key, std::string *value) const override;
|
bool GetRaw(const Slice &key, std::string *value) const override;
|
||||||
bool SetRaw(const Slice &key, const Slice &value) override;
|
bool SetRaw(const Slice &key, const Slice &value) override;
|
||||||
Keys Enumerate(const Slice &range) const override;
|
Keys Enumerate(const Slice &range) const override;
|
||||||
|
|
||||||
private:
|
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);
|
template <typename T> bool SetValue(const Slice &key, T value);
|
||||||
Json::Value object_;
|
Json::Value object_;
|
||||||
};
|
};
|
||||||
@ -35,12 +37,11 @@ private:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
bool JSONConfiguration::SetValue(const Slice &key, T value) {
|
bool JSONConfiguration::SetValue(const Slice &key, T value) {
|
||||||
Slice last_part;
|
Slice last_part;
|
||||||
Json::Value root;
|
Json::Value *root;
|
||||||
Configuration::ScopedLock _(*this);
|
|
||||||
if (!FindStart(key, &last_part, &root)) {
|
if (!FindStart(key, &last_part, &root)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
root[last_part] = Json::Value(value);
|
(*root)[last_part] = Json::Value(value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} // namespace tile
|
} // 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