aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/common/Base.hpp2
-rw-r--r--include/cru/common/PropertyTree.hpp63
-rw-r--r--include/cru/common/String.hpp5
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/PropertyTree.cpp71
-rw-r--r--test/common/CMakeLists.txt1
-rw-r--r--test/common/PropertyTreeTest.cpp26
7 files changed, 168 insertions, 1 deletions
diff --git a/include/cru/common/Base.hpp b/include/cru/common/Base.hpp
index ef5727c5..cb06cc09 100644
--- a/include/cru/common/Base.hpp
+++ b/include/cru/common/Base.hpp
@@ -36,7 +36,7 @@
classname(classname&&) = delete; \
classname& operator=(classname&&) = delete;
-#define CRU_DEFAULT_DESTRUCTOR(classname) ~classname() override = default;
+#define CRU_DEFAULT_DESTRUCTOR(classname) ~classname() = default;
#define CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(classname) \
classname() = default; \
diff --git a/include/cru/common/PropertyTree.hpp b/include/cru/common/PropertyTree.hpp
new file mode 100644
index 00000000..01b50dac
--- /dev/null
+++ b/include/cru/common/PropertyTree.hpp
@@ -0,0 +1,63 @@
+#pragma once
+
+#include "Base.hpp"
+#include "String.hpp"
+
+#include <unordered_map>
+
+namespace cru {
+class PropertyTree;
+
+class PropertySubTreeRef {
+ public:
+ static String CombineKey(StringView left, StringView right);
+
+ explicit PropertySubTreeRef(PropertyTree* tree, String path = {});
+
+ CRU_DEFAULT_COPY(PropertySubTreeRef);
+ CRU_DEFAULT_MOVE(PropertySubTreeRef);
+
+ CRU_DEFAULT_DESTRUCTOR(PropertySubTreeRef);
+
+ public:
+ PropertyTree* GetTree() const { return tree_; }
+
+ String GetPath() const { return path_; }
+ void SetPath(String path) { path_ = std::move(path); }
+
+ PropertySubTreeRef GetParent() const;
+ PropertySubTreeRef GetChild(const String& key) const;
+
+ String GetValue(const String& key) const;
+ void SetValue(const String& key, String value);
+ void DeleteValue(const String& key);
+
+ private:
+ PropertyTree* tree_;
+ String path_;
+};
+
+class PropertyTree {
+ public:
+ static String CombineKey(StringView left, StringView right);
+
+ PropertyTree() = default;
+ explicit PropertyTree(std::unordered_map<String, String> values);
+
+ CRU_DELETE_COPY(PropertyTree);
+ CRU_DELETE_MOVE(PropertyTree);
+
+ CRU_DEFAULT_DESTRUCTOR(PropertyTree);
+
+ public:
+ String GetValue(const String& key) const;
+ void SetValue(const String& key, String value);
+ void DeleteValue(const String& key);
+
+ PropertySubTreeRef GetSubTreeRef(const String& path);
+
+ private:
+ std::unordered_map<String, String> values_;
+};
+
+} // namespace cru
diff --git a/include/cru/common/String.hpp b/include/cru/common/String.hpp
index 0ae223cf..8acb6a87 100644
--- a/include/cru/common/String.hpp
+++ b/include/cru/common/String.hpp
@@ -82,6 +82,8 @@ class CRU_BASE_API String {
String(std::initializer_list<value_type> l);
+ explicit String(StringView str);
+
#ifdef CRU_PLATFORM_WINDOWS
String(const wchar_t* str);
String(const wchar_t* str, Index size);
@@ -259,6 +261,7 @@ class CRU_BASE_API StringView {
~StringView() = default;
+ bool empty() const { return size_ == 0; }
Index size() const { return size_; }
const value_type* data() const { return ptr_; }
@@ -405,6 +408,8 @@ inline void String::append(StringView str) {
inline String String::From(StringView str) { return str.ToString(); }
+inline String::String(StringView str) : String(str.data(), str.size()) {}
+
inline String ToString(StringView value) { return value.ToString(); }
inline CodePoint Utf16PreviousCodePoint(StringView str, Index current,
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index e07017bb..5cc60690 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -1,6 +1,7 @@
set(CRU_BASE_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/common)
add_library(cru_base SHARED
Logger.cpp
+ PropertyTree.cpp
String.cpp
StringUtil.cpp
)
diff --git a/src/common/PropertyTree.cpp b/src/common/PropertyTree.cpp
new file mode 100644
index 00000000..cc3e9cb5
--- /dev/null
+++ b/src/common/PropertyTree.cpp
@@ -0,0 +1,71 @@
+#include "cru/common/PropertyTree.hpp"
+#include <unordered_map>
+#include "cru/common/Exception.hpp"
+
+namespace cru {
+String PropertySubTreeRef::CombineKey(StringView left, StringView right) {
+ return PropertyTree::CombineKey(left, right);
+}
+
+PropertySubTreeRef::PropertySubTreeRef(PropertyTree* tree, String path)
+ : tree_(tree), path_(std::move(path)) {
+ Expects(tree);
+}
+
+PropertySubTreeRef PropertySubTreeRef::GetParent() const {
+ for (Index i = path_.size() - 1; i >= 0; i--) {
+ if (path_[i] == '.') {
+ return PropertySubTreeRef(tree_, path_.substr(0, i));
+ }
+ }
+
+ return PropertySubTreeRef(tree_, {});
+}
+
+PropertySubTreeRef PropertySubTreeRef::GetChild(const String& key) const {
+ return PropertySubTreeRef(tree_, CombineKey(path_, key));
+}
+
+String PropertySubTreeRef::GetValue(const String& key) const {
+ return tree_->GetValue(CombineKey(path_, key));
+}
+
+void PropertySubTreeRef::SetValue(const String& key, String value) {
+ tree_->SetValue(CombineKey(path_, key), std::move(value));
+}
+
+void PropertySubTreeRef::DeleteValue(const String& key) {
+ tree_->DeleteValue(CombineKey(path_, key));
+}
+
+String PropertyTree::CombineKey(StringView left, StringView right) {
+ return String(left) + String(left.empty() ? u"" : u".") + String(right);
+}
+
+PropertyTree::PropertyTree(std::unordered_map<String, String> values)
+ : values_(std::move(values)) {}
+
+String PropertyTree::GetValue(const String& key) const {
+ auto it = values_.find(key);
+ if (it == values_.end()) {
+ throw Exception(u"Property tree has no value.");
+ }
+ return it->second;
+}
+
+void PropertyTree::SetValue(const String& key, String value) {
+ values_[key] = std::move(value);
+}
+
+void PropertyTree::DeleteValue(const String& key) {
+ auto it = values_.find(key);
+ if (it != values_.end()) {
+ values_.erase(it);
+ }
+}
+
+PropertySubTreeRef PropertyTree::GetSubTreeRef(const String& path) {
+ return PropertySubTreeRef(this, path);
+}
+
+} // namespace cru
diff --git a/test/common/CMakeLists.txt b/test/common/CMakeLists.txt
index 730607d2..810c68d5 100644
--- a/test/common/CMakeLists.txt
+++ b/test/common/CMakeLists.txt
@@ -1,5 +1,6 @@
add_executable(cru_base_test
HandlerRegistryTest.cpp
+ PropertyTreeTest.cpp
StringTest.cpp
StringUtilTest.cpp
)
diff --git a/test/common/PropertyTreeTest.cpp b/test/common/PropertyTreeTest.cpp
new file mode 100644
index 00000000..03b8971a
--- /dev/null
+++ b/test/common/PropertyTreeTest.cpp
@@ -0,0 +1,26 @@
+#include "cru/common/PropertyTree.hpp"
+
+#include <gtest/gtest.h>
+
+TEST(PropertyTree, Test) {
+ using cru::PropertySubTreeRef;
+ using cru::PropertyTree;
+
+ PropertyTree tree({
+ {u"k1", u"v1"},
+ {u"k2", u"v2"},
+ {u"k3.sub", u"v3"},
+ });
+
+ ASSERT_EQ(tree.GetValue(u"k1"), u"v1");
+ ASSERT_EQ(tree.GetValue(u"k2"), u"v2");
+ ASSERT_EQ(tree.GetValue(u"k3.sub"), u"v3");
+
+ PropertySubTreeRef sub_tree = tree.GetSubTreeRef(u"k3");
+ ASSERT_EQ(sub_tree.GetValue(u"sub"), u"v3");
+
+ PropertySubTreeRef root_tree = sub_tree.GetParent();
+ ASSERT_EQ(root_tree.GetValue(u"k1"), u"v1");
+ ASSERT_EQ(root_tree.GetValue(u"k2"), u"v2");
+ ASSERT_EQ(root_tree.GetValue(u"k3.sub"), u"v3");
+}