aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/headless/main.cpp80
-rw-r--r--src/openvic-simulation/Modifier.cpp64
-rw-r--r--src/openvic-simulation/Modifier.hpp18
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp4
-rw-r--r--src/openvic-simulation/economy/Building.hpp2
-rw-r--r--src/openvic-simulation/map/TerrainType.cpp8
-rw-r--r--src/openvic-simulation/map/TerrainType.hpp4
-rw-r--r--src/openvic-simulation/types/IdentifierRegistry.hpp162
-rw-r--r--src/openvic-simulation/utility/Logger.cpp16
-rw-r--r--src/openvic-simulation/utility/Logger.hpp33
10 files changed, 220 insertions, 171 deletions
diff --git a/src/headless/main.cpp b/src/headless/main.cpp
index e15005b..6cb6661 100644
--- a/src/headless/main.cpp
+++ b/src/headless/main.cpp
@@ -7,36 +7,17 @@
using namespace OpenVic;
-static char const* get_program_name(char const* name) {
- static constexpr char const* missing_name = "<program>";
- if (name == nullptr) return missing_name;
- char const* last_separator = name;
- while (*name != '\0') {
- if (*name == '/' || *name == '\\') {
- last_separator = name + 1;
- }
- ++name;
- }
- if (*last_separator == '\0') return missing_name;
- return last_separator;
-}
-
-static void print_help(char const* program_name) {
- std::cout
+static void print_help(std::ostream& stream, char const* program_name) {
+ stream
<< "Usage: " << program_name << " [-h] [-t] [-b <path>] [path]+\n"
<< " -h : Print this help message and exit the program.\n"
<< " -t : Run tests after loading defines.\n"
<< " -b : Use the following path as the base directory (instead of searching for one).\n"
+ << " -s : Use the following path as a hint to search for a base directory.\n"
<< "Any following paths are read as mod directories, with priority starting at one above the base directory.\n"
<< "(Paths with spaces need to be enclosed in \"quotes\").\n";
}
-static void setup_logger_funcs() {
- Logger::set_info_func([](std::string&& str) { std::cout << str; });
- Logger::set_warning_func([](std::string&& str) { std::cerr << str; });
- Logger::set_error_func([](std::string&& str) { std::cerr << str; });
-}
-
static bool headless_load(GameManager& game_manager, Dataloader const& dataloader) {
bool ret = true;
@@ -63,8 +44,6 @@ static bool headless_load(GameManager& game_manager, Dataloader const& dataloade
static bool run_headless(Dataloader::path_vector_t const& roots, bool run_tests) {
bool ret = true;
- setup_logger_funcs();
-
Dataloader dataloader;
if (!dataloader.set_roots(roots)) {
Logger::error("Failed to set dataloader roots!");
@@ -93,36 +72,51 @@ static bool run_headless(Dataloader::path_vector_t const& roots, bool run_tests)
*/
int main(int argc, char const* argv[]) {
- char const* program_name = get_program_name(argc > 0 ? argv[0] : nullptr);
+ Logger::set_logger_funcs();
+ char const* program_name = Logger::get_filename(argc > 0 ? argv[0] : nullptr, "<program>");
fs::path root;
bool run_tests = false;
-
int argn = 0;
+
+ /* Reads the next argument and converts it to a path via path_transform. If reading or converting fails, an error
+ * message and the help text are displayed, along with returning false to signify the program should exit.
+ */
+ const auto _read = [&root, &argn, argc, argv, program_name](std::string_view command, std::string_view path_use, auto path_transform) -> bool {
+ if (root.empty()) {
+ if (++argn < argc) {
+ char const* path = argv[argn];
+ root = path_transform(path);
+ if (!root.empty()) {
+ return true;
+ } else {
+ std::cerr << "Empty path after giving \"" << path << "\" to " << path_use << " command line argument \"" << command << "\"." << std::endl;
+ }
+ } else {
+ std::cerr << "Missing path after " << path_use << " command line argument \"" << command << "\"." << std::endl;
+ }
+ } else {
+ std::cerr << "Duplicate " << path_use << " command line argument \"-b\"." << std::endl;
+ }
+ print_help(std::cerr, program_name);
+ return false;
+ };
+
while (++argn < argc) {
char const* arg = argv[argn];
if (strcmp(arg, "-h") == 0) {
- print_help(program_name);
+ print_help(std::cout, program_name);
return 0;
} else if (strcmp(arg, "-t") == 0) {
run_tests = true;
} else if (strcmp(arg, "-b") == 0) {
- if (root.empty()) {
- if (++argn < argc) {
- root = argv[argn];
- if (!root.empty()) {
- continue;
- } else {
- std::cerr << "Empty path after base directory command line argument \"-b\"." << std::endl;
- }
- } else {
- std::cerr << "Missing path after base directory command line argument \"-b\"." << std::endl;
- }
- } else {
- std::cerr << "Duplicate base directory command line argument \"-b\"." << std::endl;
+ if (!_read("-b", "base directory", std::identity{})) {
+ return -1;
+ }
+ } else if (strcmp(arg, "-s") == 0) {
+ if (!_read("-s", "search hint", Dataloader::search_for_game_path)) {
+ return -1;
}
- print_help(program_name);
- return -1;
} else {
break;
}
@@ -131,7 +125,7 @@ int main(int argc, char const* argv[]) {
root = Dataloader::search_for_game_path();
if (root.empty()) {
std::cerr << "Search for base directory path failed!" << std::endl;
- print_help(program_name);
+ print_help(std::cerr, program_name);
return -1;
}
}
diff --git a/src/openvic-simulation/Modifier.cpp b/src/openvic-simulation/Modifier.cpp
index 1273fdd..fc5dcaf 100644
--- a/src/openvic-simulation/Modifier.cpp
+++ b/src/openvic-simulation/Modifier.cpp
@@ -154,38 +154,72 @@ bool ModifierManager::setup_modifier_effects() {
ret &= add_modifier_effect("min_build_university", true, ModifierEffect::format_t::INT);
ret &= add_modifier_effect("max_bank", true, ModifierEffect::format_t::INT);
ret &= add_modifier_effect("min_build_bank", true, ModifierEffect::format_t::INT);
-
+
modifier_effects.lock();
return ret;
}
-node_callback_t ModifierManager::expect_modifier_value_and_default(callback_t<ModifierValue&&> modifier_callback, key_value_callback_t default_callback) const {
- return [this, modifier_callback, default_callback](ast::NodeCPtr root) -> bool {
- ModifierValue modifier;
- bool ret = expect_dictionary(
- [this, &modifier, default_callback](std::string_view key, ast::NodeCPtr value) -> bool {
- ModifierEffect const* effect = get_modifier_effect_by_identifier(key);
- if (effect != nullptr) {
- if (modifier.values.find(effect) == modifier.values.end()) {
- return expect_fixed_point(
- assign_variable_callback(modifier.values[effect])
- )(value);
- }
+key_value_callback_t ModifierManager::_modifier_effect_callback(
+ ModifierValue& modifier, key_value_callback_t default_callback,
+ ModifierEffectValidator auto effect_validator) const {
+
+ return [this, &modifier, default_callback, effect_validator](std::string_view key, ast::NodeCPtr value) -> bool {
+ ModifierEffect const* effect = get_modifier_effect_by_identifier(key);
+ if (effect != nullptr) {
+ if (effect_validator(*effect)) {
+ if (modifier.values.find(effect) == modifier.values.end()) {
+ return expect_fixed_point(
+ assign_variable_callback(modifier.values[effect])
+ )(value);
+ } else {
Logger::error("Duplicate modifier effect: ", key);
return false;
}
- return default_callback(key, value);
+ } else {
+ Logger::error("Failed to validate modifier effect: ", key);
+ return false;
}
- )(root);
+ }
+ return default_callback(key, value);
+ };
+}
+
+node_callback_t ModifierManager::expect_validated_modifier_value_and_default(callback_t<ModifierValue&&> modifier_callback,
+ key_value_callback_t default_callback, ModifierEffectValidator auto effect_validator) const {
+ return [this, modifier_callback, default_callback, effect_validator](ast::NodeCPtr root) -> bool {
+ ModifierValue modifier;
+ bool ret = expect_dictionary(_modifier_effect_callback(modifier, default_callback, effect_validator))(root);
ret &= modifier_callback(std::move(modifier));
return ret;
};
}
+node_callback_t ModifierManager::expect_validated_modifier_value(callback_t<ModifierValue&&> modifier_callback,
+ ModifierEffectValidator auto effect_validator) const {
+ return expect_validated_modifier_value_and_default(modifier_callback, key_value_invalid_callback, effect_validator);
+}
+
+node_callback_t ModifierManager::expect_modifier_value_and_default(callback_t<ModifierValue&&> modifier_callback, key_value_callback_t default_callback) const {
+ return expect_validated_modifier_value_and_default(modifier_callback, default_callback,
+ [](ModifierEffect const&) -> bool { return true; }
+ );
+}
node_callback_t ModifierManager::expect_modifier_value(callback_t<ModifierValue&&> modifier_callback) const {
return expect_modifier_value_and_default(modifier_callback, key_value_invalid_callback);
}
+node_callback_t ModifierManager::expect_whitelisted_modifier_value_and_default(callback_t<ModifierValue&&> modifier_callback, std::set<std::string, std::less<void>> const& whitelist, key_value_callback_t default_callback) const {
+ return expect_validated_modifier_value_and_default(modifier_callback, default_callback,
+ [&whitelist](ModifierEffect const& effect) -> bool {
+ return whitelist.contains(effect.get_identifier());
+ }
+ );
+}
+
+node_callback_t ModifierManager::expect_whitelisted_modifier_value(callback_t<ModifierValue&&> modifier_callback, std::set<std::string, std::less<void>> const& whitelist) const {
+ return expect_whitelisted_modifier_value_and_default(modifier_callback, whitelist, key_value_invalid_callback);
+}
+
node_callback_t ModifierManager::expect_modifier_value_and_key_map_and_default(callback_t<ModifierValue&&> modifier_callback, key_value_callback_t default_callback, key_map_t&& key_map) const {
return [this, modifier_callback, key_map = std::move(key_map)](ast::NodeCPtr node) mutable -> bool {
bool ret = expect_modifier_value_and_default(
diff --git a/src/openvic-simulation/Modifier.hpp b/src/openvic-simulation/Modifier.hpp
index 663d359..0801aa5 100644
--- a/src/openvic-simulation/Modifier.hpp
+++ b/src/openvic-simulation/Modifier.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include <set>
+
#include "openvic-simulation/types/IdentifierRegistry.hpp"
namespace OpenVic {
@@ -92,12 +94,20 @@ namespace OpenVic {
Date const& get_expiry_date() const;
};
+ template<typename Fn>
+ concept ModifierEffectValidator = std::predicate<Fn, ModifierEffect const&>;
+
struct ModifierManager {
private:
IdentifierRegistry<ModifierEffect> modifier_effects;
IdentifierRegistry<Modifier> modifiers;
+ /* effect_validator takes in ModifierEffect const& */
+ NodeTools::key_value_callback_t _modifier_effect_callback(ModifierValue& modifier,
+ NodeTools::key_value_callback_t default_callback,
+ ModifierEffectValidator auto effect_validator) const;
+
public:
ModifierManager();
@@ -109,9 +119,17 @@ namespace OpenVic {
bool setup_modifier_effects();
+ NodeTools::node_callback_t expect_validated_modifier_value_and_default(NodeTools::callback_t<ModifierValue&&> modifier_callback,
+ NodeTools::key_value_callback_t default_callback, ModifierEffectValidator auto effect_validator) const;
+ NodeTools::node_callback_t expect_validated_modifier_value(NodeTools::callback_t<ModifierValue&&> modifier_callback,
+ ModifierEffectValidator auto effect_validator) const;
+
NodeTools::node_callback_t expect_modifier_value_and_default(NodeTools::callback_t<ModifierValue&&> modifier_callback, NodeTools::key_value_callback_t default_callback) const;
NodeTools::node_callback_t expect_modifier_value(NodeTools::callback_t<ModifierValue&&> modifier_callback) const;
+ NodeTools::node_callback_t expect_whitelisted_modifier_value_and_default(NodeTools::callback_t<ModifierValue&&> modifier_callback, std::set<std::string, std::less<void>> const& whitelist, NodeTools::key_value_callback_t default_callback) const;
+ NodeTools::node_callback_t expect_whitelisted_modifier_value(NodeTools::callback_t<ModifierValue&&> modifier_callback, std::set<std::string, std::less<void>> const& whitelist) const;
+
NodeTools::node_callback_t expect_modifier_value_and_key_map_and_default(NodeTools::callback_t<ModifierValue&&> modifier_callback, NodeTools::key_value_callback_t default_callback, NodeTools::key_map_t&& key_map) const;
NodeTools::node_callback_t expect_modifier_value_and_key_map(NodeTools::callback_t<ModifierValue&&> modifier_callback, NodeTools::key_map_t&& key_map) const;
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp
index 5134054..72e3113 100644
--- a/src/openvic-simulation/dataloader/Dataloader.cpp
+++ b/src/openvic-simulation/dataloader/Dataloader.cpp
@@ -46,8 +46,8 @@ constexpr bool path_equals(std::string_view lhs, std::string_view rhs) {
}
template<typename LT, typename RT>
-constexpr bool filename_equals(const LT& lhs, const RT& rhs) {
- std::string_view left, right;
+bool filename_equals(const LT& lhs, const RT& rhs) {
+ std::string left, right;
if constexpr (std::same_as<LT, std::filesystem::path>)
left = lhs.filename().string();
else left = lhs;
diff --git a/src/openvic-simulation/economy/Building.hpp b/src/openvic-simulation/economy/Building.hpp
index cbf5bfd..b56c9a2 100644
--- a/src/openvic-simulation/economy/Building.hpp
+++ b/src/openvic-simulation/economy/Building.hpp
@@ -32,7 +32,7 @@ namespace OpenVic {
private:
BuildingType const& type;
- ModifierValue modifier;
+ const ModifierValue modifier;
const std::string on_completion; //probably sound played on completion
const fixed_point_t completion_size;
const level_t max_level;
diff --git a/src/openvic-simulation/map/TerrainType.cpp b/src/openvic-simulation/map/TerrainType.cpp
index 017b220..8624cdb 100644
--- a/src/openvic-simulation/map/TerrainType.cpp
+++ b/src/openvic-simulation/map/TerrainType.cpp
@@ -5,8 +5,12 @@
using namespace OpenVic;
using namespace OpenVic::NodeTools;
-TerrainType::TerrainType(std::string_view new_identifier, colour_t new_colour, ModifierValue&& new_values, bool new_is_water)
- : HasIdentifierAndColour { new_identifier, new_colour, true, false }, ModifierValue { std::move(new_values) }, is_water { new_is_water } {}
+TerrainType::TerrainType(std::string_view new_identifier, colour_t new_colour, ModifierValue&& new_modifier, bool new_is_water)
+ : HasIdentifierAndColour { new_identifier, new_colour, true, false }, modifier { std::move(new_modifier) }, is_water { new_is_water } {}
+
+ModifierValue const& TerrainType::get_modifier() const {
+ return modifier;
+}
bool TerrainType::get_is_water() const {
return is_water;
diff --git a/src/openvic-simulation/map/TerrainType.hpp b/src/openvic-simulation/map/TerrainType.hpp
index 1353130..edda0a9 100644
--- a/src/openvic-simulation/map/TerrainType.hpp
+++ b/src/openvic-simulation/map/TerrainType.hpp
@@ -9,13 +9,15 @@ namespace OpenVic {
friend struct TerrainTypeManager;
private:
+ const ModifierValue modifier;
const bool is_water;
- TerrainType(std::string_view new_identifier, colour_t new_colour, ModifierValue&& new_values, bool new_is_water);
+ TerrainType(std::string_view new_identifier, colour_t new_colour, ModifierValue&& new_modifier, bool new_is_water);
public:
TerrainType(TerrainType&&) = default;
+ ModifierValue const& get_modifier() const;
bool get_is_water() const;
};
diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp
index b2f52b2..1a03e75 100644
--- a/src/openvic-simulation/types/IdentifierRegistry.hpp
+++ b/src/openvic-simulation/types/IdentifierRegistry.hpp
@@ -103,11 +103,10 @@ namespace OpenVic {
return true;
}
- template<typename T>
- using get_identifier_func_t = std::string_view(T::*)(void) const;
-
- template<typename _Base, std::derived_from<_Base> _Type, get_identifier_func_t<_Base> get_identifier,
- typename _Storage, _Type* (*get_ptr)(_Storage&), _Type const* (*get_cptr)(_Storage const&)>
+ /* _GetIdentifier - takes _Type const* and returns std::string_view
+ * _GetPointer - takes _Storage [const]& and returns T [const]*
+ */
+ template<typename _Type, typename _Storage, typename _GetIdentifier, typename _GetPointer>
class UniqueKeyRegistry {
const std::string name;
@@ -116,12 +115,15 @@ namespace OpenVic {
bool locked = false;
string_map_t<size_t> identifier_index_map;
+ _GetIdentifier GetIdentifier;
+ _GetPointer GetPointer;
+
public:
using value_type = _Type;
using storage_type = _Storage;
- UniqueKeyRegistry(std::string_view new_name, bool new_log_lock = true)
- : name { new_name }, log_lock { new_log_lock } {}
+ UniqueKeyRegistry(std::string_view new_name, bool new_log_lock = true, _GetIdentifier new_GetIdentifier = {}, _GetPointer new_GetPointer = {})
+ : name { new_name }, log_lock { new_log_lock }, GetIdentifier { new_GetIdentifier }, GetPointer { new_GetPointer } {}
std::string_view get_name() const {
return name;
@@ -132,8 +134,7 @@ namespace OpenVic {
Logger::error("Cannot add item to the ", name, " registry - locked!");
return false;
}
- value_type const* new_item = (*get_cptr)(item);
- const std::string_view new_identifier = (new_item->*get_identifier)();
+ const std::string_view new_identifier = GetIdentifier(GetPointer(item));
value_type const* old_item = get_item_by_identifier(new_identifier);
if (old_item != nullptr) {
return duplicate_callback(name, new_identifier);
@@ -178,30 +179,47 @@ namespace OpenVic {
}
}
- value_type* get_item_by_identifier(std::string_view identifier) {
- const typename decltype(identifier_index_map)::const_iterator it = identifier_index_map.find(identifier);
- if (it != identifier_index_map.end()) return (*get_ptr)(items[it->second]);
- return nullptr;
+#define GETTERS \
+ value_type _const* get_item_by_identifier(std::string_view identifier) _const { \
+ const typename decltype(identifier_index_map)::const_iterator it = identifier_index_map.find(identifier); \
+ if (it != identifier_index_map.end()) return GetPointer(items[it->second]); \
+ return nullptr; \
+ } \
+ value_type _const* get_item_by_index(size_t index) _const { \
+ return index < items.size() ? &items[index] : nullptr; \
+ } \
+ NodeTools::callback_t<std::string_view> expect_item_identifier(NodeTools::callback_t<value_type _const&> callback) _const { \
+ return [this, callback](std::string_view identifier) -> bool { \
+ value_type _const* item = get_item_by_identifier(identifier); \
+ if (item != nullptr) return callback(*item); \
+ Logger::error("Invalid ", name, ": ", identifier); \
+ return false; \
+ }; \
+ } \
+ NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t<value_type _const&, ast::NodeCPtr> callback) _const { \
+ return NodeTools::expect_dictionary([this, callback](std::string_view key, ast::NodeCPtr value) -> bool { \
+ value_type _const* item = get_item_by_identifier(key); \
+ if (item != nullptr) { \
+ return callback(*item, value); \
+ } \
+ Logger::error("Invalid ", name, " identifier: ", key); \
+ return false; \
+ }); \
}
- value_type const* get_item_by_identifier(std::string_view identifier) const {
- const typename decltype(identifier_index_map)::const_iterator it = identifier_index_map.find(identifier);
- if (it != identifier_index_map.end()) return (*get_cptr)(items[it->second]);
- return nullptr;
- }
+#define _const
+GETTERS
+#undef _const
+#define _const const
+GETTERS
+#undef _const
+
+#undef GETTERS
bool has_identifier(std::string_view identifier) const {
return get_item_by_identifier(identifier) != nullptr;
}
- value_type* get_item_by_index(size_t index) {
- return index < items.size() ? &items[index] : nullptr;
- }
-
- value_type const* get_item_by_index(size_t index) const {
- return index < items.size() ? &items[index] : nullptr;
- }
-
bool has_index(size_t index) const {
return get_item_by_index(index) != nullptr;
}
@@ -217,46 +235,6 @@ namespace OpenVic {
return identifiers;
}
- NodeTools::callback_t<std::string_view> expect_item_identifier(NodeTools::callback_t<value_type&> callback) {
- return [this, callback](std::string_view identifier) -> bool {
- value_type* item = get_item_by_identifier(identifier);
- if (item != nullptr) return callback(*item);
- Logger::error("Invalid ", name, ": ", identifier);
- return false;
- };
- }
-
- NodeTools::callback_t<std::string_view> expect_item_identifier(NodeTools::callback_t<value_type const&> callback) const {
- return [this, callback](std::string_view identifier) -> bool {
- value_type const* item = get_item_by_identifier(identifier);
- if (item != nullptr) return callback(*item);
- Logger::error("Invalid ", name, ": ", identifier);
- return false;
- };
- }
-
- NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t<value_type&, ast::NodeCPtr> callback) {
- return NodeTools::expect_dictionary([this, callback](std::string_view key, ast::NodeCPtr value) -> bool {
- value_type* item = get_item_by_identifier(key);
- if (item != nullptr) {
- return callback(*item, value);
- }
- Logger::error("Invalid ", name, " identifier: ", key);
- return false;
- });
- }
-
- NodeTools::node_callback_t expect_item_dictionary(NodeTools::callback_t<value_type const&, ast::NodeCPtr> callback) const {
- return NodeTools::expect_dictionary([this, callback](std::string_view key, ast::NodeCPtr value) -> bool {
- value_type const* item = get_item_by_identifier(key);
- if (item != nullptr) {
- return callback(*item, value);
- }
- Logger::error("Invalid ", name, " identifier: ", key);
- return false;
- });
- }
-
NodeTools::node_callback_t expect_item_decimal_map(NodeTools::callback_t<decimal_map_t<value_type const*>&&> callback) const {
return [this, callback](ast::NodeCPtr node) -> bool {
decimal_map_t<value_type const*> map;
@@ -272,35 +250,47 @@ namespace OpenVic {
}
};
+ /* Standard value storage */
template<typename T>
- [[nodiscard]] inline constexpr T* _addressof(T& v) noexcept {
- return std::addressof<T>(v);
- }
+ struct _addressof {
+ constexpr T* operator()(T& item) const {
+ return std::addressof(item);
+ }
+ constexpr T const* operator()(T const& item) const {
+ return std::addressof(item);
+ }
+ };
+ template<typename _Type, typename _GetIdentifier>
+ using ValueRegistry = UniqueKeyRegistry<_Type, _Type, _GetIdentifier, _addressof<_Type>>;
+
+ /* std::unique_ptr dynamic storage */
template<typename T>
- const T* _addressof(const T&&) = delete;
+ struct _uptr_get {
+ constexpr T* operator()(std::unique_ptr<T>& item) const {
+ return item.get();
+ }
+ constexpr T const* operator()(std::unique_ptr<T> const& item) const {
+ return item.get();
+ }
+ };
- template<typename _Base, std::derived_from<_Base> _Type, get_identifier_func_t<_Base> get_identifier>
- using ValueRegistry = UniqueKeyRegistry<_Base, _Type, get_identifier, _Type, _addressof<_Type>, _addressof<const _Type>>;
+ template<typename _Type, typename _GetIdentifier>
+ using InstanceRegistry = UniqueKeyRegistry<_Type, std::unique_ptr<_Type>, _GetIdentifier, _uptr_get<_Type>>;
- template<typename _Type>
- constexpr _Type* get_ptr(std::unique_ptr<_Type>& storage) {
- return storage.get();
- }
- template<typename _Type>
- constexpr _Type const* get_cptr(std::unique_ptr<_Type> const& storage) {
- return storage.get();
- }
-
- template<typename _Base, std::derived_from<_Base> _Type, get_identifier_func_t<_Base> get_identifier>
- using InstanceRegistry = UniqueKeyRegistry<_Base, _Type, get_identifier, std::unique_ptr<_Type>,
- get_ptr<_Type>, get_cptr<_Type>>;
+ /* HasIdentifier versions */
+ template<std::derived_from<HasIdentifier> T>
+ struct _get_identifier {
+ constexpr std::string_view operator()(T const* item) const {
+ return item->get_identifier();
+ }
+ };
template<std::derived_from<HasIdentifier> _Type>
- using IdentifierRegistry = ValueRegistry<HasIdentifier, _Type, &HasIdentifier::get_identifier>;
+ using IdentifierRegistry = ValueRegistry<_Type, _get_identifier<_Type>>;
template<std::derived_from<HasIdentifier> _Type>
- using IdentifierInstanceRegistry = InstanceRegistry<HasIdentifier, _Type, &HasIdentifier::get_identifier>;
+ using IdentifierInstanceRegistry = InstanceRegistry<_Type, _get_identifier<_Type>>;
#define IDENTIFIER_REGISTRY_ACCESSORS_CUSTOM_PLURAL(singular, plural) \
void lock_##plural() { plural.lock(); } \
diff --git a/src/openvic-simulation/utility/Logger.cpp b/src/openvic-simulation/utility/Logger.cpp
index fca08a5..68c43dd 100644
--- a/src/openvic-simulation/utility/Logger.cpp
+++ b/src/openvic-simulation/utility/Logger.cpp
@@ -4,19 +4,19 @@
using namespace OpenVic;
-Logger::log_func_t Logger::info_func {};
-Logger::log_queue_t Logger::info_queue {};
-Logger::log_func_t Logger::warning_func {};
-Logger::log_queue_t Logger::warning_queue {};
-Logger::log_func_t Logger::error_func {};
-Logger::log_queue_t Logger::error_queue {};
+void Logger::set_logger_funcs() {
+ Logger::set_info_func([](std::string&& str) { std::cout << str; });
+ Logger::set_warning_func([](std::string&& str) { std::cerr << str; });
+ Logger::set_error_func([](std::string&& str) { std::cerr << str; });
+}
-char const* Logger::get_filename(char const* filepath) {
- if (filepath == nullptr) return nullptr;
+char const* Logger::get_filename(char const* filepath, char const* default_path) {
+ if (filepath == nullptr) return default_path;
char const* last_slash = filepath;
while (*filepath != '\0') {
if (*filepath == '\\' || *filepath == '/') last_slash = filepath + 1;
filepath++;
}
+ if (*last_slash == '\0') return default_path;
return last_slash;
}
diff --git a/src/openvic-simulation/utility/Logger.hpp b/src/openvic-simulation/utility/Logger.hpp
index 11cada5..d60e59e 100644
--- a/src/openvic-simulation/utility/Logger.hpp
+++ b/src/openvic-simulation/utility/Logger.hpp
@@ -32,7 +32,7 @@ namespace OpenVic {
};
#endif
- class Logger {
+ class Logger final {
using log_func_t = std::function<void(std::string&&)>;
using log_queue_t = std::queue<std::string>;
@@ -42,39 +42,46 @@ namespace OpenVic {
using source_location = OpenVic::source_location;
#endif
- static char const* get_filename(char const* filepath);
+ public:
+ static void set_logger_funcs();
+ static char const* get_filename(char const* filepath, char const* default_path = nullptr);
+
+ private:
+ struct log_channel_t {
+ log_func_t func;
+ log_queue_t queue;
+ };
template<typename... Ts>
struct log {
- log(log_func_t log_func, log_queue_t& log_queue, Ts&&... ts, source_location const& location) {
+ log(log_channel_t& log_channel, Ts&&... ts, source_location const& location) {
std::stringstream stream;
stream << "\n" << get_filename(location.file_name()) << "("
//<< location.line() << ") `" << location.function_name() << "`: ";
<< location.line() << "): ";
((stream << std::forward<Ts>(ts)), ...);
stream << std::endl;
- log_queue.push(stream.str());
- if (log_func) {
+ log_channel.queue.push(stream.str());
+ if (log_channel.func) {
do {
- log_func(std::move(log_queue.front()));
- log_queue.pop();
- } while (!log_queue.empty());
+ log_channel.func(std::move(log_channel.queue.front()));
+ log_channel.queue.pop();
+ } while (!log_channel.queue.empty());
}
}
};
#define LOG_FUNC(name) \
private: \
- static log_func_t name##_func; \
- static log_queue_t name##_queue; \
+ static inline log_channel_t name##_channel{}; \
public: \
- static void set_##name##_func(log_func_t log_func) { \
- name##_func = log_func; \
+ static inline void set_##name##_func(log_func_t log_func) { \
+ name##_channel.func = log_func; \
} \
template<typename... Ts> \
struct name { \
name(Ts&&... ts, source_location const& location = source_location::current()) { \
- log<Ts...>{ name##_func, name##_queue, std::forward<Ts>(ts)..., location }; \
+ log<Ts...>{ name##_channel, std::forward<Ts>(ts)..., location }; \
} \
}; \
template<typename... Ts> \