diff --git a/CMakeLists.txt b/CMakeLists.txt index fe3f4b1..dd73d4d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,9 +40,12 @@ target_sources(nf7 nf7.cc nf7.hh + common/dir.hh common/queue.hh common/type_info.hh common/yas.hh + + file/system_dir.cc ) target_link_libraries(nf7 PRIVATE diff --git a/common/dir.hh b/common/dir.hh new file mode 100644 index 0000000..f41ca67 --- /dev/null +++ b/common/dir.hh @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include +#include + +#include "nf7.hh" + + +namespace nf7 { + +class Dir : public File::Interface { + public: + class DuplicateException; + + Dir() = default; + virtual ~Dir() = default; + Dir(const Dir&) = default; + Dir(Dir&&) = default; + Dir& operator=(const Dir&) = default; + Dir& operator=(Dir&&) = default; + + virtual File& Add(std::string_view, std::unique_ptr&&) = 0; + virtual std::unique_ptr Remove(std::string_view) noexcept = 0; + + virtual std::map FetchItems() const noexcept = 0; +}; +class Dir::DuplicateException : public Exception { + public: + using Exception::Exception; +}; + +class DirItem : public File::Interface { + public: + DirItem() = default; + virtual ~DirItem() = default; + DirItem(const DirItem&) = delete; + DirItem(DirItem&&) = delete; + DirItem& operator=(const DirItem&) = delete; + DirItem& operator=(DirItem&&) = delete; + + virtual void UpdateTree() noexcept { } + virtual void UpdateMenu() noexcept { } + virtual void UpdateTooltip() noexcept { } +}; + +} // namespace nf7 diff --git a/file/system_dir.cc b/file/system_dir.cc new file mode 100644 index 0000000..8301718 --- /dev/null +++ b/file/system_dir.cc @@ -0,0 +1,95 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include "nf7.hh" + +#include "common/dir.hh" +#include "common/ptr_selector.hh" +#include "common/type_info.hh" +#include "common/yas.hh" + + +namespace nf7 { +namespace { + +class Dir final : public File, public nf7::Dir { + public: + static inline const GenericTypeInfo kType = {"System", "Dir", {"DirItem"}}; + + using ItemMap = std::map>; + + Dir(Env& env, ItemMap&& items = {}, bool shown = false) noexcept : + File(kType, env), items_(std::move(items)), shown_(shown) { + } + + Dir(Env& env, Deserializer& ar) : Dir(env) { + ar(items_, shown_); + } + void Serialize(Serializer& ar) const noexcept override { + ar(items_, shown_); + } + std::unique_ptr Clone(Env& env) const noexcept override { + ItemMap items; + for (const auto& item : items_) { + items[item.first] = item.second->Clone(env); + } + return std::make_unique(env, std::move(items)); + } + + void MoveUnder(File::Id parent) noexcept override { + File::MoveUnder(parent); + for (const auto& item : items_) { + item.second->MoveUnder(id()); + } + } + + File& Add(std::string_view name, std::unique_ptr&& f) override { + const auto sname = std::string(name); + + auto [itr, ok] = items_.emplace(sname, std::move(f)); + if (!ok) throw DuplicateException("item name duplication: "+sname); + + auto& ret = *itr->second; + if (id()) ret.MoveUnder(id()); + return ret; + } + std::unique_ptr Remove(std::string_view name) noexcept override { + auto itr = items_.find(std::string(name)); + if (itr == items_.end()) return nullptr; + + auto ret = std::move(itr->second); + items_.erase(itr); + if (id()) ret->MoveUnder(0); + return ret; + } + std::map FetchItems() const noexcept override { + std::map ret; + for (const auto& item : items_) { + ret[item.first] = item.second.get(); + } + return ret; + } + + void Update() noexcept override; + + File::Interface* iface(const std::type_info& t) noexcept override { + return PtrSelector(t).Select(this); + } + + private: + ItemMap items_; + + bool shown_; +}; + +void Dir::Update() noexcept { +} + +} +} // namespace nf7