#ifndef _SYSELEMENTS_HPP_ #define _SYSELEMENTS_HPP_ #include #include #include #include using namespace std; /** * @brief Represents a basic system element with a name. */ class SystemElement { public: string name; // Name of the system element. /** * @brief Constructor for SystemElement. * @param name Name of the element. */ SystemElement(string name) : name(name) {}; }; /** * @brief A container for managing system elements of type T. * * @tparam T Type of elements, must inherit from SystemElement. */ template class SystemElementContainer : public SystemElement { public: using MapType = unordered_map; // Map to store elements by name. using iterator = typename MapType::iterator; // Iterator for the map. using const_iterator = typename MapType::const_iterator; // Const iterator for the map. protected: unsigned int iter_count; // Counter for iterations (currently unused). MapType content; // Container for storing elements. /** * @brief Adds elements from a map to the container. * @param el_content Map of elements to add. */ void add(MapType el_content) { for (const auto &[key, value] : el_content) { add(value); } } public: /** * @brief Constructor for an empty container. * @param name Name of the container. */ SystemElementContainer(string name) : SystemElement(name) {}; /** * @brief Constructor with initial elements. * @param name Name of the container. * @param elements Vector of elements to add. */ SystemElementContainer(string name, vector elements) : SystemElement(name) { add(elements); } /** * @brief Adds a single element to the container with a given name. * @param name Name of the element to add. * @param element Pointer to the element to add. * @throws runtime_error If the element's name is empty or already exists. */ virtual void add(string name, T *element) { if ("" == name) { throw runtime_error("System elements with empty names are forbidden"); } if (exists(name)) { throw runtime_error("System elements of same names are forbidden"); } content.insert({name, element}); } /** * @brief Adds a single element to the container. * @param element Pointer to the element to add. * @throws runtime_error If the element's name is empty or already exists. */ virtual void add(T *element) { add (element->name, element); } /** * @brief Checks if an element exists in the container. * @param name Name of the element to check. * @return True if the element exists, false otherwise. */ bool exists(string name) { try { get(name); return true; } catch (const exception &e) { return false; } } /** * @brief Adds elements from another container. * @param elements Pointer to another container. */ void add(SystemElementContainer *elements) { add(elements->content); } /** * @brief Adds multiple elements from a vector. * @param elements Vector of elements to add. */ void add(vector elements) { for (auto &element : elements) { add(element); } } /** * @brief Retrieves an element by its name. * @param name Name of the element to retrieve. * @return Pointer to the element. * @throws runtime_error If the element is not found. */ T *get(string name) { auto it = content.find(name); if (it != content.end()) { return it->second; } else { throw runtime_error("System elements not found"); } } /** * @brief Merges an element by retrieving it or creating a new one if it doesn't exist. * @param name Name of the element. * @return Pointer to the merged or newly created element. */ /** * @brief Removes the element with the given name from the container. * The element itself is NOT deleted — caller owns it. * @return True if an element was removed, false if the name was absent. */ bool remove(string name) { return content.erase(name) > 0; } T *merge(string name) { if (exists(name)) { return get(name); } else { T *ret = new T(name); add(ret); return ret; } } size_t size() const { return content.size(); } /** * @brief Returns an iterator to the beginning of the container. * @return Iterator to the beginning. */ iterator begin() { return std::begin(content); } /** * @brief Returns an iterator to the end of the container. * @return Iterator to the end. */ iterator end() { return std::end(content); } /** * @brief Returns a constant iterator to the beginning of the container. * @return Constant iterator to the beginning. */ const_iterator begin() const { return std::begin(content); } /** * @brief Returns a constant iterator to the end of the container. * @return Constant iterator to the end. */ const_iterator end() const { return std::end(content); } }; #endif