Reorganise the tree into business vs frontend as separate directories:
src/core/{domain,imports,app} (was system/, imports/, app/)
src/frontends/tui/ (was tui/ + main.cpp)
tests/tui/ (the FTXUI-coupled helper test)
All cross-dir #include paths rewritten; same-dir includes untouched.
CMake: essim_core is the frontend-agnostic business library — links libzip,
pugixml and bsdl, NO GUI toolkit. Each frontend is a self-contained
src/frontends/<name>/ (own CMakeLists, toolkit, main.cpp) that links
essim_core, selected with -DESSIM_FRONTEND=<name> (default tui; 'none' = core +
tests only, no toolkit fetched). FTXUI moved into the tui frontend. Tests are
split: essim_tests links essim_core (no FTXUI), essim_tui_tests links essim_tui.
Verified: default tui build green (ctest 2/2); ESSIM_FRONTEND=none builds the
core + tests with FTXUI never fetched and no `essim` binary.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
215 lines
5.5 KiB
C++
215 lines
5.5 KiB
C++
#ifndef _SYSELEMENTS_HPP_
|
|
#define _SYSELEMENTS_HPP_
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <unordered_map>
|
|
#include <stdexcept>
|
|
|
|
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 <typename T>
|
|
class SystemElementContainer : public SystemElement
|
|
{
|
|
public:
|
|
using MapType = unordered_map<string, T *>; // 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<T *> 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<T> *elements)
|
|
{
|
|
add(elements->content);
|
|
}
|
|
|
|
/**
|
|
* @brief Adds multiple elements from a vector.
|
|
* @param elements Vector of elements to add.
|
|
*/
|
|
void add(vector<T *> 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 |