Files
essim/src/core/domain/syselmts.hpp
François 63ca17d048 build: split core/ from frontends/; prepare for multiple GUI/TUI targets
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>
2026-06-03 19:33:06 +02:00

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