From efe922f835bafced06199c123be24033d071f466 Mon Sep 17 00:00:00 2001 From: falsycat Date: Sat, 9 Sep 2023 09:21:17 +0900 Subject: [PATCH] add MetaEnv implementation --- core/CMakeLists.txt | 2 + core/meta_env.hh | 91 +++++++++++++++++++++++++++++++++++++++++++ core/meta_env_test.cc | 74 +++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+) create mode 100644 core/meta_env.hh create mode 100644 core/meta_env_test.cc diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index fa3ef39..aab96e6 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -32,6 +32,7 @@ target_sources(nf7_core clock.hh dealer.hh logger.hh + meta_env.hh version.hh ) @@ -50,6 +51,7 @@ target_sources(nf7_core_test uv/file_test.cc uv/parallelism_test.cc clock_test.cc + meta_env_test.cc ) target_link_libraries(nf7_core_test PRIVATE diff --git a/core/meta_env.hh b/core/meta_env.hh new file mode 100644 index 0000000..7f826f5 --- /dev/null +++ b/core/meta_env.hh @@ -0,0 +1,91 @@ +// No copyright +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "iface/subsys/meta_env.hh" + +namespace nf7::core { + +class NullMetaEnv : public subsys::MetaEnv { + public: + static inline const auto kInstance = std::make_shared(); + + public: + NullMetaEnv() noexcept : subsys::MetaEnv("nf7::core::NullMetaEnv") { } + + public: + Env* FindOr(std::string_view) const noexcept override { return nullptr; } + std::optional FindOr(uint64_t) const noexcept override { return std::nullopt; } + std::vector FetchAll() const override { return {}; } + std::shared_ptr parent() const noexcept override { return nullptr; } +}; + +class MetaEnv : public subsys::MetaEnv { + public: + using SharedPair = std::pair>; + + private: + static std::vector&& Sort(std::vector&& v) noexcept { + std::sort(v.begin(), v.end(), + [](const auto& a, const auto& b) { return a.first < b.first; }); + return v; + } + + public: + explicit MetaEnv(std::vector&& children, + const std::weak_ptr& parent = {}) noexcept + : subsys::MetaEnv("nf7::core::MetaEnv"), + children_(Sort(std::move(children))), + parent_(parent) { + assert(std::all_of(children_.begin(), children_.end(), + [](auto& x) { return x.second; })); + } + + public: + Env* FindOr(std::string_view name) const noexcept override { + const auto itr = std::lower_bound( + children_.cbegin(), children_.cend(), name, + [](const auto& a, const auto& b) { return a.first < b; }); + if (children_.cend() == itr || itr->first != name) { + return nullptr; + } + return itr->second.get(); + } + std::optional FindOr(uint64_t index) const noexcept override { + if (index >= children_.size()) { + return std::nullopt; + } + const auto& child = children_[index]; + return Pair {child.first, *child.second}; + } + + std::vector FetchAll() const override + try { + std::vector ret; + ret.reserve(children_.size()); + for (const auto& child : children_) { + ret.emplace_back(child.first, *child.second); + } + return ret; + } catch (const std::bad_alloc&) { + throw MemoryException {}; + } + + public: + std::shared_ptr parent() const noexcept override { + return parent_.lock(); + } + + private: + const std::vector children_; + const std::weak_ptr parent_; +}; + +} // namespace nf7::core diff --git a/core/meta_env_test.cc b/core/meta_env_test.cc new file mode 100644 index 0000000..ba2254d --- /dev/null +++ b/core/meta_env_test.cc @@ -0,0 +1,74 @@ +// No copyright +#include "core/meta_env.hh" + +#include + +#include "iface/env.hh" + + +static inline std::shared_ptr MakeEmptyEnv() { + return std::make_shared(nf7::SimpleEnv::FactoryMap {}); +} +static inline bool MatchPair(const std::optional& a, + const nf7::subsys::MetaEnv::Pair& b) { + return a && a->first == b.first && &a->second == &b.second; +} + +TEST(MetaEnv, FindOrByName) { + const auto a = MakeEmptyEnv(); + const auto b = MakeEmptyEnv(); + const auto c = MakeEmptyEnv(); + + nf7::core::MetaEnv sut { + { + {"b", b}, + {"c", c}, + {"a", a}, + }, + }; + + EXPECT_EQ(sut.FindOr(""), nullptr); + EXPECT_EQ(sut.FindOr("a"), a.get()); + EXPECT_EQ(sut.FindOr("b"), b.get()); + EXPECT_EQ(sut.FindOr("c"), c.get()); + EXPECT_EQ(sut.FindOr("d"), nullptr); +} + +TEST(MetaEnv, FindOrByIndex) { + const auto a = MakeEmptyEnv(); + const auto b = MakeEmptyEnv(); + const auto c = MakeEmptyEnv(); + + nf7::core::MetaEnv sut { + { + {"b", b}, + {"c", c}, + {"a", a}, + }, + }; + + EXPECT_TRUE(MatchPair(sut.FindOr(0), {"a", *a})); + EXPECT_TRUE(MatchPair(sut.FindOr(1), {"b", *b})); + EXPECT_TRUE(MatchPair(sut.FindOr(2), {"c", *c})); + EXPECT_EQ(sut.FindOr(3), std::nullopt); +} + +TEST(MetaEnv, FetchAll) { + const auto a = MakeEmptyEnv(); + const auto b = MakeEmptyEnv(); + const auto c = MakeEmptyEnv(); + + nf7::core::MetaEnv sut { + { + {"b", b}, + {"c", c}, + {"a", a}, + }, + }; + + const auto all = sut.FetchAll(); + EXPECT_EQ(all.size(), 3); + EXPECT_TRUE(MatchPair(all[0], {"a", *a})); + EXPECT_TRUE(MatchPair(all[1], {"b", *b})); + EXPECT_TRUE(MatchPair(all[2], {"c", *c})); +}