aboutsummaryrefslogtreecommitdiff
path: root/src/openvic-simulation
diff options
context:
space:
mode:
author hop311 <hop3114@gmail.com>2024-01-25 00:28:09 +0100
committer hop311 <hop3114@gmail.com>2024-01-25 21:31:04 +0100
commit14ba9531d118fab87b360db4aae765807fca3cec (patch)
tree97a1bff45f91d4b02ef62c4dd9a8e584699e5fdd /src/openvic-simulation
parent3e2ee2cd3553cb0a5949d7a34c5ef2f10ff5c949 (diff)
Added StringMapCase and case insensitive expect_dictionary_keyscase-rework
Diffstat (limited to 'src/openvic-simulation')
-rw-r--r--src/openvic-simulation/dataloader/NodeTools.cpp79
-rw-r--r--src/openvic-simulation/dataloader/NodeTools.hpp183
-rw-r--r--src/openvic-simulation/economy/ProductionType.cpp2
-rw-r--r--src/openvic-simulation/interface/GFX.cpp13
-rw-r--r--src/openvic-simulation/interface/GFX.hpp12
-rw-r--r--src/openvic-simulation/interface/GUI.cpp27
-rw-r--r--src/openvic-simulation/interface/GUI.hpp24
-rw-r--r--src/openvic-simulation/interface/LoadBase.hpp6
-rw-r--r--src/openvic-simulation/map/TerrainType.cpp6
-rw-r--r--src/openvic-simulation/types/IdentifierRegistry.hpp55
-rw-r--r--src/openvic-simulation/types/OrderedContainers.hpp52
-rw-r--r--src/openvic-simulation/utility/Utility.hpp8
12 files changed, 253 insertions, 214 deletions
diff --git a/src/openvic-simulation/dataloader/NodeTools.cpp b/src/openvic-simulation/dataloader/NodeTools.cpp
index 957aa01..7ab0dbe 100644
--- a/src/openvic-simulation/dataloader/NodeTools.cpp
+++ b/src/openvic-simulation/dataloader/NodeTools.cpp
@@ -1,7 +1,6 @@
#include "NodeTools.hpp"
#include "openvic-simulation/types/Colour.hpp"
-#include "openvic-simulation/utility/TslHelper.hpp"
using namespace OpenVic;
using namespace OpenVic::NodeTools;
@@ -70,7 +69,7 @@ node_callback_t NodeTools::expect_identifier_or_string(callback_t<std::string_vi
}
node_callback_t NodeTools::expect_bool(callback_t<bool> callback) {
- static const case_insensitive_string_map_t<bool> bool_map = { { "yes", true }, { "no", false } };
+ static const case_insensitive_string_map_t<bool> bool_map { { "yes", true }, { "no", false } };
return expect_identifier(expect_mapped_string(bool_map, callback));
}
@@ -324,82 +323,6 @@ node_callback_t NodeTools::expect_dictionary(key_value_callback_t callback) {
return expect_dictionary_and_length(default_length_callback, callback);
}
-bool NodeTools::add_key_map_entry(
- key_map_t& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count, node_callback_t callback
-) {
- if (!key_map.contains(key)) {
- key_map.emplace(key, dictionary_entry_t { expected_count, callback });
- return true;
- }
- Logger::error("Duplicate expected dictionary key: ", key);
- return false;
-}
-
-bool NodeTools::remove_key_map_entry(key_map_t& key_map, std::string_view key) {
- if (key_map.erase(key) == 0) {
- Logger::error("Failed to find dictionary key to remove: ", key);
- return false;
- }
- return true;
-}
-
-key_value_callback_t NodeTools::dictionary_keys_callback(key_map_t& key_map, key_value_callback_t default_callback) {
- return [&key_map, default_callback](std::string_view key, ast::NodeCPtr value) -> bool {
- key_map_t::iterator it = key_map.find(key);
- if (it == key_map.end()) {
- return default_callback(key, value);
- }
- dictionary_entry_t& entry = it.value();
- if (++entry.count > 1 && !entry.can_repeat()) {
- Logger::error("Invalid repeat of dictionary key: ", key);
- return false;
- }
- if (entry.callback(value)) {
- return true;
- } else {
- Logger::error("Callback failed for dictionary key: ", key);
- return false;
- }
- };
-}
-
-bool NodeTools::check_key_map_counts(key_map_t& key_map) {
- bool ret = true;
- for (auto key_entry : mutable_iterator(key_map)) {
- dictionary_entry_t& entry = key_entry.second;
- if (entry.must_appear() && entry.count < 1) {
- Logger::error("Mandatory dictionary key not present: ", key_entry.first);
- ret = false;
- }
- entry.count = 0;
- }
- return ret;
-}
-
-node_callback_t NodeTools::expect_dictionary_key_map_and_length_and_default(
- key_map_t key_map, length_callback_t length_callback, key_value_callback_t default_callback
-) {
- return [length_callback, default_callback, key_map = std::move(key_map)](ast::NodeCPtr node) mutable -> bool {
- bool ret = expect_dictionary_and_length(length_callback, dictionary_keys_callback(key_map, default_callback))(node);
- ret &= check_key_map_counts(key_map);
- return ret;
- };
-}
-
-node_callback_t NodeTools::expect_dictionary_key_map_and_length(key_map_t key_map, length_callback_t length_callback) {
- return expect_dictionary_key_map_and_length_and_default(std::move(key_map), length_callback, key_value_invalid_callback);
-}
-
-node_callback_t NodeTools::expect_dictionary_key_map_and_default(key_map_t key_map, key_value_callback_t default_callback) {
- return expect_dictionary_key_map_and_length_and_default(std::move(key_map), default_length_callback, default_callback);
-}
-
-node_callback_t NodeTools::expect_dictionary_key_map(key_map_t key_map) {
- return expect_dictionary_key_map_and_length_and_default(
- std::move(key_map), default_length_callback, key_value_invalid_callback
- );
-}
-
node_callback_t NodeTools::name_list_callback(callback_t<name_list_t&&> callback) {
return [callback](ast::NodeCPtr node) -> bool {
name_list_t list;
diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp
index 9137d6a..54b61d0 100644
--- a/src/openvic-simulation/dataloader/NodeTools.hpp
+++ b/src/openvic-simulation/dataloader/NodeTools.hpp
@@ -14,21 +14,11 @@
#include "openvic-simulation/types/HasIdentifier.hpp"
#include "openvic-simulation/types/OrderedContainers.hpp"
#include "openvic-simulation/types/Vector.hpp"
+#include "openvic-simulation/utility/TslHelper.hpp"
namespace OpenVic {
namespace ast = ovdl::v2script::ast;
- /* Template for map from strings to Ts, in which string_views can be
- * searched for without needing to be copied into a string */
- template<typename T, class Hash = container_hash<std::string>, class KeyEqual = std::equal_to<>>
- using string_map_t = ordered_map<std::string, T, Hash, KeyEqual>;
- template<typename T>
- using case_insensitive_string_map_t = string_map_t<T, case_insensitive_string_hash, case_insensitive_string_equal>;
-
- /* String set type supporting heterogeneous key lookup */
- using string_set_t = ordered_set<std::string>;
- using case_insensitive_string_set_t = case_insensitive_ordered_set<std::string>;
-
using name_list_t = std::vector<std::string>;
std::ostream& operator<<(std::ostream& stream, name_list_t const& name_list);
@@ -178,22 +168,80 @@ namespace OpenVic {
}
};
using enum dictionary_entry_t::expected_count_t;
- using key_map_t = string_map_t<dictionary_entry_t>;
+ template<StringMapCase Case>
+ using template_key_map_t = template_string_map_t<dictionary_entry_t, Case>;
+
+ using key_map_t = template_key_map_t<StringMapCaseSensitive>;
+ using case_insensitive_key_map_t = template_key_map_t<StringMapCaseInsensitive>;
+
+ template<StringMapCase Case>
bool add_key_map_entry(
- key_map_t& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count,
- node_callback_t callback
- );
- bool remove_key_map_entry(key_map_t& key_map, std::string_view key);
- key_value_callback_t dictionary_keys_callback(key_map_t& key_map, key_value_callback_t default_callback);
- bool check_key_map_counts(key_map_t& key_map);
+ template_key_map_t<Case>& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count,
+ NodeCallback auto callback
+ ) {
+ if (!key_map.contains(key)) {
+ key_map.emplace(key, dictionary_entry_t { expected_count, callback });
+ return true;
+ }
+ Logger::error("Duplicate expected dictionary key: ", key);
+ return false;
+ }
- constexpr bool add_key_map_entries(key_map_t& key_map) {
+ template<StringMapCase Case>
+ bool remove_key_map_entry(template_key_map_t<Case>& key_map, std::string_view key) {
+ if (key_map.erase(key) == 0) {
+ Logger::error("Failed to find dictionary key to remove: ", key);
+ return false;
+ }
return true;
}
- template<typename... Args>
+
+ template<StringMapCase Case>
+ KeyValueCallback auto dictionary_keys_callback(
+ template_key_map_t<Case>& key_map, KeyValueCallback auto default_callback
+ ) {
+ return [&key_map, default_callback](std::string_view key, ast::NodeCPtr value) -> bool {
+ typename template_key_map_t<Case>::iterator it = key_map.find(key);
+ if (it == key_map.end()) {
+ return default_callback(key, value);
+ }
+ dictionary_entry_t& entry = it.value();
+ if (++entry.count > 1 && !entry.can_repeat()) {
+ Logger::error("Invalid repeat of dictionary key: ", key);
+ return false;
+ }
+ if (entry.callback(value)) {
+ return true;
+ } else {
+ Logger::error("Callback failed for dictionary key: ", key);
+ return false;
+ }
+ };
+ }
+
+ template<StringMapCase Case>
+ bool check_key_map_counts(template_key_map_t<Case>& key_map) {
+ bool ret = true;
+ for (auto key_entry : mutable_iterator(key_map)) {
+ dictionary_entry_t& entry = key_entry.second;
+ if (entry.must_appear() && entry.count < 1) {
+ Logger::error("Mandatory dictionary key not present: ", key_entry.first);
+ ret = false;
+ }
+ entry.count = 0;
+ }
+ return ret;
+ }
+
+ template<StringMapCase Case>
+ constexpr bool add_key_map_entries(template_key_map_t<Case>& key_map) {
+ return true;
+ }
+
+ template<StringMapCase Case, typename... Args>
bool add_key_map_entries(
- key_map_t& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count,
+ template_key_map_t<Case>& key_map, std::string_view key, dictionary_entry_t::expected_count_t expected_count,
NodeCallback auto callback, Args... args
) {
bool ret = add_key_map_entry(key_map, key, expected_count, callback);
@@ -201,43 +249,81 @@ namespace OpenVic {
return ret;
}
- node_callback_t expect_dictionary_key_map_and_length_and_default(
- key_map_t key_map, length_callback_t length_callback, key_value_callback_t default_callback
- );
- node_callback_t expect_dictionary_key_map_and_length(key_map_t key_map, length_callback_t length_callback);
- node_callback_t expect_dictionary_key_map_and_default(key_map_t key_map, key_value_callback_t default_callback);
- node_callback_t expect_dictionary_key_map(key_map_t key_map);
+ template<StringMapCase Case>
+ NodeCallback auto expect_dictionary_key_map_and_length_and_default(
+ template_key_map_t<Case> key_map, LengthCallback auto length_callback, KeyValueCallback auto default_callback
+ ) {
+ return [length_callback, default_callback, key_map = std::move(key_map)](ast::NodeCPtr node) mutable -> bool {
+ bool ret = expect_dictionary_and_length(
+ length_callback, dictionary_keys_callback(key_map, default_callback)
+ )(node);
+ ret &= check_key_map_counts(key_map);
+ return ret;
+ };
+ }
- template<typename... Args>
+ template<StringMapCase Case>
+ NodeCallback auto expect_dictionary_key_map_and_length(
+ template_key_map_t<Case> key_map, LengthCallback auto length_callback
+ ) {
+ return expect_dictionary_key_map_and_length_and_default(
+ std::move(key_map), length_callback, key_value_invalid_callback
+ );
+ }
+
+ template<StringMapCase Case>
+ NodeCallback auto expect_dictionary_key_map_and_default(
+ template_key_map_t<Case> key_map, KeyValueCallback auto default_callback
+ ) {
+ return expect_dictionary_key_map_and_length_and_default(
+ std::move(key_map), default_length_callback, default_callback
+ );
+ }
+
+ template<StringMapCase Case>
+ NodeCallback auto expect_dictionary_key_map(template_key_map_t<Case> key_map) {
+ return expect_dictionary_key_map_and_length_and_default(
+ std::move(key_map), default_length_callback, key_value_invalid_callback
+ );
+ }
+
+ template<StringMapCase Case, typename... Args>
NodeCallback auto expect_dictionary_key_map_and_length_and_default(
- key_map_t key_map, length_callback_t length_callback, key_value_callback_t default_callback, Args... args
+ template_key_map_t<Case> key_map, LengthCallback auto length_callback, KeyValueCallback auto default_callback,
+ Args... args
) {
// TODO - pass return value back up (part of big key_map_t rewrite?)
add_key_map_entries(key_map, args...);
return expect_dictionary_key_map_and_length_and_default(std::move(key_map), length_callback, default_callback);
}
- template<typename... Args>
+ template<StringMapCase Case = StringMapCaseSensitive, typename... Args>
NodeCallback auto expect_dictionary_keys_and_length_and_default(
LengthCallback auto length_callback, KeyValueCallback auto default_callback, Args... args
) {
- return expect_dictionary_key_map_and_length_and_default({}, length_callback, default_callback, args...);
+ return expect_dictionary_key_map_and_length_and_default(
+ template_key_map_t<Case> {}, length_callback, default_callback, args...
+ );
}
- template<typename... Args>
+ template<StringMapCase Case = StringMapCaseSensitive, typename... Args>
NodeCallback auto expect_dictionary_keys_and_length(LengthCallback auto length_callback, Args... args) {
- return expect_dictionary_key_map_and_length_and_default({}, length_callback, key_value_invalid_callback, args...);
+ return expect_dictionary_key_map_and_length_and_default(
+ template_key_map_t<Case> {}, length_callback, key_value_invalid_callback, args...
+ );
}
- template<typename... Args>
+ template<StringMapCase Case = StringMapCaseSensitive, typename... Args>
NodeCallback auto expect_dictionary_keys_and_default(KeyValueCallback auto default_callback, Args... args) {
- return expect_dictionary_key_map_and_length_and_default({}, default_length_callback, default_callback, args...);
+ return expect_dictionary_key_map_and_length_and_default(
+ template_key_map_t<Case> {}, default_length_callback, default_callback, args...
+ );
}
- template<typename... Args>
+ template<StringMapCase Case = StringMapCaseSensitive, typename... Args>
NodeCallback auto expect_dictionary_keys(Args... args) {
return expect_dictionary_key_map_and_length_and_default(
- {}, default_length_callback, key_value_invalid_callback, args...
+ template_key_map_t<Case> {}, default_length_callback, key_value_invalid_callback, args...
);
}
@@ -253,41 +339,42 @@ namespace OpenVic {
NodeCallback auto expect_dictionary_reserve_length(Reservable auto& reservable, KeyValueCallback auto callback) {
return expect_dictionary_and_length(reserve_length_callback(reservable), callback);
}
- template<typename... Args>
+ template<StringMapCase Case, typename... Args>
NodeCallback auto expect_dictionary_key_map_reserve_length_and_default(
- Reservable auto& reservable, key_map_t key_map, KeyValueCallback auto default_callback, Args... args
+ Reservable auto& reservable, template_key_map_t<Case> key_map, KeyValueCallback auto default_callback,
+ Args... args
) {
return expect_dictionary_key_map_and_length_and_default(
std::move(key_map), reserve_length_callback(reservable), default_callback, args...
);
}
- template<typename... Args>
+ template<StringMapCase Case, typename... Args>
NodeCallback auto expect_dictionary_key_map_reserve_length(
- Reservable auto& reservable, key_map_t key_map, Args... args
+ Reservable auto& reservable, template_key_map_t<Case> key_map, Args... args
) {
return expect_dictionary_key_map_and_length(std::move(key_map), reserve_length_callback(reservable), args...);
}
- template<typename... Args>
+ template<StringMapCase Case = StringMapCaseSensitive, typename... Args>
NodeCallback auto expect_dictionary_keys_reserve_length_and_default(
Reservable auto& reservable, KeyValueCallback auto default_callback, Args... args
) {
- return expect_dictionary_keys_and_length_and_default(
+ return expect_dictionary_keys_and_length_and_default<Case>(
reserve_length_callback(reservable), default_callback, args...
);
}
- template<typename... Args>
+ template<StringMapCase Case = StringMapCaseSensitive, typename... Args>
NodeCallback auto expect_dictionary_keys_reserve_length(Reservable auto& reservable, Args... args) {
- return expect_dictionary_keys_and_length(reserve_length_callback(reservable), args...);
+ return expect_dictionary_keys_and_length<Case>(reserve_length_callback(reservable), args...);
}
node_callback_t name_list_callback(callback_t<name_list_t&&> callback);
- template<typename T, class Hash, class KeyEqual>
+ template<typename T, StringMapCase Case>
Callback<std::string_view> auto expect_mapped_string(
- string_map_t<T, Hash, KeyEqual> const& map, Callback<T> auto callback
+ template_string_map_t<T, Case> const& map, Callback<T> auto callback
) {
return [&map, callback](std::string_view string) -> bool {
- const typename string_map_t<T, Hash, KeyEqual>::const_iterator it = map.find(string);
+ const typename template_string_map_t<T, Case>::const_iterator it = map.find(string);
if (it != map.end()) {
return callback(it->second);
}
diff --git a/src/openvic-simulation/economy/ProductionType.cpp b/src/openvic-simulation/economy/ProductionType.cpp
index 9c806e5..7029fd1 100644
--- a/src/openvic-simulation/economy/ProductionType.cpp
+++ b/src/openvic-simulation/economy/ProductionType.cpp
@@ -230,7 +230,7 @@ bool ProductionTypeManager::load_production_types_file(
{ "factory", FACTORY }, { "rgo", RGO }, { "artisan", ARTISAN }
};
- const auto parse_node = expect_dictionary_keys(
+ auto parse_node = expect_dictionary_keys(
"template", ZERO_OR_ONE, success_callback, /* Already parsed using expect_key in Pass #1 above. */
"bonus", ZERO_OR_MORE, [&bonuses](ast::NodeCPtr bonus_node) -> bool {
ConditionScript trigger { scope_t::STATE, scope_t::NO_SCOPE, scope_t::NO_SCOPE };
diff --git a/src/openvic-simulation/interface/GFX.cpp b/src/openvic-simulation/interface/GFX.cpp
index 0ec2954..ca31419 100644
--- a/src/openvic-simulation/interface/GFX.cpp
+++ b/src/openvic-simulation/interface/GFX.cpp
@@ -26,11 +26,10 @@ node_callback_t Sprite::expect_sprites(length_callback_t length_callback, callba
TextureSprite::TextureSprite() : texture_file {}, no_of_frames { NO_FRAMES } {}
-bool TextureSprite::_fill_key_map(key_map_t& key_map) {
+bool TextureSprite::_fill_key_map(case_insensitive_key_map_t& key_map) {
bool ret = Sprite::_fill_key_map(key_map);
ret &= add_key_map_entries(key_map,
"texturefile", ZERO_OR_ONE, expect_string(assign_variable_callback_string(texture_file)),
- "textureFile", ZERO_OR_ONE, expect_string(assign_variable_callback_string(texture_file)),
"noOfFrames", ZERO_OR_ONE, expect_uint(assign_variable_callback(no_of_frames)),
"norefcount", ZERO_OR_ONE, success_callback,
@@ -45,7 +44,7 @@ bool TextureSprite::_fill_key_map(key_map_t& key_map) {
TileTextureSprite::TileTextureSprite() : texture_file {}, size {} {}
-bool TileTextureSprite::_fill_key_map(key_map_t& key_map) {
+bool TileTextureSprite::_fill_key_map(case_insensitive_key_map_t& key_map) {
bool ret = Sprite::_fill_key_map(key_map);
ret &= add_key_map_entries(key_map,
"texturefile", ZERO_OR_ONE, expect_string(assign_variable_callback_string(texture_file)),
@@ -59,7 +58,7 @@ bool TileTextureSprite::_fill_key_map(key_map_t& key_map) {
ProgressBar::ProgressBar() : back_colour {}, progress_colour {} {}
-bool ProgressBar::_fill_key_map(key_map_t& key_map) {
+bool ProgressBar::_fill_key_map(case_insensitive_key_map_t& key_map) {
bool ret = Sprite::_fill_key_map(key_map);
ret &= add_key_map_entries(key_map,
"color", ONE_EXACTLY, expect_colour(assign_variable_callback(progress_colour)),
@@ -78,7 +77,7 @@ bool ProgressBar::_fill_key_map(key_map_t& key_map) {
PieChart::PieChart() : size {} {}
-bool PieChart::_fill_key_map(key_map_t& key_map) {
+bool PieChart::_fill_key_map(case_insensitive_key_map_t& key_map) {
bool ret = Sprite::_fill_key_map(key_map);
ret &= add_key_map_entries(key_map, "size", ONE_EXACTLY, expect_uint(assign_variable_callback(size)));
return ret;
@@ -86,7 +85,7 @@ bool PieChart::_fill_key_map(key_map_t& key_map) {
LineChart::LineChart() : size {}, linewidth {} {}
-bool LineChart::_fill_key_map(key_map_t& key_map) {
+bool LineChart::_fill_key_map(case_insensitive_key_map_t& key_map) {
bool ret = Sprite::_fill_key_map(key_map);
ret &= add_key_map_entries(key_map,
"size", ONE_EXACTLY, expect_ivec2(assign_variable_callback(size)),
@@ -98,7 +97,7 @@ bool LineChart::_fill_key_map(key_map_t& key_map) {
MaskedFlag::MaskedFlag() : overlay_file {}, mask_file {} {}
-bool MaskedFlag::_fill_key_map(key_map_t& key_map) {
+bool MaskedFlag::_fill_key_map(case_insensitive_key_map_t& key_map) {
bool ret = Sprite::_fill_key_map(key_map);
ret &= add_key_map_entries(key_map,
"textureFile1", ONE_EXACTLY, expect_string(assign_variable_callback_string(overlay_file)),
diff --git a/src/openvic-simulation/interface/GFX.hpp b/src/openvic-simulation/interface/GFX.hpp
index efd2293..21baa85 100644
--- a/src/openvic-simulation/interface/GFX.hpp
+++ b/src/openvic-simulation/interface/GFX.hpp
@@ -52,7 +52,7 @@ namespace OpenVic::GFX {
protected:
TextureSprite();
- bool _fill_key_map(NodeTools::key_map_t& key_map) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map) override;
public:
TextureSprite(TextureSprite&&) = default;
@@ -70,7 +70,7 @@ namespace OpenVic::GFX {
protected:
TileTextureSprite();
- bool _fill_key_map(NodeTools::key_map_t& key_map) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map) override;
public:
TileTextureSprite(TileTextureSprite&&) = default;
@@ -93,7 +93,7 @@ namespace OpenVic::GFX {
protected:
ProgressBar();
- bool _fill_key_map(NodeTools::key_map_t& key_map) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map) override;
public:
ProgressBar(ProgressBar&&) = default;
@@ -110,7 +110,7 @@ namespace OpenVic::GFX {
protected:
PieChart();
- bool _fill_key_map(NodeTools::key_map_t& key_map) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map) override;
public:
PieChart(PieChart&&) = default;
@@ -128,7 +128,7 @@ namespace OpenVic::GFX {
protected:
LineChart();
- bool _fill_key_map(NodeTools::key_map_t& key_map) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map) override;
public:
LineChart(LineChart&&) = default;
@@ -146,7 +146,7 @@ namespace OpenVic::GFX {
protected:
MaskedFlag();
- bool _fill_key_map(NodeTools::key_map_t& key_map) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map) override;
public:
MaskedFlag(MaskedFlag&&) = default;
diff --git a/src/openvic-simulation/interface/GUI.cpp b/src/openvic-simulation/interface/GUI.cpp
index 23a577c..7aebfe8 100644
--- a/src/openvic-simulation/interface/GUI.cpp
+++ b/src/openvic-simulation/interface/GUI.cpp
@@ -8,7 +8,7 @@ using namespace OpenVic::NodeTools;
Element::Element() : position {}, orientation { orientation_t::UPPER_LEFT } {}
-bool Element::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) {
+bool Element::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) {
bool ret = Named::_fill_key_map(key_map, ui_manager);
using enum orientation_t;
static const string_map_t<orientation_t> orientation_map = {
@@ -18,14 +18,13 @@ bool Element::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_m
};
ret &= add_key_map_entries(key_map,
"position", ONE_EXACTLY, expect_fvec2(assign_variable_callback(position)),
- "orientation", ZERO_OR_ONE, expect_string(expect_mapped_string(orientation_map, assign_variable_callback(orientation))),
- "Orientation", ZERO_OR_ONE, expect_string(expect_mapped_string(orientation_map, assign_variable_callback(orientation)))
+ "orientation", ZERO_OR_ONE, expect_string(expect_mapped_string(orientation_map, assign_variable_callback(orientation)))
);
return ret;
}
bool Element::_fill_elements_key_map(
- NodeTools::key_map_t& key_map, callback_t<std::unique_ptr<Element>&&> callback, UIManager const& ui_manager
+ NodeTools::case_insensitive_key_map_t& key_map, callback_t<std::unique_ptr<Element>&&> callback, UIManager const& ui_manager
) {
bool ret = true;
ret &= add_key_map_entries(key_map,
@@ -42,7 +41,7 @@ bool Element::_fill_elements_key_map(
return ret;
}
-bool Scene::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) {
+bool Scene::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) {
return Element::_fill_elements_key_map(key_map, [this](std::unique_ptr<Element>&& element) -> bool {
return scene_elements.add_item(std::move(element));
}, ui_manager);
@@ -59,7 +58,7 @@ node_callback_t Scene::expect_scene(
Window::Window() : moveable { false }, fullscreen { false } {}
-bool Window::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) {
+bool Window::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) {
bool ret = Element::_fill_elements_key_map(key_map, [this](std::unique_ptr<Element>&& element) -> bool {
return window_elements.add_item(std::move(element));
}, ui_manager);
@@ -78,7 +77,7 @@ bool Window::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_ma
Icon::Icon() : sprite { nullptr }, frame { GFX::NO_FRAMES } {}
-bool Icon::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) {
+bool Icon::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) {
bool ret = Element::_fill_key_map(key_map, ui_manager);
ret &= add_key_map_entries(key_map,
"spriteType", ONE_EXACTLY, expect_string(ui_manager.expect_sprite_str(assign_variable_callback_pointer(sprite))),
@@ -89,7 +88,7 @@ bool Icon::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_mana
BaseButton::BaseButton() : sprite { nullptr } {}
-bool BaseButton::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) {
+bool BaseButton::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) {
bool ret = Element::_fill_key_map(key_map, ui_manager);
// look up sprite registry for texture sprite with name...
ret &= add_key_map_entries(key_map,
@@ -104,7 +103,7 @@ bool BaseButton::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& u
Button::Button() : text {}, font { nullptr} {}
-bool Button::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) {
+bool Button::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) {
bool ret = BaseButton::_fill_key_map(key_map, ui_manager);
ret &= add_key_map_entries(key_map,
"buttonText", ZERO_OR_ONE, expect_string(assign_variable_callback_string(text), true),
@@ -118,14 +117,14 @@ bool Button::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_ma
return ret;
}
-bool Checkbox::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) {
+bool Checkbox::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) {
bool ret = BaseButton::_fill_key_map(key_map, ui_manager);
return ret;
}
AlignedElement::AlignedElement() : format { format_t::left } {}
-bool AlignedElement::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) {
+bool AlignedElement::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) {
bool ret = Element::_fill_key_map(key_map, ui_manager);
using enum format_t;
static const string_map_t<format_t> format_map = {
@@ -139,7 +138,7 @@ bool AlignedElement::_fill_key_map(NodeTools::key_map_t& key_map, UIManager cons
Text::Text() : text {}, font { nullptr } {}
-bool Text::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) {
+bool Text::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) {
bool ret = AlignedElement::_fill_key_map(key_map, ui_manager);
ret &= add_key_map_entries(key_map,
"text", ZERO_OR_ONE, expect_string(assign_variable_callback_string(text), true),
@@ -158,7 +157,7 @@ bool Text::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_mana
OverlappingElementsBox::OverlappingElementsBox() : size {} {}
-bool OverlappingElementsBox::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) {
+bool OverlappingElementsBox::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) {
bool ret = AlignedElement::_fill_key_map(key_map, ui_manager);
ret &= add_key_map_entries(key_map,
"size", ONE_EXACTLY, expect_fvec2(assign_variable_callback(size)),
@@ -169,7 +168,7 @@ bool OverlappingElementsBox::_fill_key_map(NodeTools::key_map_t& key_map, UIMana
ListBox::ListBox() : size {} {}
-bool ListBox::_fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) {
+bool ListBox::_fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) {
bool ret = Element::_fill_key_map(key_map, ui_manager);
ret &= add_key_map_entries(key_map,
"backGround", ZERO_OR_ONE, success_callback,
diff --git a/src/openvic-simulation/interface/GUI.hpp b/src/openvic-simulation/interface/GUI.hpp
index d658adf..96bb2a2 100644
--- a/src/openvic-simulation/interface/GUI.hpp
+++ b/src/openvic-simulation/interface/GUI.hpp
@@ -23,9 +23,9 @@ namespace OpenVic::GUI {
protected:
Element();
- bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) override;
static bool _fill_elements_key_map(
- NodeTools::key_map_t& key_map, NodeTools::callback_t<std::unique_ptr<Element>&&> callback,
+ NodeTools::case_insensitive_key_map_t& key_map, NodeTools::callback_t<std::unique_ptr<Element>&&> callback,
UIManager const& ui_manager
);
@@ -45,7 +45,7 @@ namespace OpenVic::GUI {
protected:
Scene() = default;
- bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) override;
public:
Scene(Scene&&) = default;
@@ -72,7 +72,7 @@ namespace OpenVic::GUI {
protected:
Window();
- bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) override;
public:
Window(Window&&) = default;
@@ -90,7 +90,7 @@ namespace OpenVic::GUI {
protected:
Icon();
- bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) override;
public:
Icon(Icon&&) = default;
@@ -106,7 +106,7 @@ namespace OpenVic::GUI {
protected:
BaseButton();
- bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) override;
public:
BaseButton(BaseButton&&) = default;
@@ -126,7 +126,7 @@ namespace OpenVic::GUI {
protected:
Button();
- bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) override;
public:
Button(Button&&) = default;
@@ -141,7 +141,7 @@ namespace OpenVic::GUI {
protected:
Checkbox() = default;
- bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) override;
public:
Checkbox(Checkbox&&) = default;
@@ -162,7 +162,7 @@ namespace OpenVic::GUI {
protected:
AlignedElement();
- bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) override;
public:
AlignedElement(AlignedElement&&) = default;
@@ -183,7 +183,7 @@ namespace OpenVic::GUI {
protected:
Text();
- bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) override;
public:
Text(Text&&) = default;
@@ -201,7 +201,7 @@ namespace OpenVic::GUI {
protected:
OverlappingElementsBox();
- bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) override;
public:
OverlappingElementsBox(OverlappingElementsBox&&) = default;
@@ -220,7 +220,7 @@ namespace OpenVic::GUI {
protected:
ListBox();
- bool _fill_key_map(NodeTools::key_map_t& key_map, UIManager const& ui_manager) override;
+ bool _fill_key_map(NodeTools::case_insensitive_key_map_t& key_map, UIManager const& ui_manager) override;
public:
ListBox(ListBox&&) = default;
diff --git a/src/openvic-simulation/interface/LoadBase.hpp b/src/openvic-simulation/interface/LoadBase.hpp
index 3363651..10b0169 100644
--- a/src/openvic-simulation/interface/LoadBase.hpp
+++ b/src/openvic-simulation/interface/LoadBase.hpp
@@ -10,14 +10,14 @@ namespace OpenVic {
protected:
LoadBase() = default;
- virtual bool _fill_key_map(NodeTools::key_map_t&, Context...) = 0;
+ virtual bool _fill_key_map(NodeTools::case_insensitive_key_map_t&, Context...) = 0;
public:
LoadBase(LoadBase&&) = default;
virtual ~LoadBase() = default;
bool load(ast::NodeCPtr node, Context... context) {
- NodeTools::key_map_t key_map;
+ NodeTools::case_insensitive_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;
@@ -45,7 +45,7 @@ namespace OpenVic {
protected:
Named() = default;
- virtual bool _fill_key_map(NodeTools::key_map_t& key_map, Context...) override {
+ virtual bool _fill_key_map(NodeTools::case_insensitive_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)));
}
diff --git a/src/openvic-simulation/map/TerrainType.cpp b/src/openvic-simulation/map/TerrainType.cpp
index e7dd068..93a5e83 100644
--- a/src/openvic-simulation/map/TerrainType.cpp
+++ b/src/openvic-simulation/map/TerrainType.cpp
@@ -1,7 +1,5 @@
#include "TerrainType.hpp"
-#include <limits>
-
#include "openvic-simulation/types/Colour.hpp"
using namespace OpenVic;
@@ -132,7 +130,9 @@ TerrainTypeMapping::index_t TerrainTypeManager::get_terrain_texture_limit() cons
bool TerrainTypeManager::load_terrain_types(ModifierManager const& modifier_manager, ast::NodeCPtr root) {
const bool ret = expect_dictionary_keys_reserve_length_and_default(
terrain_type_mappings,
- std::bind_front(&TerrainTypeManager::_load_terrain_type_mapping, this),
+ [this](std::string_view key, ast::NodeCPtr value) -> bool {
+ return _load_terrain_type_mapping(key, value);
+ },
"terrain", ONE_EXACTLY, expect_uint(assign_variable_callback(terrain_texture_limit)),
"categories", ONE_EXACTLY, _load_terrain_type_categories(modifier_manager)
)(root);
diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp
index 4d002e7..7e6fdb3 100644
--- a/src/openvic-simulation/types/IdentifierRegistry.hpp
+++ b/src/openvic-simulation/types/IdentifierRegistry.hpp
@@ -142,26 +142,11 @@ namespace OpenVic {
}
};
- /* 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<
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 */
+ StringMapCase Case = StringMapCaseSensitive /* Identifier map parameters */
>
requires(
RegistryItemInfo<_ItemInfo, typename ValueInfo::internal_value_type> &&
@@ -177,8 +162,7 @@ namespace OpenVic {
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>;
+ using identifier_index_map_t = template_string_map_t<index_type, Case>;
public:
using storage_type = typename StorageInfo::storage_type;
@@ -440,50 +424,49 @@ namespace OpenVic {
/* Item Specialisations */
template<
RegistryValueInfo ValueInfo, template<typename> typename StorageInfo = RegistryStorageInfoVector,
- RegistryIdentifierMapInfo IdentifierMapInfo = RegistryIdentifierMapInfoCaseSensitive
+ StringMapCase Case = StringMapCaseSensitive
>
- requires RegistryStorageInfo<StorageInfo, typename RegistryItemInfoValue<typename ValueInfo::internal_value_type>::item_type>
- using ValueRegistry = UniqueKeyRegistry<ValueInfo, RegistryItemInfoValue, StorageInfo, IdentifierMapInfo>;
+ requires
+ RegistryStorageInfo<StorageInfo, typename RegistryItemInfoValue<typename ValueInfo::internal_value_type>::item_type>
+ using ValueRegistry = UniqueKeyRegistry<ValueInfo, RegistryItemInfoValue, StorageInfo, Case>;
template<
RegistryValueInfo ValueInfo, template<typename> typename StorageInfo = RegistryStorageInfoVector,
- RegistryIdentifierMapInfo IdentifierMapInfo = RegistryIdentifierMapInfoCaseSensitive
+ StringMapCase Case = StringMapCaseSensitive
>
- requires RegistryStorageInfo<StorageInfo, typename RegistryItemInfoInstance<typename ValueInfo::internal_value_type>::item_type>
- using InstanceRegistry = UniqueKeyRegistry<ValueInfo, RegistryItemInfoInstance, StorageInfo, IdentifierMapInfo>;
+ requires
+ RegistryStorageInfo<StorageInfo, typename RegistryItemInfoInstance<typename ValueInfo::internal_value_type>::item_type>
+ using InstanceRegistry = UniqueKeyRegistry<ValueInfo, RegistryItemInfoInstance, StorageInfo, Case>;
/* HasIdentifier Specialisations */
template<
std::derived_from<HasIdentifier> Value, template<typename> typename StorageInfo = RegistryStorageInfoVector,
- RegistryIdentifierMapInfo IdentifierMapInfo = RegistryIdentifierMapInfoCaseSensitive
+ StringMapCase Case = StringMapCaseSensitive
>
- using IdentifierRegistry = ValueRegistry<RegistryValueInfoHasIdentifier<Value>, StorageInfo, IdentifierMapInfo>;
+ using IdentifierRegistry = ValueRegistry<RegistryValueInfoHasIdentifier<Value>, StorageInfo, Case>;
template<
std::derived_from<HasIdentifier> Value, template<typename> typename StorageInfo = RegistryStorageInfoVector,
- RegistryIdentifierMapInfo IdentifierMapInfo = RegistryIdentifierMapInfoCaseSensitive
+ StringMapCase Case = StringMapCaseSensitive
>
using IdentifierPointerRegistry =
- ValueRegistry<RegistryValueInfoPointer<RegistryValueInfoHasIdentifier<Value>>, StorageInfo, IdentifierMapInfo>;
+ ValueRegistry<RegistryValueInfoPointer<RegistryValueInfoHasIdentifier<Value>>, StorageInfo, Case>;
template<
std::derived_from<HasIdentifier> Value, template<typename> typename StorageInfo = RegistryStorageInfoVector,
- RegistryIdentifierMapInfo IdentifierMapInfo = RegistryIdentifierMapInfoCaseSensitive
+ StringMapCase Case = StringMapCaseSensitive
>
- using IdentifierInstanceRegistry = InstanceRegistry<RegistryValueInfoHasIdentifier<Value>, StorageInfo, IdentifierMapInfo>;
+ using IdentifierInstanceRegistry = InstanceRegistry<RegistryValueInfoHasIdentifier<Value>, StorageInfo, Case>;
/* Case-Insensitive HasIdentifier Specialisations */
template<std::derived_from<HasIdentifier> Value, template<typename> typename StorageInfo = RegistryStorageInfoVector>
- using CaseInsensitiveIdentifierRegistry =
- IdentifierRegistry<Value, StorageInfo, RegistryIdentifierMapInfoCaseInsensitive>;
+ using CaseInsensitiveIdentifierRegistry = IdentifierRegistry<Value, StorageInfo, StringMapCaseInsensitive>;
template<std::derived_from<HasIdentifier> Value, template<typename> typename StorageInfo = RegistryStorageInfoVector>
- using CaseInsensitiveIdentifierPointerRegistry =
- IdentifierPointerRegistry<Value, StorageInfo, RegistryIdentifierMapInfoCaseInsensitive>;
+ using CaseInsensitiveIdentifierPointerRegistry = IdentifierPointerRegistry<Value, StorageInfo, StringMapCaseInsensitive>;
template<std::derived_from<HasIdentifier> Value, template<typename> typename StorageInfo = RegistryStorageInfoVector>
- using CaseInsensitiveIdentifierInstanceRegistry =
- IdentifierInstanceRegistry<Value, StorageInfo, RegistryIdentifierMapInfoCaseInsensitive>;
+ using CaseInsensitiveIdentifierInstanceRegistry = IdentifierInstanceRegistry<Value, StorageInfo, StringMapCaseInsensitive>;
/* Macros to generate declaration and constant accessor methods for a UniqueKeyRegistry member variable. */
diff --git a/src/openvic-simulation/types/OrderedContainers.hpp b/src/openvic-simulation/types/OrderedContainers.hpp
index e9f8717..31bf17a 100644
--- a/src/openvic-simulation/types/OrderedContainers.hpp
+++ b/src/openvic-simulation/types/OrderedContainers.hpp
@@ -72,17 +72,17 @@ namespace OpenVic {
using ordered_set = vector_ordered_set<Key, Hash, KeyEqual, Allocator, IndexType>;
template<typename T>
- concept IsOrderedMap = utility::is_specialization_of_v<T, tsl::ordered_map>;
+ concept IsOrderedMap = utility::is_derived_from_specialization_of<T, tsl::ordered_map>;
template<typename T>
- concept IsOrderedSet = utility::is_specialization_of_v<T, tsl::ordered_set>;
+ concept IsOrderedSet = utility::is_derived_from_specialization_of<T, tsl::ordered_set>;
template<typename T>
- concept IsVectorOrderedMap = utility::is_specialization_of_v<T, vector_ordered_map>;
+ concept IsVectorOrderedMap = utility::is_derived_from_specialization_of<T, vector_ordered_map>;
template<typename T>
- concept IsVectorOrderedSet = utility::is_specialization_of_v<T, vector_ordered_set>;
+ concept IsVectorOrderedSet = utility::is_derived_from_specialization_of<T, vector_ordered_set>;
template<typename T>
- concept IsDequeOrderedMap = utility::is_specialization_of_v<T, deque_ordered_map>;
+ concept IsDequeOrderedMap = utility::is_derived_from_specialization_of<T, deque_ordered_map>;
template<typename T>
- concept IsDequeOrderedSet = utility::is_specialization_of_v<T, deque_ordered_set>;
+ concept IsDequeOrderedSet = utility::is_derived_from_specialization_of<T, deque_ordered_set>;
template<typename T, typename Key, typename Value>
concept IsOrderedMapOf =
@@ -162,4 +162,44 @@ namespace OpenVic {
template<class Key, class Allocator = std::allocator<Key>, class IndexType = std::uint_least32_t>
using case_insensitive_ordered_set = case_insensitive_vector_ordered_set<Key, Allocator, IndexType>;
+
+ template<typename Case>
+ concept StringMapCase = requires(std::string_view identifier) {
+ { typename Case::hash {}(identifier) } -> std::same_as<std::size_t>;
+ { typename Case::equal {}(identifier, identifier) } -> std::same_as<bool>;
+ };
+ struct StringMapCaseSensitive {
+ using hash = container_hash<std::string>;
+ using equal = std::equal_to<>;
+ };
+ struct StringMapCaseInsensitive {
+ using hash = case_insensitive_string_hash;
+ using equal = case_insensitive_string_equal;
+ };
+
+ /* Intermediate struct that "remembers" Case, instead of just decomposing it into its hash and equal components,
+ * needed so that templates can deduce the Case with which a type was defined. */
+ template<template<typename...> typename Container, StringMapCase Case, typename... Args>
+ struct template_case_container_t : Container<Args..., typename Case::hash, typename Case::equal> {
+ using container_t = Container<Args..., typename Case::hash, typename Case::equal>;
+ using container_t::container_t;
+
+ using case_t = Case;
+ };
+
+ /* Template for map with string keys, supporting search by string_view without creating an intermediate string. */
+ template<typename T, StringMapCase Case>
+ using template_string_map_t = template_case_container_t<ordered_map, Case, std::string, T>;
+
+ template<typename T>
+ using string_map_t = template_string_map_t<T, StringMapCaseSensitive>;
+ template<typename T>
+ using case_insensitive_string_map_t = template_string_map_t<T, StringMapCaseInsensitive>;
+
+ /* Template for set with string elements, supporting search by string_view without creating an intermediate string. */
+ template<StringMapCase Case>
+ using template_string_set_t = template_case_container_t<ordered_set, Case, std::string>;
+
+ using string_set_t = template_string_set_t<StringMapCaseSensitive>;
+ using case_insensitive_string_set_t = template_string_set_t<StringMapCaseInsensitive>;
}
diff --git a/src/openvic-simulation/utility/Utility.hpp b/src/openvic-simulation/utility/Utility.hpp
index 9951532..8180e55 100644
--- a/src/openvic-simulation/utility/Utility.hpp
+++ b/src/openvic-simulation/utility/Utility.hpp
@@ -81,6 +81,14 @@ namespace OpenVic::utility {
template<typename T, template<typename...> class Z>
inline constexpr bool is_specialization_of_v = is_specialization_of<T, Z>::value;
+ template <template<typename...> class Template, typename... Args>
+ void _derived_from_specialization_impl(const Template<Args...>&);
+
+ template <typename T, template<typename...> class Template>
+ concept is_derived_from_specialization_of = requires(const T& t) {
+ _derived_from_specialization_impl<Template>(t);
+ };
+
inline constexpr auto three_way(auto&& left, auto&& right) {
// This is Apple's fault again
#if __cpp_lib_three_way_comparison >= 201907L