diff options
Diffstat (limited to 'core/src/Model')
-rw-r--r-- | core/src/Model/Items.cpp | 83 | ||||
-rw-r--r-- | core/src/Model/Items.hpp | 146 | ||||
-rw-r--r-- | core/src/Model/Project.cpp | 22 | ||||
-rw-r--r-- | core/src/Model/Project.hpp | 13 | ||||
-rw-r--r-- | core/src/Model/fwd.hpp | 8 |
5 files changed, 271 insertions, 1 deletions
diff --git a/core/src/Model/Items.cpp b/core/src/Model/Items.cpp new file mode 100644 index 0000000..db2d39f --- /dev/null +++ b/core/src/Model/Items.cpp @@ -0,0 +1,83 @@ +#include "Items.hpp" + +#include <limits> +#include <utility> + +ItemBase::ItemBase() + : mId{ std::numeric_limits<size_t>::max() } { +} + +ItemBase::ItemBase(size_t id) + : mId{ id } { +} + +bool ItemBase::IsInvalid() const { + return mId == std::numeric_limits<size_t>::max(); +} + +size_t ItemBase::GetId() const { + return mId; +} + +ProductItem::ProductItem(size_t id, std::string name) + : ItemBase(id) + , mName{ std::move(name) } { +} + +const std::string& ProductItem::GetName() const { + return mName; +} + +void ProductItem::SetName(std::string name) { + mName = std::move(name); +} + +const std::string& ProductItem::GetDescription() const { + return mDescription; +} + +void ProductItem::SetDescription(std::string description) { + mDescription = std::move(description); +} + +FactoryItem::FactoryItem(size_t id, std::string name) + : ItemBase(id) + , mName{ std::move(name) } { +} + +const std::string& FactoryItem::GetName() const { + return mName; +} + +void FactoryItem::SetName(std::string name) { + mName = std::move(name); +} + +const std::string& FactoryItem::GetDescription() const { + return mDescription; +} + +void FactoryItem::SetDescription(std::string description) { + mDescription = std::move(description); +} + +CustomerItem::CustomerItem(size_t id, std::string name) + : ItemBase(id) + , mName{ std::move(name) } { +} + +const std::string& CustomerItem::GetName() const { + return mName; +} + +void CustomerItem::SetName(std::string name) { + mName = std::move(name); +} + +const std::string& CustomerItem::GetDescription() const { + return mDescription; +} + +void CustomerItem::SetDescription(std::string description) { + mDescription = std::move(description); +} diff --git a/core/src/Model/Items.hpp b/core/src/Model/Items.hpp new file mode 100644 index 0000000..0c7be41 --- /dev/null +++ b/core/src/Model/Items.hpp @@ -0,0 +1,146 @@ +#pragma once + +#include <tsl/array_map.h> +#include <cstddef> +#include <stdexcept> +#include <string> +#include <string_view> +#include <vector> + +/// Pointers and references returned by accessors are valid as long as no non-const functions have been called. +template <class T> +class ItemList { +public: + class Iterator { + private: + typename std::vector<T>::const_iterator mBackingIter; + + public: + Iterator(typename std::vector<T>::const_iterator it) + : mBackingIter{ it } { + } + + Iterator& operator++() { + ++mBackingIter; + return *this; + } + + Iterator& operator++(int) { + auto tmp = *this; + ++mBackingIter; + return tmp; + } + + Iterator& operator--() { + --mBackingIter; + return *this; + } + + Iterator& operator--(int) { + auto tmp = *this; + --mBackingIter; + return tmp; + } + + const T& operator*() const { + return *mBackingIter; + } + + friend bool operator==(const Iterator&, const Iterator&) = default; + }; + +private: + std::vector<T> mStorage; + tsl::array_map<char, size_t> mNameLookup; + +public: + template <class... Args> + T& Insert(std::string name, Args... args) { + auto iter = mNameLookup.find(name); + if (iter != mNameLookup.end()) { + throw std::runtime_error("Duplicate key."); + } + + size_t id = mStorage.size(); + mNameLookup.insert(name, id); + return mStorage.emplace_back(id, std::move(name), std::forward<Args>(args)...); + } + + const T* Find(size_t id) const { + return &mStorage[id]; + } + + const T* Find(std::string_view name) const { + auto iter = mNameLookup.find(name); + if (iter != mNameLookup.end()) { + return &mStorage[iter.value()]; + } else { + return nullptr; + } + } + + Iterator begin() const { + return Iterator(mStorage.begin()); + } + + Iterator end() const { + return Iterator(mStorage.end()); + } +}; + +class ItemBase { +private: + size_t mId; + +public: + ItemBase(); + ItemBase(size_t id); + + bool IsInvalid() const; + size_t GetId() const; +}; + +class ProductItem : public ItemBase { +private: + std::string mName; + std::string mDescription; + +public: + ProductItem() {} + ProductItem(size_t id, std::string name); + + const std::string& GetName() const; + void SetName(std::string mName); + const std::string& GetDescription() const; + void SetDescription(std::string description); +}; + +class FactoryItem : public ItemBase { +private: + std::string mName; + std::string mDescription; + +public: + FactoryItem() {} + FactoryItem(size_t id, std::string name); + + const std::string& GetName() const; + void SetName(std::string name); + const std::string& GetDescription() const; + void SetDescription(std::string description); +}; + +class CustomerItem : public ItemBase { +private: + std::string mName; + std::string mDescription; + +public: + CustomerItem() {} + CustomerItem(size_t id, std::string name); + + const std::string& GetName() const; + void SetName(std::string name); + const std::string& GetDescription() const; + void SetDescription(std::string description); +}; diff --git a/core/src/Model/Project.cpp b/core/src/Model/Project.cpp index c54a02c..f070940 100644 --- a/core/src/Model/Project.cpp +++ b/core/src/Model/Project.cpp @@ -25,11 +25,12 @@ Project Project::Load(const fs::path& path) { Project proj; proj.mRootPath = path.parent_path(); + proj.mRootPathString = proj.mRootPath.string(); Json::Value root; ifs >> root; - const auto& croot = root; // Use const reference so that accessors default to returning a null if not found, instead of siliently creating new elements + const auto& croot = root; // Use const reference so that accessors default to returning a null if not found, instead of silently creating new elements if (!croot.isObject()) { throw std::runtime_error(kInvalidFormatErr); } @@ -46,6 +47,7 @@ Project Project::Load(const fs::path& path) { Project Project::Create(std::string name, const fs::path& path) { Project proj; proj.mRootPath = path; + proj.mRootPathString = path.string(); proj.mName = std::move(name); return proj; } @@ -54,6 +56,10 @@ const fs::path& Project::GetPath() const { return mRootPath; } +const std::string& Project::GetPathString() const { + return mRootPathString; +} + const std::string& Project::GetName() const { return mName; } @@ -61,3 +67,17 @@ const std::string& Project::GetName() const { void Project::SetName(std::string name) { mName = std::move(name); } + +Json::Value Project::Serialize() { + Json::Value root(Json::objectValue); + + root["Name"] = mName; + + return root; +} + +void Project::WriteToDisk() { + auto root = Serialize(); + std::ofstream ofs(mRootPath / "cplt_project.json"); + ofs << root; +} diff --git a/core/src/Model/Project.hpp b/core/src/Model/Project.hpp index 7b5c7e3..23eafc1 100644 --- a/core/src/Model/Project.hpp +++ b/core/src/Model/Project.hpp @@ -1,11 +1,20 @@ #pragma once +#include "Model/Items.hpp" + #include <filesystem> #include <string> +#include <json/forwards.h> class Project { public: + ItemList<ProductItem> Products; + ItemList<FactoryItem> Factories; + ItemList<CustomerItem> Customers; + +private: std::filesystem::path mRootPath; + std::string mRootPathString; std::string mName; public: @@ -17,10 +26,14 @@ public: // Path to a *directory* that contains the project file. const std::filesystem::path& GetPath() const; + const std::string& GetPathString() const; const std::string& GetName() const; void SetName(std::string name); + Json::Value Serialize(); + void WriteToDisk(); + private: Project() = default; }; diff --git a/core/src/Model/fwd.hpp b/core/src/Model/fwd.hpp index 6bbc0b7..bf9a8cf 100644 --- a/core/src/Model/fwd.hpp +++ b/core/src/Model/fwd.hpp @@ -3,5 +3,13 @@ // GlobalStates.hpp class GlobalStates; +// Items.hpp +template <class T> +class ItemList; +class ItemBase; +class ProductItem; +class FactoryItem; +class CustomerItem; + // Project.hpp class Project; |