aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation
diff options
context:
space:
mode:
author Hop311 <Hop3114@gmail.com>2024-01-14 12:27:56 +0100
committer GitHub <noreply@github.com>2024-01-14 12:27:56 +0100
commit2fcc7ccd409701f6bad343e57afe74bd05246b68 (patch)
tree8e2f7f4de34ec3d62e55f9918ce26900c16a5d0f /src/openvic-simulation
parent046e5619277c6f3dffbb29244b4b88029da31bee (diff)
parent70948572ef0fb5c6dae453c410fdaedfab36741b (diff)
Merge pull request #129 from OpenVicProject/registry-template-fun
Reworked `UniqueKeyRegistry` template params
Diffstat (limited to 'src/openvic-simulation')
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp2
-rw-r--r--src/openvic-simulation/interface/LoadBase.hpp40
-rw-r--r--src/openvic-simulation/misc/Modifier.cpp4
-rw-r--r--src/openvic-simulation/misc/Modifier.hpp11
-rw-r--r--src/openvic-simulation/types/IdentifierRegistry.hpp335
5 files changed, 243 insertions, 149 deletions
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp
index fd4f2b0..0078ed2 100644
--- a/src/openvic-simulation/dataloader/Dataloader.cpp
+++ b/src/openvic-simulation/dataloader/Dataloader.cpp
@@ -836,8 +836,10 @@ bool Dataloader::load_defines(GameManager& game_manager) {
ret = false;
}
if (!_load_technologies(game_manager)) {
+ Logger::error("Failed to load technologies!");
ret = false;
}
+ game_manager.get_modifier_manager().lock_modifier_effects();
if (!game_manager.get_politics_manager().get_rule_manager().setup_rules(
game_manager.get_economy_manager().get_building_type_manager()
)) {
diff --git a/src/openvic-simulation/interface/LoadBase.hpp b/src/openvic-simulation/interface/LoadBase.hpp
index 3ee7c83..74aece9 100644
--- a/src/openvic-simulation/interface/LoadBase.hpp
+++ b/src/openvic-simulation/interface/LoadBase.hpp
@@ -5,27 +5,27 @@
namespace OpenVic {
- template<typename... _Context>
+ template<typename... Context>
class LoadBase {
protected:
LoadBase() = default;
- virtual bool _fill_key_map(NodeTools::key_map_t&, _Context...) = 0;
+ virtual bool _fill_key_map(NodeTools::key_map_t&, Context...) = 0;
public:
LoadBase(LoadBase&&) = default;
virtual ~LoadBase() = default;
- bool load(ast::NodeCPtr node, _Context... context) {
+ bool load(ast::NodeCPtr node, Context... context) {
NodeTools::key_map_t key_map;
bool ret = _fill_key_map(key_map, context...);
ret &= NodeTools::expect_dictionary_key_map(std::move(key_map))(node);
return ret;
}
- template<std::derived_from<LoadBase<_Context...>> T, std::derived_from<T> U>
+ template<std::derived_from<LoadBase<Context...>> T, std::derived_from<T> U>
static NodeTools::node_callback_t _expect_instance(
- NodeTools::callback_t<std::unique_ptr<T>&&> callback, _Context... context
+ NodeTools::callback_t<std::unique_ptr<T>&&> callback, Context... context
) {
return [callback, &context...](ast::NodeCPtr node) -> bool {
std::unique_ptr<T> instance { std::make_unique<U>() };
@@ -38,14 +38,14 @@ namespace OpenVic {
OV_DETAIL_GET_TYPE_BASE_CLASS(LoadBase)
};
- template<typename... _Context>
- class Named : public LoadBase<_Context...> {
+ template<typename... Context>
+ class Named : public LoadBase<Context...> {
std::string PROPERTY(name);
protected:
Named() = default;
- virtual bool _fill_key_map(NodeTools::key_map_t& key_map, _Context...) override {
+ virtual bool _fill_key_map(NodeTools::key_map_t& key_map, Context...) override {
using namespace OpenVic::NodeTools;
return add_key_map_entries(key_map, "name", ONE_EXACTLY, expect_string(assign_variable_callback_string(name)));
}
@@ -64,19 +64,21 @@ namespace OpenVic {
OV_DETAIL_GET_TYPE
};
- template<typename T, typename... _Context>
- requires std::derived_from<T, Named<_Context...>>
- struct _get_name {
- constexpr std::string_view operator()(T const* item) const {
- return item->get_name();
+ template<typename Value, typename... Context>
+ requires std::derived_from<Value, Named<Context...>>
+ struct RegistryValueInfoNamed {
+ using value_type = Value;
+
+ static constexpr std::string_view get_identifier(value_type const& item) {
+ return item.get_name();
}
};
- template<typename T, typename... _Context>
- requires std::derived_from<T, Named<_Context...>>
- using NamedRegistry = ValueRegistry<T, _get_name<T, _Context...>>;
+ template<typename Value, typename... Context>
+ requires std::derived_from<Value, Named<Context...>>
+ using NamedRegistry = ValueRegistry<RegistryValueInfoNamed<Value, Context...>>;
- template<typename T, typename... _Context>
- requires std::derived_from<T, Named<_Context...>>
- using NamedInstanceRegistry = InstanceRegistry<T, _get_name<T, _Context...>>;
+ template<typename Value, typename... Context>
+ requires std::derived_from<Value, Named<Context...>>
+ using NamedInstanceRegistry = InstanceRegistry<RegistryValueInfoNamed<Value, Context...>>;
}
diff --git a/src/openvic-simulation/misc/Modifier.cpp b/src/openvic-simulation/misc/Modifier.cpp
index 8abafe3..b0dc1cf 100644
--- a/src/openvic-simulation/misc/Modifier.cpp
+++ b/src/openvic-simulation/misc/Modifier.cpp
@@ -98,9 +98,7 @@ bool ModifierManager::add_modifier_effect(std::string_view identifier, bool posi
Logger::error("Invalid modifier effect identifier - empty!");
return false;
}
- return modifier_effects.add_item(
- std::make_unique<ModifierEffect>(std::move(identifier), std::move(positive_good), std::move(format))
- );
+ return modifier_effects.add_item({ std::move(identifier), positive_good, format });
}
bool ModifierManager::setup_modifier_effects() {
diff --git a/src/openvic-simulation/misc/Modifier.hpp b/src/openvic-simulation/misc/Modifier.hpp
index 83efe9b..abb3891 100644
--- a/src/openvic-simulation/misc/Modifier.hpp
+++ b/src/openvic-simulation/misc/Modifier.hpp
@@ -3,13 +3,12 @@
#include "openvic-simulation/scripts/ConditionScript.hpp"
#include "openvic-simulation/types/IdentifierRegistry.hpp"
-#include "dataloader/NodeTools.hpp"
-
-
namespace OpenVic {
struct ModifierManager;
struct ModifierEffect : HasIdentifier {
+ friend struct ModifierManager;
+
enum class format_t {
PROPORTION_DECIMAL, /* An unscaled fraction/ratio, with 1 being "full"/"whole" */
PERCENTAGE_DECIMAL, /* A fraction/ratio scaled so that 100 is "full"/"whole" */
@@ -17,8 +16,6 @@ namespace OpenVic {
INT /* A discrete quantity, e.g. building count limit */
};
- friend std::unique_ptr<ModifierEffect> std::make_unique<ModifierEffect>(std::string_view&&, bool&&, format_t&&);
-
private:
/* If true, positive values will be green and negative values will be red.
* If false, the colours will be switced.
@@ -115,10 +112,10 @@ namespace OpenVic {
struct ModifierManager {
/* Some ModifierEffects are generated mid-load, such as max/min count modifiers for each building, so
* we can't lock it until loading is over. This means we can't rely on locking for pointer stability,
- * so instead we use an IdentifierInstanceRegistry (using std::unique_ptr's under the hood).
+ * so instead we store the effects in a deque which doesn't invalidate pointers on insert.
*/
private:
- CaseInsensitiveIdentifierInstanceRegistry<ModifierEffect> IDENTIFIER_REGISTRY(modifier_effect);
+ CaseInsensitiveIdentifierRegistry<ModifierEffect, RegistryStorageInfoDeque> IDENTIFIER_REGISTRY(modifier_effect);
case_insensitive_string_set_t complex_modifiers;
IdentifierRegistry<Modifier> IDENTIFIER_REGISTRY(event_modifier);
diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp
index 04198b0..bbaf52c 100644
--- a/src/openvic-simulation/types/IdentifierRegistry.hpp
+++ b/src/openvic-simulation/types/IdentifierRegistry.hpp
@@ -24,69 +24,177 @@ namespace OpenVic {
);
return true;
}
- static bool duplicate_ignore_callback(std::string_view registry_name, std::string_view duplicate_identifier) {
+ static constexpr bool duplicate_ignore_callback(std::string_view registry_name, std::string_view duplicate_identifier) {
return true;
}
- /* _GetIdentifier - takes _Type const* and returns std::string_view
- * _GetPointer - takes _Storage [const]& and returns T [const]*
- */
+ /* Registry Value Info - the type that is being registered, and a unique identifier string getter. */
+ template<typename ValueInfo>
+ concept RegistryValueInfo = requires(typename ValueInfo::value_type const& item) {
+ { ValueInfo::get_identifier(item) } -> std::same_as<std::string_view>;
+ };
+ template <std::derived_from<HasIdentifier> Value>
+ struct RegistryValueInfoHasIdentifier {
+ using value_type = Value;
+
+ static constexpr std::string_view get_identifier(value_type const& item) {
+ return item.get_identifier();
+ }
+ };
+
+ /* Registry Item Info - how individual elements of the registered type are stored, and type from item getters. */
+ template<template<typename> typename ItemInfo, typename Value>
+ concept RegistryItemInfo = requires(
+ typename ItemInfo<Value>::item_type& item, typename ItemInfo<Value>::item_type const& const_item
+ ) {
+ { ItemInfo<Value>::get_value(item) } -> std::same_as<Value&>;
+ { ItemInfo<Value>::get_value(const_item) } -> std::same_as<Value const&>;
+ };
+ template<typename Value>
+ struct RegistryItemInfoValue {
+ using item_type = Value;
+
+ static constexpr Value& get_value(item_type& item) {
+ return item;
+ }
+ static constexpr Value const& get_value(item_type const& item) {
+ return item;
+ }
+ };
+ template<typename Value>
+ struct RegistryItemInfoInstance {
+ using item_type = std::unique_ptr<Value>;
+
+ static constexpr Value& get_value(item_type& item) {
+ return *item.get();
+ }
+ static constexpr Value const& get_value(item_type const& item) {
+ return *item.get();
+ }
+ };
+
+ /* Registry Storage Info - how items are stored and indexed, and item-index conversion functions. */
+ template<template<typename> typename StorageInfo, typename Item>
+ concept RegistryStorageInfo =
+ std::same_as<typename StorageInfo<Item>::storage_type::value_type, Item> &&
+ requires(
+ typename StorageInfo<Item>::storage_type& items, typename StorageInfo<Item>::storage_type const& const_items,
+ typename StorageInfo<Item>::index_type index
+ ) {
+ { StorageInfo<Item>::get_back_index(items) } -> std::same_as<typename StorageInfo<Item>::index_type>;
+ { StorageInfo<Item>::get_item_from_index(items, index) } -> std::same_as<Item&>;
+ { StorageInfo<Item>::get_item_from_index(const_items, index) } -> std::same_as<Item const&>;
+ };
+ template<typename Item>
+ struct RegistryStorageInfoVector {
+ using storage_type = std::vector<Item>;
+ using index_type = std::size_t;
+
+ static constexpr index_type get_back_index(storage_type& items) {
+ return items.size() - 1;
+ }
+ static constexpr Item& get_item_from_index(storage_type& items, index_type index) {
+ return items[index];
+ }
+ static constexpr Item const& get_item_from_index(storage_type const& items, index_type index) {
+ return items[index];
+ }
+ };
+ template<typename Item>
+ struct RegistryStorageInfoDeque {
+ using storage_type = std::deque<Item>;
+ using index_type = Item*;
+
+ static constexpr index_type get_back_index(storage_type& items) {
+ return std::addressof(items.back());
+ }
+ static constexpr Item& get_item_from_index(storage_type& items, index_type index) {
+ return *index;
+ }
+ static constexpr Item const& get_item_from_index(storage_type const& items, index_type index) {
+ return *index;
+ }
+ };
+
+ /* Registry Identifier Map Info - how unique identifier strings are compared when looking up entries. */
+ template<typename IdentifierMapInfo>
+ concept RegistryIdentifierMapInfo = requires(std::string_view identifier) {
+ { typename IdentifierMapInfo::hash {}(identifier) } -> std::same_as<std::size_t>;
+ { typename IdentifierMapInfo::equal {}(identifier, identifier) } -> std::same_as<bool>;
+ };
+ struct RegistryIdentifierMapInfoCaseSensitive {
+ using hash = container_hash<std::string>;
+ using equal = std::equal_to<>;
+ };
+ struct RegistryIdentifierMapInfoCaseInsensitive {
+ using hash = case_insensitive_string_hash;
+ using equal = case_insensitive_string_equal;
+ };
+
template<
- typename _Type, typename _Storage, typename _GetIdentifier, typename _GetPointer,
- class Hash = container_hash<std::string>, class KeyEqual = std::equal_to<>>
+ RegistryValueInfo ValueInfo, /* The type that is being registered and that has unique string identifiers */
+ template<typename> typename _ItemInfo, /* How the type is being stored, usually either by value or std::unique_ptr */
+ template<typename> typename _StorageInfo = RegistryStorageInfoVector, /* How items are stored, including indexing type */
+ RegistryIdentifierMapInfo IdentifierMapInfo = RegistryIdentifierMapInfoCaseSensitive /* Identifier map parameters */
+ >
+ requires (
+ RegistryItemInfo<_ItemInfo, typename ValueInfo::value_type> &&
+ RegistryStorageInfo<_StorageInfo, typename _ItemInfo<typename ValueInfo::value_type>::item_type>
+ )
class UniqueKeyRegistry {
+ public:
+ using value_type = typename ValueInfo::value_type;
+ using ItemInfo = _ItemInfo<value_type>;
+ using item_type = typename ItemInfo::item_type;
- using identifier_index_map_t = string_map_t<size_t, Hash, KeyEqual>;
+ private:
+ using StorageInfo = _StorageInfo<item_type>;
+ using index_type = typename StorageInfo::index_type;
+ using identifier_index_map_t =
+ string_map_t<index_type, typename IdentifierMapInfo::hash, typename IdentifierMapInfo::equal>;
+
+ public:
+ using storage_type = typename StorageInfo::storage_type;
+ private:
const std::string name;
const bool log_lock;
- std::vector<_Storage> PROPERTY_REF(items);
+ storage_type PROPERTY_REF(items);
bool locked = false;
identifier_index_map_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, _GetIdentifier new_GetIdentifier = {},
- _GetPointer new_GetPointer = {}
- ) : name { new_name }, log_lock { new_log_lock }, GetIdentifier { new_GetIdentifier }, GetPointer { new_GetPointer } {}
+ constexpr UniqueKeyRegistry(std::string_view new_name, bool new_log_lock = true)
+ : name { new_name }, log_lock { new_log_lock } {}
- std::string_view get_name() const {
+ constexpr std::string_view get_name() const {
return name;
}
- bool add_item(
- storage_type&& item,
- NodeTools::callback_t<std::string_view, std::string_view> duplicate_callback = duplicate_fail_callback
+ constexpr bool add_item(
+ item_type&& item, NodeTools::Callback<std::string_view, std::string_view> auto duplicate_callback
) {
if (locked) {
Logger::error("Cannot add item to the ", name, " registry - locked!");
return false;
}
- const std::string_view new_identifier = GetIdentifier(GetPointer(item));
- if (duplicate_callback &&
- duplicate_callback.target<bool(std::string_view, std::string_view)>() == duplicate_ignore_callback) {
- if (has_identifier(new_identifier)) {
- return true;
- }
- } else {
- value_type const* old_item = get_item_by_identifier(new_identifier);
- if (old_item != nullptr) {
- return duplicate_callback(name, new_identifier);
- }
+
+ const std::string_view new_identifier = ValueInfo::get_identifier(ItemInfo::get_value(item));
+ value_type const* old_item = get_item_by_identifier(new_identifier);
+ if (old_item != nullptr) {
+ return duplicate_callback(name, new_identifier);
}
- const std::pair<typename identifier_index_map_t::iterator, bool> ret =
- identifier_index_map.emplace(std::move(new_identifier), items.size());
+
items.emplace_back(std::move(item));
- return ret.second && ret.first->second + 1 == items.size();
+ identifier_index_map.emplace(std::move(new_identifier), StorageInfo::get_back_index(items));
+ return true;
}
- void lock() {
+ constexpr bool add_item(item_type&& item) {
+ return add_item(std::move(item), duplicate_fail_callback);
+ }
+
+ constexpr void lock() {
if (locked) {
Logger::error("Failed to lock ", name, " registry - already locked!");
} else {
@@ -97,25 +205,25 @@ namespace OpenVic {
}
}
- bool is_locked() const {
+ constexpr bool is_locked() const {
return locked;
}
- void reset() {
+ constexpr void reset() {
identifier_index_map.clear();
items.clear();
locked = false;
}
- size_t size() const {
+ constexpr std::size_t size() const {
return items.size();
}
- bool empty() const {
+ constexpr bool empty() const {
return items.empty();
}
- void reserve(size_t size) {
+ constexpr void reserve(std::size_t size) {
if (locked) {
Logger::error("Failed to reserve space for ", size, " items in ", name, " registry - already locked!");
} else {
@@ -124,7 +232,7 @@ namespace OpenVic {
}
}
- static NodeTools::KeyValueCallback auto key_value_invalid_callback(std::string_view name) {
+ constexpr static NodeTools::KeyValueCallback auto key_value_invalid_callback(std::string_view name) {
return [name](std::string_view key, ast::NodeCPtr) {
Logger::error("Invalid ", name, ": ", key);
return false;
@@ -132,17 +240,17 @@ namespace OpenVic {
}
#define GETTERS(CONST) \
- value_type CONST* get_item_by_identifier(std::string_view identifier) CONST { \
+ constexpr 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 std::addressof(ItemInfo::get_value(StorageInfo::get_item_from_index(items, it->second))); \
} \
return nullptr; \
} \
- value_type CONST* get_item_by_index(size_t index) CONST { \
- return index < items.size() ? GetPointer(items[index]) : nullptr; \
+ constexpr value_type CONST* get_item_by_index(std::size_t index) CONST { \
+ return index < items.size() ? std::addressof(ItemInfo::get_value(items[index])) : nullptr; \
} \
- NodeTools::Callback<std::string_view> auto expect_item_str( \
+ constexpr NodeTools::Callback<std::string_view> auto expect_item_str( \
NodeTools::Callback<value_type CONST&> auto callback, bool warn \
) CONST { \
return [this, callback, warn](std::string_view identifier) -> bool { \
@@ -159,12 +267,12 @@ namespace OpenVic {
} \
}; \
} \
- NodeTools::NodeCallback auto expect_item_identifier( \
+ constexpr NodeTools::NodeCallback auto expect_item_identifier( \
NodeTools::Callback<value_type CONST&> auto callback, bool warn \
) CONST { \
return NodeTools::expect_identifier(expect_item_str(callback, warn)); \
} \
- NodeTools::NodeCallback auto expect_item_assign_and_default( \
+ constexpr NodeTools::NodeCallback auto expect_item_assign_and_default( \
NodeTools::KeyValueCallback auto default_callback, \
NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
) CONST { \
@@ -179,12 +287,12 @@ namespace OpenVic {
} \
); \
} \
- NodeTools::NodeCallback auto expect_item_assign( \
+ constexpr NodeTools::NodeCallback auto expect_item_assign( \
NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
) CONST { \
return expect_item_assign_and_default(key_value_invalid_callback(name), callback); \
} \
- NodeTools::NodeCallback auto expect_item_dictionary_and_length_and_default( \
+ constexpr NodeTools::NodeCallback auto expect_item_dictionary_and_length_and_default( \
NodeTools::LengthCallback auto length_callback, \
NodeTools::KeyValueCallback auto default_callback, \
NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
@@ -193,7 +301,7 @@ namespace OpenVic {
length_callback, expect_item_assign_and_default(default_callback, callback) \
); \
} \
- NodeTools::NodeCallback auto expect_item_dictionary_and_length( \
+ constexpr NodeTools::NodeCallback auto expect_item_dictionary_and_length( \
NodeTools::LengthCallback auto length_callback, \
NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
) CONST { \
@@ -203,7 +311,7 @@ namespace OpenVic {
callback \
); \
} \
- NodeTools::NodeCallback auto expect_item_dictionary_and_default( \
+ constexpr NodeTools::NodeCallback auto expect_item_dictionary_and_default( \
NodeTools::KeyValueCallback auto default_callback, \
NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
) CONST { \
@@ -213,7 +321,7 @@ namespace OpenVic {
callback \
); \
} \
- NodeTools::NodeCallback auto expect_item_dictionary( \
+ constexpr NodeTools::NodeCallback auto expect_item_dictionary( \
NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
) CONST { \
return expect_item_dictionary_and_length_and_default( \
@@ -223,7 +331,7 @@ namespace OpenVic {
); \
} \
template<NodeTools::Reservable T> \
- NodeTools::NodeCallback auto expect_item_dictionary_reserve_length_and_default( \
+ constexpr NodeTools::NodeCallback auto expect_item_dictionary_reserve_length_and_default( \
T& t, \
NodeTools::KeyValueCallback auto default_callback, \
NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
@@ -235,7 +343,7 @@ namespace OpenVic {
); \
} \
template<NodeTools::Reservable T> \
- NodeTools::NodeCallback auto expect_item_dictionary_reserve_length( \
+ constexpr NodeTools::NodeCallback auto expect_item_dictionary_reserve_length( \
T& t, \
NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \
) CONST { \
@@ -259,11 +367,11 @@ namespace OpenVic {
#undef GETTERS
- bool has_identifier(std::string_view identifier) const {
+ constexpr bool has_identifier(std::string_view identifier) const {
return identifier_index_map.contains(identifier);
}
- bool has_index(size_t index) const {
+ constexpr bool has_index(std::size_t index) const {
return index < size();
}
@@ -276,7 +384,7 @@ namespace OpenVic {
return identifiers;
}
- NodeTools::NodeCallback auto expect_item_decimal_map(
+ constexpr NodeTools::NodeCallback auto expect_item_decimal_map(
NodeTools::Callback<fixed_point_map_t<value_type const*>&&> auto callback
) const {
return [this, callback](ast::NodeCPtr node) -> bool {
@@ -293,55 +401,42 @@ namespace OpenVic {
}
};
- /* Standard value storage */
- template<typename T>
- 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, class Hash = container_hash<std::string>, class KeyEqual = std::equal_to<>>
- using ValueRegistry = UniqueKeyRegistry<_Type, _Type, _GetIdentifier, _addressof<_Type>, Hash, KeyEqual>;
-
- /* std::unique_ptr dynamic storage */
- template<typename T>
- 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();
- }
- };
+ /* Item Specialisations */
+ template<
+ RegistryValueInfo ValueInfo, template<typename> typename StorageInfo = RegistryStorageInfoVector,
+ RegistryIdentifierMapInfo IdentifierMapInfo = RegistryIdentifierMapInfoCaseSensitive
+ >
+ requires RegistryStorageInfo<StorageInfo, typename RegistryItemInfoValue<typename ValueInfo::value_type>::item_type>
+ using ValueRegistry = UniqueKeyRegistry<ValueInfo, RegistryItemInfoValue, StorageInfo, IdentifierMapInfo>;
- template<typename _Type, typename _GetIdentifier, class Hash = container_hash<std::string>, class KeyEqual = std::equal_to<>>
- using InstanceRegistry = UniqueKeyRegistry<_Type, std::unique_ptr<_Type>, _GetIdentifier, _uptr_get<_Type>, Hash, KeyEqual>;
+ template<
+ RegistryValueInfo ValueInfo, template<typename> typename StorageInfo = RegistryStorageInfoVector,
+ RegistryIdentifierMapInfo IdentifierMapInfo = RegistryIdentifierMapInfoCaseSensitive
+ >
+ requires RegistryStorageInfo<StorageInfo, typename RegistryItemInfoInstance<typename ValueInfo::value_type>::item_type>
+ using InstanceRegistry = UniqueKeyRegistry<ValueInfo, RegistryItemInfoInstance, StorageInfo, IdentifierMapInfo>;
- /* HasIdentifier versions */
- template<std::derived_from<HasIdentifier> T>
- struct _get_identifier {
- constexpr std::string_view operator()(T const* item) const {
- return item->get_identifier();
- }
- };
+ /* HasIdentifier Specialisations */
+ template<
+ std::derived_from<HasIdentifier> Value, template<typename> typename StorageInfo = RegistryStorageInfoVector,
+ RegistryIdentifierMapInfo IdentifierMapInfo = RegistryIdentifierMapInfoCaseSensitive
+ >
+ using IdentifierRegistry = ValueRegistry<RegistryValueInfoHasIdentifier<Value>, StorageInfo, IdentifierMapInfo>;
- template<std::derived_from<HasIdentifier> _Type, class Hash = container_hash<std::string>, class KeyEqual = std::equal_to<>>
- using IdentifierRegistry = ValueRegistry<_Type, _get_identifier<_Type>, Hash, KeyEqual>;
+ template<
+ std::derived_from<HasIdentifier> Value, template<typename> typename StorageInfo = RegistryStorageInfoVector,
+ RegistryIdentifierMapInfo IdentifierMapInfo = RegistryIdentifierMapInfoCaseSensitive
+ >
+ using IdentifierInstanceRegistry = InstanceRegistry<RegistryValueInfoHasIdentifier<Value>, StorageInfo, IdentifierMapInfo>;
- template<std::derived_from<HasIdentifier> _Type>
+ /* Case-Insensitive HasIdentifier Specialisations */
+ template<std::derived_from<HasIdentifier> Value, template<typename> typename StorageInfo = RegistryStorageInfoVector>
using CaseInsensitiveIdentifierRegistry =
- IdentifierRegistry<_Type, case_insensitive_string_hash, case_insensitive_string_equal>;
-
- template<std::derived_from<HasIdentifier> _Type, class Hash = container_hash<std::string>, class KeyEqual = std::equal_to<>>
- using IdentifierInstanceRegistry = InstanceRegistry<_Type, _get_identifier<_Type>, Hash, KeyEqual>;
+ IdentifierRegistry<Value, StorageInfo, RegistryIdentifierMapInfoCaseInsensitive>;
- template<std::derived_from<HasIdentifier> _Type>
+ template<std::derived_from<HasIdentifier> Value, template<typename> typename StorageInfo = RegistryStorageInfoVector>
using CaseInsensitiveIdentifierInstanceRegistry =
- IdentifierInstanceRegistry<_Type, case_insensitive_string_hash, case_insensitive_string_equal>;
+ IdentifierInstanceRegistry<Value, StorageInfo, RegistryIdentifierMapInfoCaseInsensitive>;
/* Macros to generate declaration and constant accessor methods for a UniqueKeyRegistry member variable. */
@@ -357,25 +452,25 @@ namespace OpenVic {
#define IDENTIFIER_REGISTRY_FULL_CUSTOM(singular, plural, registry, debug_name, index_offset) \
registry { #debug_name };\
public: \
- void lock_##plural() { \
+ constexpr void lock_##plural() { \
registry.lock(); \
} \
- bool plural##_are_locked() const { \
+ constexpr bool plural##_are_locked() const { \
return registry.is_locked(); \
} \
- bool has_##singular##_identifier(std::string_view identifier) const { \
+ constexpr bool has_##singular##_identifier(std::string_view identifier) const { \
return registry.has_identifier(identifier); \
} \
- size_t get_##singular##_count() const { \
+ constexpr std::size_t get_##singular##_count() const { \
return registry.size(); \
} \
- bool plural##_empty() const { \
+ constexpr bool plural##_empty() const { \
return registry.empty(); \
} \
std::vector<std::string_view> get_##singular##_identifiers() const { \
return registry.get_item_identifiers(); \
} \
- NodeTools::NodeCallback auto expect_##singular##_decimal_map( \
+ constexpr NodeTools::NodeCallback auto expect_##singular##_decimal_map( \
NodeTools::Callback<fixed_point_map_t<decltype(registry)::value_type const*>&&> auto callback \
) const { \
return registry.expect_item_decimal_map(callback); \
@@ -398,56 +493,56 @@ private:
IDENTIFIER_REGISTRY_INTERNAL_SHARED(singular, plural, registry, index_offset,)
#define IDENTIFIER_REGISTRY_INTERNAL_SHARED(singular, plural, registry, index_offset, const_kw) \
- decltype(registry)::value_type const_kw* get_##singular##_by_identifier(std::string_view identifier) const_kw { \
+ constexpr decltype(registry)::value_type const_kw* get_##singular##_by_identifier(std::string_view identifier) const_kw { \
return registry.get_item_by_identifier(identifier); \
} \
- decltype(registry)::value_type const_kw* get_##singular##_by_index(size_t index) const_kw { \
+ constexpr decltype(registry)::value_type const_kw* get_##singular##_by_index(std::size_t index) const_kw { \
return index >= index_offset ? registry.get_item_by_index(index - index_offset) : nullptr; \
} \
- std::vector<decltype(registry)::storage_type> const_kw& get_##plural() const_kw { \
+ constexpr decltype(registry)::storage_type const_kw& get_##plural() const_kw { \
return registry.get_items(); \
} \
- NodeTools::Callback<std::string_view> auto expect_##singular##_str( \
+ constexpr NodeTools::Callback<std::string_view> auto expect_##singular##_str( \
NodeTools::Callback<decltype(registry)::value_type const_kw&> auto callback, bool warn = false \
) const_kw { \
return registry.expect_item_str(callback, warn); \
} \
- NodeTools::NodeCallback auto expect_##singular##_identifier( \
+ constexpr NodeTools::NodeCallback auto expect_##singular##_identifier( \
NodeTools::Callback<decltype(registry)::value_type const_kw&> auto callback, bool warn = false \
) const_kw { \
return registry.expect_item_identifier(callback, warn); \
} \
- NodeTools::NodeCallback auto expect_##singular##_assign_and_default( \
+ constexpr NodeTools::NodeCallback auto expect_##singular##_assign_and_default( \
NodeTools::KeyValueCallback auto default_callback, \
NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \
) const_kw { \
return registry.expect_item_assign_and_default(default_callback, callback); \
} \
- NodeTools::NodeCallback auto expect_##singular##_assign( \
+ constexpr NodeTools::NodeCallback auto expect_##singular##_assign( \
NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \
) const_kw { \
return registry.expect_item_assign(callback); \
} \
- NodeTools::NodeCallback auto expect_##singular##_dictionary_and_length_and_default( \
+ constexpr NodeTools::NodeCallback auto expect_##singular##_dictionary_and_length_and_default( \
NodeTools::LengthCallback auto length_callback, \
NodeTools::KeyValueCallback auto default_callback, \
NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \
) const_kw { \
return registry.expect_item_dictionary_and_length_and_default(length_callback, default_callback, callback); \
} \
- NodeTools::NodeCallback auto expect_##singular##_dictionary_and_default( \
+ constexpr NodeTools::NodeCallback auto expect_##singular##_dictionary_and_default( \
NodeTools::KeyValueCallback auto default_callback, \
NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \
) const_kw { \
return registry.expect_item_dictionary_and_default(default_callback, callback); \
} \
- NodeTools::NodeCallback auto expect_##singular##_dictionary( \
+ constexpr NodeTools::NodeCallback auto expect_##singular##_dictionary( \
NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \
) const_kw { \
return registry.expect_item_dictionary(callback); \
} \
template<NodeTools::Reservable T> \
- NodeTools::NodeCallback auto expect_##singular##_dictionary_reserve_length_and_default( \
+ constexpr NodeTools::NodeCallback auto expect_##singular##_dictionary_reserve_length_and_default( \
T& t, \
NodeTools::KeyValueCallback auto default_callback, \
NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \
@@ -455,7 +550,7 @@ private:
return registry.expect_item_dictionary_reserve_length_and_default(t, default_callback, callback); \
} \
template<NodeTools::Reservable T> \
- NodeTools::NodeCallback auto expect_##singular##_dictionary_reserve_length( \
+ constexpr NodeTools::NodeCallback auto expect_##singular##_dictionary_reserve_length( \
T& t, \
NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \
) const_kw { \