From ea17456ce2b89ccf1dc5f46eaba28d7e1de8fffb Mon Sep 17 00:00:00 2001 From: wvpm <24685035+wvpm@users.noreply.github.com> Date: Fri, 22 May 2026 23:40:57 +0200 Subject: [PATCH] IdentifierRegistry replacement types --- src/openvic-simulation/InstanceManager.cpp | 15 +- .../console/ConsoleInstance.cpp | 10 +- .../country/CountryDefinition.hpp | 4 +- .../country/CountryDefinitionManager.cpp | 43 +-- .../country/CountryDefinitionManager.hpp | 5 +- .../country/CountryInstance.cpp | 4 +- .../country/CountryInstanceManager.cpp | 16 +- .../dataloader/Dataloader.cpp | 11 +- .../dataloader/IdentifierPolicy.hpp | 15 + .../history/CountryHistory.cpp | 31 +-- .../history/DiplomaticHistory.cpp | 63 +++-- .../history/ProvinceHistory.cpp | 26 +- .../military/DeploymentManager.cpp | 13 +- .../military/UnitTypeManager.cpp | 28 +- .../military/UnitTypeManager.hpp | 12 +- src/openvic-simulation/misc/GameAction.cpp | 11 +- .../population/CultureManager.cpp | 33 +-- src/openvic-simulation/population/Pop.cpp | 2 +- .../population/PopManager.cpp | 19 +- .../population/PopsAggregate.cpp | 2 +- .../research/InventionManager.cpp | 25 +- .../research/TechnologyManager.cpp | 21 +- .../scripts/ConditionManager.cpp | 29 +- .../types/registries/OwningRegistry.hpp | 120 ++++++++ .../registries/OwningRegistry_Modify.hpp | 166 +++++++++++ .../registries/OwningRegistry_NodeTools.hpp | 258 ++++++++++++++++++ .../registries/OwningRegistry_Search.hpp | 126 +++++++++ 27 files changed, 917 insertions(+), 191 deletions(-) create mode 100644 src/openvic-simulation/dataloader/IdentifierPolicy.hpp create mode 100644 src/openvic-simulation/types/registries/OwningRegistry.hpp create mode 100644 src/openvic-simulation/types/registries/OwningRegistry_Modify.hpp create mode 100644 src/openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp create mode 100644 src/openvic-simulation/types/registries/OwningRegistry_Search.hpp diff --git a/src/openvic-simulation/InstanceManager.cpp b/src/openvic-simulation/InstanceManager.cpp index 022406351..095f4fcdc 100644 --- a/src/openvic-simulation/InstanceManager.cpp +++ b/src/openvic-simulation/InstanceManager.cpp @@ -4,6 +4,7 @@ #include "openvic-simulation/console/ConsoleInstance.hpp" #include "openvic-simulation/core/stl/containers/TypedSpan.hpp" #include "openvic-simulation/misc/GameAction.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" #include "openvic-simulation/utility/Logger.hpp" #include "openvic-simulation/utility/ThreadDeps.hpp" @@ -67,8 +68,12 @@ InstanceManager::InstanceManager( }, new_definition_manager.get_pop_manager().get_pop_types(), new_definition_manager.get_politics_manager().get_issue_manager().get_reform_groups(), - new_definition_manager.get_military_manager().get_unit_type_manager().get_regiment_types(), - new_definition_manager.get_military_manager().get_unit_type_manager().get_ship_types(), + get_values( + new_definition_manager.get_military_manager().get_unit_type_manager().get_regiment_types() + ), + get_values( + new_definition_manager.get_military_manager().get_unit_type_manager().get_ship_types() + ), new_definition_manager.get_pop_manager().get_stratas(), new_definition_manager.get_research_manager().get_technology_manager().get_technologies(), new_definition_manager.get_military_manager().get_unit_type_manager() @@ -115,7 +120,9 @@ InstanceManager::InstanceManager( good_instance_manager, new_definition_manager.get_define_manager().get_pops_defines(), new_definition_manager.get_pop_manager().get_pop_types(), - new_definition_manager.get_military_manager().get_unit_type_manager().get_regiment_types(), + get_values( + new_definition_manager.get_military_manager().get_unit_type_manager().get_regiment_types() + ), thread_pool }, unit_instance_manager { @@ -244,7 +251,7 @@ bool InstanceManager::setup() { definition_manager.get_define_manager().get_pops_defines(), definition_manager.get_economy_manager().get_production_type_manager(), definition_manager.get_modifier_manager().get_static_modifier_cache(), - country_index_t(definition_manager.get_country_definition_manager().get_country_definition_count()), + country_index_t(definition_manager.get_country_definition_manager().get_country_definitions().size()), good_index_t(definition_manager.get_economy_manager().get_good_definition_manager().get_good_definition_count()), strata_index_t(definition_manager.get_pop_manager().get_strata_count()) }, diff --git a/src/openvic-simulation/console/ConsoleInstance.cpp b/src/openvic-simulation/console/ConsoleInstance.cpp index c2dd684c6..67cbf0373 100644 --- a/src/openvic-simulation/console/ConsoleInstance.cpp +++ b/src/openvic-simulation/console/ConsoleInstance.cpp @@ -22,6 +22,7 @@ #include "openvic-simulation/research/Technology.hpp" #include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/types/Date.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" using namespace OpenVic; using namespace std::string_view_literals; @@ -222,15 +223,14 @@ CountryInstance* ConsoleInstance::validate_country_tag(std::string_view value_st return nullptr; } - CountryDefinition const* const country_definition_ptr = instance_manager - .definition_manager.get_country_definition_manager() - .get_country_definition_by_identifier(value_string); + auto const& country_definitions = instance_manager.definition_manager.get_country_definition_manager().get_country_definitions(); + const auto it = find(country_definitions, value_string); - if (country_definition_ptr == nullptr) { + if (it == country_definitions.end()) { write_error("Unknown country"); return nullptr; } - return &instance_manager.get_country_instance_manager().get_country_instance_by_index(country_definition_ptr->index); + return &instance_manager.get_country_instance_manager().get_country_instance_by_index((*it).index); } Event const* ConsoleInstance::validate_event_id(std::string_view value_string) { diff --git a/src/openvic-simulation/country/CountryDefinition.hpp b/src/openvic-simulation/country/CountryDefinition.hpp index 7bf9ba2b1..f758383d7 100644 --- a/src/openvic-simulation/country/CountryDefinition.hpp +++ b/src/openvic-simulation/country/CountryDefinition.hpp @@ -11,8 +11,8 @@ #include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/HasIndex.hpp" -#include "openvic-simulation/types/IdentifierRegistry.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" +#include "openvic-simulation/types/registries/OwningRegistry.hpp" #include "openvic-simulation/types/TypedIndices.hpp" namespace OpenVic { @@ -23,7 +23,6 @@ namespace OpenVic { /* Generic information about a TAG */ struct CountryDefinition : HasIdentifierAndColour, HasIndex { friend struct CountryDefinitionManager; - IdentifierRegistry IDENTIFIER_REGISTRY_CUSTOM_PLURAL(party, parties); private: memory::FixedVector< // for each ship type @@ -41,6 +40,7 @@ namespace OpenVic { public: const bool is_dynamic_tag; + const OwningRegistry parties; GraphicalCultureType const& graphical_culture; OV_ALWAYS_INLINE bool is_rebel_country() const { diff --git a/src/openvic-simulation/country/CountryDefinitionManager.cpp b/src/openvic-simulation/country/CountryDefinitionManager.cpp index 66d676b1d..0fcf5921f 100644 --- a/src/openvic-simulation/country/CountryDefinitionManager.cpp +++ b/src/openvic-simulation/country/CountryDefinitionManager.cpp @@ -14,6 +14,8 @@ #include "openvic-simulation/types/ConstructorTags.hpp" #include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Modify.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp" #include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/utility/Logger.hpp" @@ -44,9 +46,10 @@ bool CountryDefinitionManager::add_country( static constexpr colour_t default_colour = colour_t::fill_as(colour_t::max_value); - return country_definitions.emplace_item( + return try_emplace_item( + country_definitions, identifier, - identifier, colour, country_index_t(country_definitions.size()), *graphical_culture, + identifier, colour, country_definitions.size(), *graphical_culture, std::move(parties), std::move(ship_names), is_dynamic_tag, std::move(alternative_colours), /* Default to country colour for the chest and grey for the others. Update later if necessary. */ colour, default_colour, default_colour @@ -63,8 +66,8 @@ bool CountryDefinitionManager::load_countries( const bool ret = expect_dictionary_and_length( [this](const std::size_t country_count) -> std::size_t { - reserve_country_definitions(country_count); - return get_country_definitions_capacity(); + country_definitions.clear_and_reserve(country_index_t(country_count)); + return country_count; }, [this, &definition_manager, &is_dynamic, &dataloader](std::string_view key, ovdl::v2script::ast::Node const* value) -> bool { if (key == "dynamic_tags") { @@ -100,7 +103,7 @@ bool CountryDefinitionManager::load_countries( return false; } )(root); - lock_country_definitions(); + lock_registry(country_definitions); return ret; } @@ -109,16 +112,13 @@ bool CountryDefinitionManager::load_country_colours(ovdl::v2script::ast::Node co NodeTools::default_length_callback, NodeTools::expect_assign( [this](std::string_view identifier, ovdl::v2script::ast::Node const* node) -> bool { - //temporary fix till OwningRegistry replaces this entirely - CountryDefinition* country_definition_ptr = const_cast( - get_country_definition_by_identifier(identifier) - ); - if (country_definition_ptr == nullptr) { + const auto it = find(country_definitions, identifier); + if (it == country_definitions.end()) { spdlog::warn_s("country_colors.txt references country tag {} which is not defined!", identifier); return true; } - CountryDefinition& country = *country_definition_ptr; + CountryDefinition& country = *it; return expect_dictionary_keys( "color1", ONE_EXACTLY, expect_colour(assign_variable_callback(country.primary_unit_colour)), "color2", ONE_EXACTLY, expect_colour(assign_variable_callback(country.secondary_unit_colour)), @@ -217,9 +217,9 @@ bool CountryDefinitionManager::load_country_data_file( ) { colour_t colour; GraphicalCultureType const* graphical_culture; - auto const& unit_type_manager = definition_manager.get_military_manager().get_unit_type_manager(); + auto const& ship_types = definition_manager.get_military_manager().get_unit_type_manager().get_ship_types(); decltype(CountryDefinition::ship_names) ship_names { - ship_type_index_t(unit_type_manager.get_ship_type_count()), + ship_types.size(), [](const ship_type_index_t) { return create_empty; } }; decltype(CountryDefinition::alternative_colours) alternative_colours; @@ -238,10 +238,11 @@ bool CountryDefinitionManager::load_country_data_file( assign_variable_callback_pointer(graphical_culture) ), "party", ZERO_OR_MORE, load_country_party(definition_manager.get_politics_manager(), party_dtos), - "unit_names", ZERO_OR_ONE, unit_type_manager.expect_ship_type_dictionary( - [&ship_names](ShipType const& ship_type, ovdl::v2script::ast::Node const* value) -> bool { + "unit_names", ZERO_OR_ONE, expect_item_dictionary( + ship_types, + [&ship_names](const ship_type_index_t ship_type_index, ovdl::v2script::ast::Node const* value) -> bool { return name_list_callback( - [&ship_names, ship_type_index = ship_type.index](memory::FixedVector&& names) -> bool { + [&ship_names, ship_type_index](memory::FixedVector&& names) -> bool { ship_names[ship_type_index] = std::move(names); return true; } @@ -250,17 +251,17 @@ bool CountryDefinitionManager::load_country_data_file( ) )(root); - IdentifierRegistry parties { "country parties" }; - parties.reserve(party_dtos.size()); + OwningRegistry parties { create_empty, party_dtos.size() }; for (CountryPartyDto& dto : party_dtos) { - ret &= parties.emplace_item( + ret &= try_emplace_item( + parties, dto.identifier, - duplicate_warning_callback, + duplicate_warning_cb, dto.identifier, dto.start_date, dto.end_date, dto.ideology, std::move(dto.policies) ); } - parties.lock(); + lock_registry(parties); ret &= add_country( name, colour, graphical_culture, diff --git a/src/openvic-simulation/country/CountryDefinitionManager.hpp b/src/openvic-simulation/country/CountryDefinitionManager.hpp index 5d46b9bc8..0803dca62 100644 --- a/src/openvic-simulation/country/CountryDefinitionManager.hpp +++ b/src/openvic-simulation/country/CountryDefinitionManager.hpp @@ -5,6 +5,7 @@ #include "openvic-simulation/country/CountryDefinition.hpp" #include "openvic-simulation/dataloader/Node_forwarded.hpp" #include "openvic-simulation/types/ConstructorTags.hpp" +#include "openvic-simulation/types/registries/OwningRegistry.hpp" #include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/utility/Getters.hpp" @@ -15,10 +16,10 @@ namespace OpenVic { struct CountryDefinitionManager { private: - IdentifierRegistry IDENTIFIER_REGISTRY(country_definition); + OwningRegistry PROPERTY(country_definitions); public: - constexpr CountryDefinitionManager() {} + constexpr CountryDefinitionManager() : country_definitions(create_empty) {} bool add_country( std::string_view identifier, colour_t colour, GraphicalCultureType const* graphical_culture, diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp index 5bdc3df4e..7add8e06f 100644 --- a/src/openvic-simulation/country/CountryInstance.cpp +++ b/src/openvic-simulation/country/CountryInstance.cpp @@ -1638,7 +1638,9 @@ void CountryInstance::_update_military() { fixed_point_t::parse_raw(regular_army_size), fixed_point_t::parse_raw( 7 * ( - 1 + unit_type_manager.get_regiment_type_count() + 1 + type_safe::get( + unit_type_manager.get_regiment_types().size() + ) ) ) ) diff --git a/src/openvic-simulation/country/CountryInstanceManager.cpp b/src/openvic-simulation/country/CountryInstanceManager.cpp index a29a82494..4988ea2eb 100644 --- a/src/openvic-simulation/country/CountryInstanceManager.cpp +++ b/src/openvic-simulation/country/CountryInstanceManager.cpp @@ -11,6 +11,7 @@ #include "openvic-simulation/history/CountryHistory.hpp" #include "openvic-simulation/military/UnitInstanceGroup.hpp" #include "openvic-simulation/population/Pop.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" #include "openvic-simulation/utility/ThreadPool.hpp" #if defined(__APPLE__) @@ -38,21 +39,21 @@ CountryInstanceManager::CountryInstanceManager( regiment_types }, country_instances { - country_index_t(new_country_definition_manager.get_country_definition_count()), + new_country_definition_manager.get_country_definitions().size(), [ this, &new_country_definition_manager, &country_instance_deps ](const country_index_t country_index)->auto{ return std::make_tuple( - std::ref(*new_country_definition_manager.get_country_definition_by_index(country_index)), + std::ref(new_country_definition_manager.get_country_definitions()[country_index]), std::ref(shared_country_values), std::ref(country_instance_deps) ); } } { - assert(new_country_definition_manager.country_definitions_are_locked()); + assert(new_country_definition_manager.get_country_definitions().is_locked()); great_powers.reserve(new_country_defines.get_great_power_rank()); secondary_powers.reserve(new_country_defines.get_max_secondary_power_count()); } @@ -186,17 +187,20 @@ CountryDefinition const* find_country_definition_by_identifier( CountryDefinitionManager const& country_definition_manager, std::string_view identifier ) { - return country_definition_manager.get_country_definition_by_identifier(identifier); + const auto it = find(country_definition_manager.get_country_definitions(), identifier); + return it == country_definition_manager.get_country_definitions().end() + ? nullptr + : &*it; } CountryInstance* CountryInstanceManager::get_country_instance_by_identifier(std::string_view identifier) { - CountryDefinition const* country_definition = country_definition_manager.get_country_definition_by_identifier(identifier); + CountryDefinition const* country_definition = find_country_definition_by_identifier(country_definition_manager, identifier); return country_definition == nullptr ? nullptr : &(country_instances[country_definition->index]); } CountryInstance const* CountryInstanceManager::get_country_instance_by_identifier(std::string_view identifier) const { - CountryDefinition const* country_definition = country_definition_manager.get_country_definition_by_identifier(identifier); + CountryDefinition const* country_definition = find_country_definition_by_identifier(country_definition_manager, identifier); return country_definition == nullptr ? nullptr : &(country_instances[country_definition->index]); diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index 2888096cd..5378d826f 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -21,6 +21,7 @@ #include "openvic-simulation/interface/UI.hpp" #include "openvic-simulation/misc/GameRulesManager.hpp" #include "openvic-simulation/misc/SoundEffect.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" #include "openvic-simulation/utility/Logger.hpp" using namespace OpenVic; @@ -605,11 +606,9 @@ bool Dataloader::_load_history(DefinitionManager& definition_manager, bool unuse const memory::string filename = file.stem().string(memory::string::allocator_type{}); const std::string_view country_id = extract_basic_identifier_prefix(filename); - CountryDefinitionManager const& country_definition_manager = definition_manager.get_country_definition_manager(); - CountryDefinition const* country = country_definition_manager.get_country_definition_by_identifier( - country_id - ); - if (country == nullptr) { + auto const& country_definitions = definition_manager.get_country_definition_manager().get_country_definitions(); + const auto it = find(country_definitions, country_id); + if (it == country_definitions.end()) { if (unused_history_file_warnings) { spdlog::warn_s("Found history file for non-existent country: {}", country_id); } @@ -617,7 +616,7 @@ bool Dataloader::_load_history(DefinitionManager& definition_manager, bool unuse } return country_history_manager.load_country_history_file( - definition_manager, *this, *country, + definition_manager, *this, *it, definition_manager.get_politics_manager().get_ideology_manager().get_ideologies(), definition_manager.get_politics_manager().get_government_type_manager().get_government_types(), parse_defines(file).get_file_node() diff --git a/src/openvic-simulation/dataloader/IdentifierPolicy.hpp b/src/openvic-simulation/dataloader/IdentifierPolicy.hpp new file mode 100644 index 000000000..a848d2fed --- /dev/null +++ b/src/openvic-simulation/dataloader/IdentifierPolicy.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include + +namespace OpenVic { + enum struct IdentifierSyntax : uint8_t { + Either, + Identifier, // ENG + String // "ENG" + }; + struct IdentifierValidation { + bool allow_empty = false; + bool warn_on_invalid = false; + }; +} \ No newline at end of file diff --git a/src/openvic-simulation/history/CountryHistory.cpp b/src/openvic-simulation/history/CountryHistory.cpp index 9924ef89c..ccd28d51c 100644 --- a/src/openvic-simulation/history/CountryHistory.cpp +++ b/src/openvic-simulation/history/CountryHistory.cpp @@ -5,6 +5,7 @@ #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/politics/Government.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp" #include "openvic-simulation/core/FormatValidate.hpp" using namespace OpenVic; @@ -158,7 +159,12 @@ bool CountryHistoryMap::_load_history_entry( "civilized", ZERO_OR_ONE, expect_bool(assign_variable_callback(entry.civilised)), "prestige", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.prestige)), "ruling_party", ZERO_OR_ONE, [this, &entry](ovdl::v2script::ast::Node const* value) -> bool { - country.expect_party_identifier(assign_variable_callback_pointer_opt(entry.ruling_party), true)(value); + expect_item( + country.parties, + assign_variable_callback_pointer_opt(entry.ruling_party), + { .warn_on_invalid=true } + )(value); + if (!entry.ruling_party.has_value()) { std::string_view def {}; bool is_valid = true; @@ -166,7 +172,7 @@ bool CountryHistoryMap::_load_history_entry( expect_identifier(assign_variable_callback(def))(value); // if the party specified is invalid, replace with the first valid party - for (const auto& party : country.get_parties()) { + for (const auto& party : country.parties) { if (party.start_date <= entry.date && entry.date < party.end_date) { entry.ruling_party.emplace(&party); break; @@ -176,7 +182,7 @@ bool CountryHistoryMap::_load_history_entry( // if there's somehow no valid party, we use the first defined party even though it isn't valid for the entry if (!entry.ruling_party.has_value()) { is_valid = false; - entry.ruling_party.emplace(&country.get_front_party()); + entry.ruling_party.emplace(&country.parties.front()); } spdlog::log_s( @@ -217,21 +223,10 @@ bool CountryHistoryMap::_load_history_entry( "schools", ZERO_OR_ONE, technology_manager.expect_technology_school_identifier( assign_variable_callback_pointer_opt(entry.tech_school) ), - "foreign_investment", ZERO_OR_ONE, - country_definition_manager.expect_country_definition_decimal_map( - [&entry](fixed_point_map_t ptr_map)->bool { - auto& index_map = entry.foreign_investment; - index_map.clear(); - index_map.reserve(ptr_map.size()); - for (const auto [ptr, weight] : ptr_map) { - index_map.emplace( - ptr->index, - weight - ); - } - return true; - } - ), + "foreign_investment", ZERO_OR_ONE, expect_item_decimal_map( + country_definition_manager.get_country_definitions(), + move_variable_callback(entry.foreign_investment) + ), "literacy", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.literacy)), "non_state_culture_literacy", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.nonstate_culture_literacy)), diff --git a/src/openvic-simulation/history/DiplomaticHistory.cpp b/src/openvic-simulation/history/DiplomaticHistory.cpp index 3214443cc..a3855f823 100644 --- a/src/openvic-simulation/history/DiplomaticHistory.cpp +++ b/src/openvic-simulation/history/DiplomaticHistory.cpp @@ -3,6 +3,7 @@ #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/DefinitionManager.hpp" #include "openvic-simulation/history/DiplomaticHistory.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -59,10 +60,12 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file( std::optional end {}; bool ret = expect_dictionary_keys( - "first", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "first", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(first) ), - "second", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "second", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(second) ), "start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)), @@ -81,10 +84,12 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file( std::optional end {}; bool ret = expect_dictionary_keys( - "first", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "first", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(overlord) ), - "second", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "second", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(subject) ), "start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)), @@ -103,10 +108,12 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file( std::optional end {}; bool ret = expect_dictionary_keys( - "first", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "first", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(overlord) ), - "second", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "second", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(subject) ), "start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)), @@ -125,10 +132,12 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file( std::optional end {}; bool ret = expect_dictionary_keys( - "first", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "first", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(overlord) ), - "second", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "second", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(subject) ), "start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)), @@ -147,10 +156,12 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file( std::optional end {}; bool ret = expect_dictionary_keys( - "first", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "first", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(receiver) ), - "second", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "second", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(sender) ), "start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)), @@ -196,7 +207,8 @@ bool DiplomaticHistoryManager::load_war_history_file(DefinitionManager const& de ret &= expect_dictionary_keys( "add_attacker", ZERO_OR_MORE, - definition_manager.get_country_definition_manager().expect_country_definition_identifier( + expect_item( + definition_manager.get_country_definition_manager().get_country_definitions(), [¤t_date, &name](CountryDefinition const& country) -> bool { for (WarHistory::war_participant_t const& attacker : attackers) { CountryDefinition const& attacker_country = attacker.country; @@ -214,7 +226,8 @@ bool DiplomaticHistoryManager::load_war_history_file(DefinitionManager const& de } ), "add_defender", ZERO_OR_MORE, - definition_manager.get_country_definition_manager().expect_country_definition_identifier( + expect_item( + definition_manager.get_country_definition_manager().get_country_definitions(), [¤t_date, &name](CountryDefinition const& country) -> bool { for (WarHistory::war_participant_t const& defender : defenders) { CountryDefinition const& defender_country = defender.country; @@ -232,7 +245,8 @@ bool DiplomaticHistoryManager::load_war_history_file(DefinitionManager const& de } ), "rem_attacker", ZERO_OR_MORE, - definition_manager.get_country_definition_manager().expect_country_definition_identifier( + expect_item( + definition_manager.get_country_definition_manager().get_country_definitions(), [¤t_date, &name](CountryDefinition const& country) -> bool { WarHistory::war_participant_t* participant_to_remove = nullptr; @@ -256,7 +270,8 @@ bool DiplomaticHistoryManager::load_war_history_file(DefinitionManager const& de } ), "rem_defender", ZERO_OR_MORE, - definition_manager.get_country_definition_manager().expect_country_definition_identifier( + expect_item( + definition_manager.get_country_definition_manager().get_country_definitions(), [¤t_date, &name](CountryDefinition const& country) -> bool { WarHistory::war_participant_t* participant_to_remove = nullptr; @@ -283,23 +298,26 @@ bool DiplomaticHistoryManager::load_war_history_file(DefinitionManager const& de CountryDefinition const* actor = nullptr; CountryDefinition const* receiver = nullptr; WargoalType const* type = nullptr; - std::optional third_party {}; + std::optional third_party {}; std::optional target {}; bool ret = expect_dictionary_keys( "actor", ONE_EXACTLY, - definition_manager.get_country_definition_manager().expect_country_definition_identifier( + expect_item( + definition_manager.get_country_definition_manager().get_country_definitions(), assign_variable_callback_pointer(actor) ), "receiver", ONE_EXACTLY, - definition_manager.get_country_definition_manager().expect_country_definition_identifier( + expect_item( + definition_manager.get_country_definition_manager().get_country_definitions(), assign_variable_callback_pointer(receiver) ), "casus_belli", ONE_EXACTLY, definition_manager.get_military_manager().get_wargoal_type_manager() .expect_wargoal_type_identifier(assign_variable_callback_pointer(type)), "country", ZERO_OR_ONE, - definition_manager.get_country_definition_manager().expect_country_definition_identifier( - assign_variable_callback_pointer_opt(third_party) + expect_index( + definition_manager.get_country_definition_manager().get_country_definitions(), + assign_variable_callback_opt(third_party) ), "state_province_id", ZERO_OR_ONE, definition_manager.get_map_definition().expect_province_definition_identifier( @@ -308,12 +326,7 @@ bool DiplomaticHistoryManager::load_war_history_file(DefinitionManager const& de )(value); if (ret) { - wargoals.emplace_back(current_date, *actor, *receiver, *type, - third_party.has_value() - ? std::optional{ third_party.value()->index } - : std::nullopt, - target - ); + wargoals.emplace_back(current_date, *actor, *receiver, *type, third_party, target); } return ret; } diff --git a/src/openvic-simulation/history/ProvinceHistory.cpp b/src/openvic-simulation/history/ProvinceHistory.cpp index bc39b306b..9dda0b555 100644 --- a/src/openvic-simulation/history/ProvinceHistory.cpp +++ b/src/openvic-simulation/history/ProvinceHistory.cpp @@ -8,6 +8,7 @@ #include "openvic-simulation/economy/BuildingLevel.hpp" #include "openvic-simulation/economy/GoodDefinition.hpp" #include "openvic-simulation/map/ProvinceDefinition.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp" #include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/utility/Logger.hpp" @@ -51,8 +52,7 @@ bool ProvinceHistoryMap::_load_history_entry( }; const auto set_core_instruction = [&entry](bool add) { - return [&entry, add](CountryDefinition const& country_definition) -> bool { - const country_index_t country_index = country_definition.index; + return [&entry, add](const country_index_t country_index) -> bool { const auto it = entry.cores.find(country_index); if (it == entry.cores.end()) { // No current core instruction @@ -133,22 +133,20 @@ bool ProvinceHistoryMap::_load_history_entry( return _load_history_sub_entry_callback(definition_manager, entry.date, value, key_map, key, value); }, - "owner", ZERO_OR_ONE, country_definition_manager.expect_country_definition_identifier( - [&entry](CountryDefinition const& c) -> bool { - entry.owner = c.index; - return true; - } + "owner", ZERO_OR_ONE, expect_index( + country_definition_manager.get_country_definitions(), + assign_variable_callback_opt(entry.owner, true) ), - "controller", ZERO_OR_ONE, country_definition_manager.expect_country_definition_identifier( - [&entry](CountryDefinition const& c) -> bool { - entry.controller = c.index; - return true; - } + "controller", ZERO_OR_ONE, expect_index( + country_definition_manager.get_country_definitions(), + assign_variable_callback_opt(entry.controller, true) ), - "add_core", ZERO_OR_MORE, country_definition_manager.expect_country_definition_identifier( + "add_core", ZERO_OR_MORE, expect_index( + country_definition_manager.get_country_definitions(), set_core_instruction(true) ), - "remove_core", ZERO_OR_MORE, country_definition_manager.expect_country_definition_identifier( + "remove_core", ZERO_OR_MORE, expect_index( + country_definition_manager.get_country_definitions(), set_core_instruction(false) ), "colonial", ZERO_OR_ONE, diff --git a/src/openvic-simulation/military/DeploymentManager.cpp b/src/openvic-simulation/military/DeploymentManager.cpp index a3d92aaa6..c5c5c2989 100644 --- a/src/openvic-simulation/military/DeploymentManager.cpp +++ b/src/openvic-simulation/military/DeploymentManager.cpp @@ -6,6 +6,7 @@ #include "openvic-simulation/military/MilitaryManager.hpp" #include "openvic-simulation/military/Leader.hpp" #include "openvic-simulation/military/LeaderTrait.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -161,8 +162,10 @@ bool DeploymentManager::load_oob_file( const bool ret = expect_dictionary_keys( "name", ONE_EXACTLY, expect_string(assign_variable_callback(regiment_name)), - "type", ONE_EXACTLY, military_manager.get_unit_type_manager() - .expect_regiment_type_identifier(assign_variable_callback_pointer(regiment_type)), + "type", ONE_EXACTLY, expect_item( + military_manager.get_unit_type_manager().get_regiment_types(), + assign_variable_callback_pointer(regiment_type) + ), "home", ZERO_OR_ONE, map_definition .expect_province_definition_identifier(assign_variable_callback_pointer(regiment_home)) )(node); @@ -214,8 +217,10 @@ bool DeploymentManager::load_oob_file( const bool ret = expect_dictionary_keys( "name", ONE_EXACTLY, expect_string(assign_variable_callback(ship_name)), - "type", ONE_EXACTLY, military_manager.get_unit_type_manager() - .expect_ship_type_identifier(assign_variable_callback_pointer(ship_type)) + "type", ONE_EXACTLY, expect_item( + military_manager.get_unit_type_manager().get_ship_types(), + assign_variable_callback_pointer(ship_type) + ) )(node); if (ship_type == nullptr) { diff --git a/src/openvic-simulation/military/UnitTypeManager.cpp b/src/openvic-simulation/military/UnitTypeManager.cpp index abd0745f4..777cff748 100644 --- a/src/openvic-simulation/military/UnitTypeManager.cpp +++ b/src/openvic-simulation/military/UnitTypeManager.cpp @@ -9,6 +9,8 @@ #include "openvic-simulation/map/TerrainTypeManager.hpp" #include "openvic-simulation/modifier/ModifierManager.hpp" #include "openvic-simulation/modifier/ModifierEffectCache.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Modify.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" #include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/types/UnitBranchType.hpp" @@ -19,13 +21,13 @@ using enum unit_branch_t; using enum UnitType::unit_category_t; void UnitTypeManager::reserve_all_unit_types(size_t size) { - reserve_more_regiment_types(size); - reserve_more_ship_types(size); + regiment_types.clear_and_reserve(regiment_type_index_t(size)); + ship_types.clear_and_reserve(ship_type_index_t(size)); } void UnitTypeManager::lock_all_unit_types() { - regiment_types.lock(); - ship_types.lock(); + lock_registry(regiment_types); + lock_registry(ship_types); } static bool _check_shared_parameters(std::string_view identifier, UnitType::unit_type_args_t const& unit_args) { @@ -61,14 +63,15 @@ bool UnitTypeManager::add_regiment_type( // TODO check that sprite_override, sprite_mount, and sprite_mount_attach_node exist - if (ship_types.has_identifier(identifier)) { + if (has_identifier(ship_types, identifier)) { spdlog::error_s("Land unit {} already exists as a naval unit!", identifier); return false; } - return regiment_types.emplace_item( + return try_emplace_item( + regiment_types, identifier, - RegimentType::index_t { get_regiment_type_count() }, identifier, + regiment_types.size(), identifier, unit_args, std::move(regiment_type_args) ); } @@ -89,14 +92,15 @@ bool UnitTypeManager::add_ship_type( spdlog::warn_s("Supply consumption score for {} is not positive!", identifier); } - if (regiment_types.has_identifier(identifier)) { + if (has_identifier(regiment_types, identifier)) { spdlog::error_s("Naval unit {} already exists as a land unit!", identifier); return false; } - return ship_types.emplace_item( + return try_emplace_item( + ship_types, identifier, - ShipType::index_t { get_ship_type_count() }, identifier, + ship_types.size(), identifier, unit_args, ship_type_args ); } @@ -313,7 +317,7 @@ bool UnitTypeManager::generate_modifiers(ModifierManager& modifier_manager) cons regiment_type_effects = std::move( decltype(ModifierEffectCache::regiment_type_effects) { generate_values, - regiment_type_index_t(get_regiment_type_count()) + regiment_types.size() } ); @@ -329,7 +333,7 @@ bool UnitTypeManager::generate_modifiers(ModifierManager& modifier_manager) cons ship_type_effects = std::move( decltype(ModifierEffectCache::ship_type_effects) { generate_values, - ship_type_index_t(get_ship_type_count()) + ship_types.size() } ); diff --git a/src/openvic-simulation/military/UnitTypeManager.hpp b/src/openvic-simulation/military/UnitTypeManager.hpp index 939268728..472a80d49 100644 --- a/src/openvic-simulation/military/UnitTypeManager.hpp +++ b/src/openvic-simulation/military/UnitTypeManager.hpp @@ -4,7 +4,9 @@ #include "openvic-simulation/core/template/FunctionalConcepts.hpp" #include "openvic-simulation/military/UnitType.hpp" -#include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/types/ConstructorTags.hpp" +#include "openvic-simulation/types/registries/OwningRegistry.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/types/UnitBranchType.hpp" namespace ovdl::v2script { @@ -18,11 +20,13 @@ namespace OpenVic { struct UnitTypeManager { private: - IdentifierRegistry IDENTIFIER_REGISTRY(regiment_type); - IdentifierRegistry IDENTIFIER_REGISTRY(ship_type); + OwningRegistry PROPERTY(regiment_types); + OwningRegistry PROPERTY(ship_types); public: - constexpr UnitTypeManager() {} + constexpr UnitTypeManager() : + regiment_types(create_empty), + ship_types(create_empty) {} void reserve_all_unit_types(size_t size); void lock_all_unit_types(); diff --git a/src/openvic-simulation/misc/GameAction.cpp b/src/openvic-simulation/misc/GameAction.cpp index 8a468b140..fd28f1a5c 100644 --- a/src/openvic-simulation/misc/GameAction.cpp +++ b/src/openvic-simulation/misc/GameAction.cpp @@ -293,17 +293,16 @@ bool GameActionManager::VariantVisitor::operator() (set_mobilise_argument_t cons bool GameActionManager::VariantVisitor::operator() (start_land_unit_recruitment_argument_t const& argument) const { const auto [regiment_type_index, province_index, pop_id_in_province] = argument; - auto const& unit_type_manager = instance_manager.definition_manager + auto const& regiment_types = instance_manager.definition_manager .get_military_manager() - .get_unit_type_manager(); - if (OV_unlikely(regiment_type_index < regiment_type_index_t{} - || regiment_type_index >= regiment_type_index_t(unit_type_manager.get_regiment_type_count())) - ) { + .get_unit_type_manager() + .get_regiment_types(); + if (OV_unlikely(regiment_type_index < regiment_type_index_t{} || regiment_type_index >= regiment_types.size())) { spdlog::error_s("GAME_ACTION_START_LAND_UNIT_RECRUITMENT called with invalid regiment type index: {}", regiment_type_index); return false; } - RegimentType const& regiment_type = *unit_type_manager.get_regiment_type_by_index(regiment_type_index); + RegimentType const& regiment_type = regiment_types[regiment_type_index]; ProvinceInstance* province = instance_manager .get_map_instance() diff --git a/src/openvic-simulation/population/CultureManager.cpp b/src/openvic-simulation/population/CultureManager.cpp index f52309262..cfc109a66 100644 --- a/src/openvic-simulation/population/CultureManager.cpp +++ b/src/openvic-simulation/population/CultureManager.cpp @@ -10,7 +10,7 @@ #include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/core/string/Utility.hpp" #include "openvic-simulation/core/Typedefs.hpp" -#include "openvic-simulation/types/TypedIndices.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -116,21 +116,23 @@ bool CultureManager::_load_culture_group( std::string_view leader {}; GraphicalCultureType const* unit_graphical_culture_type = default_graphical_culture_type; bool is_overseas = true; - CountryDefinition const* union_country_ptr = nullptr; + std::optional union_country; bool ret = expect_dictionary_keys_and_default( increment_callback(total_expected_cultures), "leader", ZERO_OR_ONE, expect_identifier(assign_variable_callback(leader)), // acts like ONE_EXACTLY, but vic2 doesn't complain and loads anyway if not present, for now I just commuted the error to a warning in the add function and fudged a default leader from the first defined culture group if it exists - brickpi "unit", ZERO_OR_ONE, expect_graphical_culture_type_identifier(assign_variable_callback_pointer(unit_graphical_culture_type)), - "union", ZERO_OR_ONE, - country_definition_manager.expect_country_definition_identifier(assign_variable_callback_pointer(union_country_ptr)), + "union", ZERO_OR_ONE, expect_index( + country_definition_manager.get_country_definitions(), + assign_variable_callback_opt(union_country) + ), "is_overseas", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_overseas)) )(culture_group_node); - ret &= add_culture_group(culture_group_key, leader, unit_graphical_culture_type, is_overseas, - union_country_ptr == nullptr - ? std::optional{} - : std::optional{union_country_ptr->index} + ret &= add_culture_group( + culture_group_key, leader, + unit_graphical_culture_type, is_overseas, + union_country ); return ret; } @@ -142,23 +144,22 @@ bool CultureManager::_load_culture( colour_t colour = colour_t::null(); memory::vector first_names {}, last_names {}; fixed_point_t radicalism = 0; - CountryDefinition const* primary_country_ptr = nullptr; + std::optional primary_country; bool ret = expect_dictionary_keys( "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)), "first_names", ONE_EXACTLY, name_list_callback(move_variable_callback(first_names)), "last_names", ONE_EXACTLY, name_list_callback(move_variable_callback(last_names)), "radicalism", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(radicalism)), - "primary", ZERO_OR_ONE, country_definition_manager.expect_country_definition_identifier( - assign_variable_callback_pointer(primary_country_ptr), - false + "primary", ZERO_OR_ONE, expect_index( + country_definition_manager.get_country_definitions(), + assign_variable_callback_opt(primary_country) ) )(culture_node); ret &= add_culture( - culture_key, colour, culture_group, std::move(first_names), std::move(last_names), radicalism, - primary_country_ptr == nullptr - ? std::nullopt - : std::optional{primary_country_ptr->index} + culture_key, colour, culture_group, + std::move(first_names), std::move(last_names), + radicalism, primary_country ); return ret; } diff --git a/src/openvic-simulation/population/Pop.cpp b/src/openvic-simulation/population/Pop.cpp index 3f11de5be..c5d2db013 100644 --- a/src/openvic-simulation/population/Pop.cpp +++ b/src/openvic-simulation/population/Pop.cpp @@ -223,7 +223,7 @@ void Pop::update_location_based_attributes() { } CountryDefinition const& country_definition = owner->country_definition; - auto view = country_definition.get_parties() | std::views::transform( + auto view = country_definition.parties | std::views::transform( [](CountryParty const& key) { return std::make_pair(&key, fixed_point_t::_0); } diff --git a/src/openvic-simulation/population/PopManager.cpp b/src/openvic-simulation/population/PopManager.cpp index 0bf3e3948..15e4e6eb0 100644 --- a/src/openvic-simulation/population/PopManager.cpp +++ b/src/openvic-simulation/population/PopManager.cpp @@ -14,8 +14,9 @@ #include "openvic-simulation/politics/RebelManager.hpp" #include "openvic-simulation/population/Pop.hpp" #include "openvic-simulation/population/PopSize.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp" #include "openvic-simulation/utility/Logger.hpp" -#include "types/TypedIndices.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -401,19 +402,9 @@ bool PopManager::load_delayed_parse_pop_type_data( pop_type_ptr->promote_to = std::move(decltype(PopType::promote_to){get_pop_types()}); if (rebel_units != nullptr - && !unit_type_manager.expect_regiment_type_decimal_map( - [pop_type_ptr](fixed_point_map_t ptr_map)->bool { - auto& index_map = pop_type_ptr->rebel_units; - index_map.clear(); - index_map.reserve(ptr_map.size()); - for (const auto [ptr, weight] : ptr_map) { - index_map.emplace( - ptr->index, - weight - ); - } - return true; - } + && !expect_item_decimal_map( + unit_type_manager.get_regiment_types(), + move_variable_callback(pop_type_ptr->rebel_units) )(rebel_units) ) { spdlog::error_s("Errors parsing rebel unit distribution for pop type {}!", ovfmt::validate(pop_type_ptr)); diff --git a/src/openvic-simulation/population/PopsAggregate.cpp b/src/openvic-simulation/population/PopsAggregate.cpp index 05eeb25a1..020b1d5b1 100644 --- a/src/openvic-simulation/population/PopsAggregate.cpp +++ b/src/openvic-simulation/population/PopsAggregate.cpp @@ -253,7 +253,7 @@ void PopsAggregate::update_parties_for_votes(CountryDefinition const* country_de return; } - auto view = country_definition->get_parties() | std::views::transform( + auto view = country_definition->parties | std::views::transform( [](CountryParty const& key) { return std::make_pair(&key, fixed_point_t::_0); } diff --git a/src/openvic-simulation/research/InventionManager.cpp b/src/openvic-simulation/research/InventionManager.cpp index 8f3c24a88..8ad1ef9da 100644 --- a/src/openvic-simulation/research/InventionManager.cpp +++ b/src/openvic-simulation/research/InventionManager.cpp @@ -8,6 +8,7 @@ #include "openvic-simulation/military/UnitTypeManager.hpp" #include "openvic-simulation/modifier/ModifierManager.hpp" #include "openvic-simulation/research/TechnologyManager.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -45,11 +46,13 @@ bool InventionManager::load_inventions_file( ModifierValue loose_modifiers; ModifierValue modifiers; - std::remove_const_t activated_regiment_types; - assert(unit_type_manager.regiment_types_are_locked()); + auto const& regiment_types = unit_type_manager.get_regiment_types(); + std::remove_const_t activated_regiment_types; + assert_is_locked(regiment_types); - std::remove_const_t activated_ship_types; - assert(unit_type_manager.ship_types_are_locked()); + auto const& ship_types = unit_type_manager.get_ship_types(); + std::remove_const_t activated_ship_types; + assert_is_locked(ship_types); Invention::building_set_t activated_buildings; Invention::crime_set_t enabled_crimes; @@ -93,17 +96,13 @@ bool InventionManager::load_inventions_file( "activate_unit", ZERO_OR_MORE, NodeTools::expect_identifier( [ &activated_regiment_types, &activated_ship_types, - &unit_type_manager + ®iment_types, &ship_types ](std::string_view identifier) -> bool { - if (RegimentType const* const regiment_type_ptr = unit_type_manager.get_regiment_type_by_identifier(identifier); - regiment_type_ptr != nullptr - ) { - return (activated_regiment_types.emplace(regiment_type_ptr)).second; + if (const auto regiment_it = find(regiment_types, identifier); regiment_it != regiment_types.end()) { + return (activated_regiment_types.emplace(&*regiment_it)).second; } - if (ShipType const* const ship_type_ptr = unit_type_manager.get_ship_type_by_identifier(identifier); - ship_type_ptr != nullptr - ) { - return (activated_ship_types.emplace(ship_type_ptr)).second; + if (const auto ship_it = find(ship_types, identifier); ship_it != ship_types.end()) { + return (activated_ship_types.emplace(&*ship_it)).second; } spdlog::error_s("Invalid regiment type or ship type identifier: {}", identifier); return false; diff --git a/src/openvic-simulation/research/TechnologyManager.cpp b/src/openvic-simulation/research/TechnologyManager.cpp index ec6714a09..55854171e 100644 --- a/src/openvic-simulation/research/TechnologyManager.cpp +++ b/src/openvic-simulation/research/TechnologyManager.cpp @@ -6,6 +6,7 @@ #include "openvic-simulation/military/UnitTypeManager.hpp" #include "openvic-simulation/modifier/ModifierManager.hpp" #include "openvic-simulation/types/TypedIndices.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -183,11 +184,13 @@ bool TechnologyManager::load_technologies_file( bool unciv_military = false; std::optional unit_variant; + auto const& regiment_types = unit_type_manager.get_regiment_types(); std::remove_const_t activated_regiment_types; - assert(unit_type_manager.regiment_types_are_locked()); + assert_is_locked(regiment_types); + auto const& ship_types = unit_type_manager.get_ship_types(); std::remove_const_t activated_ship_types; - assert(unit_type_manager.ship_types_are_locked()); + assert_is_locked(ship_types); Technology::building_set_t activated_buildings; ConditionalWeightFactorMul ai_chance { COUNTRY, COUNTRY, NO_SCOPE }; @@ -202,17 +205,13 @@ bool TechnologyManager::load_technologies_file( "activate_unit", ZERO_OR_MORE,NodeTools::expect_identifier( [ &activated_regiment_types, &activated_ship_types, - &unit_type_manager + ®iment_types, &ship_types ](std::string_view identifier) -> bool { - if (RegimentType const* const regiment_type_ptr = unit_type_manager.get_regiment_type_by_identifier(identifier); - regiment_type_ptr != nullptr - ) { - return (activated_regiment_types.emplace(regiment_type_ptr)).second; + if (const auto regiment_it = find(regiment_types, identifier); regiment_it != regiment_types.end()) { + return (activated_regiment_types.emplace(&*regiment_it)).second; } - if (ShipType const* const ship_type_ptr = unit_type_manager.get_ship_type_by_identifier(identifier); - ship_type_ptr != nullptr - ) { - return (activated_ship_types.emplace(ship_type_ptr)).second; + if (const auto ship_it = find(ship_types, identifier); ship_it != ship_types.end()) { + return (activated_ship_types.emplace(&*ship_it)).second; } spdlog::error_s("Invalid regiment type or ship type identifier: {}", identifier); return false; diff --git a/src/openvic-simulation/scripts/ConditionManager.cpp b/src/openvic-simulation/scripts/ConditionManager.cpp index cced15985..1424d8434 100644 --- a/src/openvic-simulation/scripts/ConditionManager.cpp +++ b/src/openvic-simulation/scripts/ConditionManager.cpp @@ -5,6 +5,7 @@ #include "openvic-simulation/core/template/RangeConcepts.hpp" #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/DefinitionManager.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -343,7 +344,9 @@ bool ConditionManager::setup_conditions(DefinitionManager const& definition_mana /* Scopes from other registries */ import_identifiers( - definition_manager.get_country_definition_manager().get_country_definition_identifiers(), + get_identifiers( + definition_manager.get_country_definition_manager().get_country_definitions() + ), GROUP, COUNTRY, COUNTRY, @@ -466,6 +469,19 @@ NodeTools::callback_t ConditionManager::expect_parse_identifie } \ }) \ } + #define EXPECT_CALL_OWNINGRESITRY(type, registry, ...) \ + if (share_identifier_type(identifier_type, type)) { \ + const auto it = find(registry, identifier); \ + if (it != registry.end()) { \ + return callback(&*it); \ + } __VA_OPT__(else { \ + /* TODO: the set is just a placeholder for actual logic */ \ + static const case_insensitive_string_set_t chances { __VA_ARGS__ }; \ + if (chances.contains(identifier)) { \ + return true; \ + } \ + }) \ + } //TODO: placeholder for not implemented stuff #define EXPECT_CALL_PLACEHOLDER(type) \ @@ -475,8 +491,9 @@ NodeTools::callback_t ConditionManager::expect_parse_identifie EXPECT_CALL_PLACEHOLDER(GLOBAL_FLAG); EXPECT_CALL_PLACEHOLDER(COUNTRY_FLAG); EXPECT_CALL_PLACEHOLDER(PROVINCE_FLAG); - EXPECT_CALL_IDENTIFIERGRESITRY( - COUNTRY_TAG, country_definition, definition_manager.get_country_definition_manager(), "THIS", "FROM", "OWNER" + EXPECT_CALL_OWNINGRESITRY( + COUNTRY_TAG, definition_manager.get_country_definition_manager().get_country_definitions(), + "THIS", "FROM", "OWNER" ); EXPECT_CALL_IDENTIFIERGRESITRY(PROVINCE_ID, province_definition, definition_manager.get_map_definition(), "THIS", "FROM"); EXPECT_CALL_IDENTIFIERGRESITRY(REGION, region, definition_manager.get_map_definition()); @@ -499,14 +516,16 @@ NodeTools::callback_t ConditionManager::expect_parse_identifie EXPECT_CALL_IDENTIFIERGRESITRY(COUNTRY_EVENT_MODIFIER | PROVINCE_EVENT_MODIFIER, event_modifier, definition_manager.get_modifier_manager()); EXPECT_CALL_IDENTIFIERGRESITRY(COUNTRY_EVENT_MODIFIER, triggered_modifier, definition_manager.get_modifier_manager()); EXPECT_CALL_IDENTIFIERGRESITRY(NATIONAL_VALUE, national_value, definition_manager.get_politics_manager().get_national_value_manager()); - EXPECT_CALL_IDENTIFIERGRESITRY( - CULTURE_UNION, country_definition, definition_manager.get_country_definition_manager(), "THIS", "FROM", "THIS_UNION" + EXPECT_CALL_OWNINGRESITRY( + CULTURE_UNION, definition_manager.get_country_definition_manager().get_country_definitions(), + "THIS", "FROM", "THIS_UNION" ); EXPECT_CALL_IDENTIFIERGRESITRY(CONTINENT, continent, definition_manager.get_map_definition()); EXPECT_CALL_IDENTIFIERGRESITRY(CRIME, crime_modifier, definition_manager.get_crime_manager()); EXPECT_CALL_IDENTIFIERGRESITRY(TERRAIN, terrain_type, definition_manager.get_map_definition().get_terrain_type_manager()); #undef EXPECT_CALL_IDENTIFIERGRESITRY + #undef EXPECT_CALL_OWNINGRESITRY #undef EXPECT_CALL_PLACEHOLDER return false; diff --git a/src/openvic-simulation/types/registries/OwningRegistry.hpp b/src/openvic-simulation/types/registries/OwningRegistry.hpp new file mode 100644 index 000000000..2d274fddf --- /dev/null +++ b/src/openvic-simulation/types/registries/OwningRegistry.hpp @@ -0,0 +1,120 @@ +#pragma once + +#include +#include + +#include + +#include "openvic-simulation/core/Assert.hpp" +#include "openvic-simulation/core/memory/FixedVector.hpp" +#include "openvic-simulation/types/ConstructorTags.hpp" + +namespace OpenVic { + struct owning_registry_internal_tag {}; + + template< + typename ValueType, + typename SizeType, + typename Allocator = foonathan::memory::default_allocator + > + struct OwningRegistry { + private: + bool _is_locked { false }; + memory::FixedVector _values; + + constexpr void swap(OwningRegistry& other) noexcept { + std::swap(_is_locked, other._is_locked); + std::swap(_values, other._values); + } + + public: + constexpr OwningRegistry(OwningRegistry&& other) noexcept : _values(create_empty) { + swap(other); + } + + template + requires (sizeof...(Args) != 1 || (!std::is_same_v, OwningRegistry> && ...)) + constexpr OwningRegistry(Args&&... args) : _values(std::forward(args)...) {} + + [[nodiscard]] constexpr bool is_locked() const { return _is_locked; } + [[nodiscard]] constexpr bool& is_locked_internal(owning_registry_internal_tag) { return _is_locked; } + [[nodiscard]] constexpr decltype(_values)& values_internal(owning_registry_internal_tag) { return _values; } + constexpr void clear_and_reserve(const SizeType new_cap) noexcept { + assert(!_is_locked); + _is_locked = false; + _values = std::move( + decltype(_values) { + create_empty, + new_cap + } + ); + } + + // Member types based on std::vector + using value_type = typename decltype(_values)::value_type; + using size_type = SizeType; + using difference_type = typename decltype(_values)::difference_type; + using reference = typename decltype(_values)::reference; + using const_reference = typename decltype(_values)::const_reference; + using iterator = typename decltype(_values)::iterator; + using const_iterator = typename decltype(_values)::const_iterator; + using reverse_iterator = typename decltype(_values)::reverse_iterator; + using const_reverse_iterator = typename decltype(_values)::const_reverse_iterator; + + // Element access based on std::vector + [[nodiscard]] constexpr reference operator[](const size_type pos) { + OV_HARDEN_ASSERT_ACCESS(pos, "operator[]"); + return _values[pos]; + } + [[nodiscard]] constexpr const_reference operator[](const size_type pos) const { + OV_HARDEN_ASSERT_ACCESS(pos, "operator[]"); + return _values[pos]; + } + + [[nodiscard]] constexpr reference front() { + OV_HARDEN_ASSERT_NONEMPTY("front"); + return _values[0]; + } + [[nodiscard]] constexpr const_reference front() const { + OV_HARDEN_ASSERT_NONEMPTY("front"); + return _values[0]; + } + + [[nodiscard]] constexpr reference back() { + OV_HARDEN_ASSERT_NONEMPTY("back"); + return _values[_values.size()-1]; + } + [[nodiscard]] constexpr const_reference back() const { + OV_HARDEN_ASSERT_NONEMPTY("back"); + return _values[_values.size()-1]; + } + + [[nodiscard]] constexpr value_type* data() noexcept { return _values.data(); } + [[nodiscard]] constexpr value_type const* data() const noexcept { return _values.data(); } + + // Iterators based on std::vector + [[nodiscard]] constexpr iterator begin() noexcept { return _values.begin(); } + [[nodiscard]] constexpr const_iterator begin() const noexcept { return _values.begin(); } + [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return _values.cbegin(); } + + [[nodiscard]] constexpr iterator end() noexcept { return _values.end(); } + [[nodiscard]] constexpr const_iterator end() const noexcept { return _values.end(); } + [[nodiscard]] constexpr const_iterator cend() const noexcept { return _values.cend(); } + + [[nodiscard]] constexpr reverse_iterator rbegin() noexcept { return _values.rbegin(); } + [[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { return _values.rbegin(); } + [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return _values.crbegin(); } + + [[nodiscard]] constexpr reverse_iterator rend() noexcept { return _values.rend(); } + [[nodiscard]] constexpr const_reverse_iterator rend() const noexcept { return _values.rend(); } + [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return _values.crend(); } + + // Capacity based on std::vector + [[nodiscard]] constexpr bool empty() const noexcept { return _values.empty(); } + [[nodiscard]] constexpr size_type size() const noexcept { return _values.size(); } + [[nodiscard]] constexpr size_type max_size() const noexcept { return _values.max_size(); } + [[nodiscard]] constexpr size_type capacity() const noexcept { return _values.capacity(); } + + // Modifiers omitted on purpose + }; +} \ No newline at end of file diff --git a/src/openvic-simulation/types/registries/OwningRegistry_Modify.hpp b/src/openvic-simulation/types/registries/OwningRegistry_Modify.hpp new file mode 100644 index 000000000..f5f683c42 --- /dev/null +++ b/src/openvic-simulation/types/registries/OwningRegistry_Modify.hpp @@ -0,0 +1,166 @@ +#pragma once + +#include + +#include "OwningRegistry.hpp" +#include "OwningRegistry_Search.hpp" + +#include "openvic-simulation/core/template/FunctionalConcepts.hpp" +#include "openvic-simulation/core/Typedefs.hpp" +#include "openvic-simulation/utility/Logger.hpp" + +namespace OpenVic { + inline bool duplicate_fail_cb(std::string_view registry_name, std::string_view duplicate_identifier) { + spdlog::error_s( + "Failure adding item to the {} registry - an item with the identifier \"{}\" already exists!", + registry_name, duplicate_identifier + ); + return false; + } + inline bool duplicate_warning_cb(std::string_view registry_name, std::string_view duplicate_identifier) { + spdlog::warn_s( + "Warning adding item to the {} registry - an item with the identifier \"{}\" already exists!", + registry_name, duplicate_identifier + ); + return true; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline void lock_registry( + OwningRegistry& registry, + const bool should_log = false + ) { + if (registry.is_locked()) { + spdlog::error_s("Failed to lock {} registry - already locked!", OpenVic::type_name()); + } else { + registry.is_locked_internal(owning_registry_internal_tag{}) = true; + if (should_log) { + SPDLOG_INFO("Locked {} registry after registering {} items", OpenVic::type_name(), registry.size()); + } + } + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr bool validate_emplacement(OwningRegistry& registry) { + assert(!registry.is_locked()); + if (registry.is_locked()) { + spdlog::error_s("Cannot emplace_item to the {} registry - locked!", OpenVic::type_name()); + return false; + } + + assert(registry.size() < registry.capacity()); + if (registry.size() >= registry.capacity()) { + spdlog::error_s("Cannot emplace_item to the {} registry - no capacity!", OpenVic::type_name()); + return false; + } + + return true; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator, + typename... Args + > + inline constexpr bool emplace_item( + OwningRegistry& registry, + Args&&... args + ) { + if (!validate_emplacement(registry)) { + return false; + } + + registry.values_internal(owning_registry_internal_tag{}).emplace_back(std::forward(args)...); + return true; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator, + typename... Args + > + inline constexpr bool try_emplace_item( + OwningRegistry& registry, + const std::string_view identifier, + Callback auto duplicate_callback, + Args&&... args + ) { + if (has_identifier(registry, identifier)) { + return duplicate_callback(OpenVic::type_name(), identifier); + } + + return emplace_item(registry, std::forward(args)...); + } + + template< + typename ValueType, + typename SizeType, + typename Allocator, + typename... Args + > + inline constexpr bool try_emplace_item( + OwningRegistry& registry, + const std::string_view identifier, + Args&&... args + ) { + return try_emplace_item(registry, identifier, duplicate_fail_cb, std::forward(args)...); + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr bool emplace_via_move( + OwningRegistry& registry, + ValueType&& item + ) { + if (!validate_emplacement(registry)) { + return false; + } + + registry.values_internal(owning_registry_internal_tag{}).emplace_back(std::move(item)); + return true; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr bool try_emplace_via_move( + OwningRegistry& registry, + const std::string_view identifier, + Callback auto duplicate_callback, + ValueType&& item + ) { + if (has_identifier(registry, identifier)) { + return duplicate_callback(OpenVic::type_name(), identifier); + } + + return emplace_via_move(registry, std::move(item)); + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr bool try_emplace_via_move( + OwningRegistry& registry, + const std::string_view identifier, + ValueType&& item + ) { + return try_emplace_via_move(registry, identifier, duplicate_fail_cb, std::move(item)); + } +} \ No newline at end of file diff --git a/src/openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp b/src/openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp new file mode 100644 index 000000000..dc94a6160 --- /dev/null +++ b/src/openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp @@ -0,0 +1,258 @@ +#pragma once + +#include + +#include "OwningRegistry.hpp" +#include "OwningRegistry_Search.hpp" + +#include "openvic-simulation/core/template/FunctionalConcepts.hpp" +#include "openvic-simulation/core/Typedefs.hpp" +#include "openvic-simulation/dataloader/IdentifierPolicy.hpp" +#include "openvic-simulation/dataloader/NodeTools.hpp" +#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp" +#include "openvic-simulation/utility/Logger.hpp" + +namespace OpenVic { + inline constexpr NodeTools::KeyValueCallback auto key_value_invalid_callback(std::string_view name) { + return [name](std::string_view key, ovdl::v2script::ast::Node const*) -> bool { + spdlog::error_s("Invalid {}: {}", name, key); + return false; + }; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr Callback auto expect_index_by_identifier( + OwningRegistry const& registry, + Callback auto callback, + IdentifierValidation validation + ) { + assert_is_locked(registry); + return [®istry, callback, validation](std::string_view identifier) -> bool { + if (identifier.empty()) { + if (validation.allow_empty) { + return true; + } else { + spdlog::log_s( + validation.warn_on_invalid ? spdlog::level::warn : spdlog::level::err, + "Invalid {} identifier: empty!", OpenVic::type_name() + ); + return validation.warn_on_invalid; + } + } + const auto it = find(registry, identifier); + if (it == registry.end()) { + spdlog::log_s( + validation.warn_on_invalid ? spdlog::level::warn : spdlog::level::err, + "Invalid {} identifier: {}", OpenVic::type_name(), identifier + ); + return validation.warn_on_invalid; + } + + return callback(SizeType(std::distance(registry.begin(), it))); + }; + } + template< + IdentifierSyntax Policy = IdentifierSyntax::Either, + typename ValueType, + typename SizeType, + typename Allocator + > + inline NodeTools::node_callback_t expect_index( + OwningRegistry const& registry, + Callback auto callback, + IdentifierValidation validation = {} + ) { + if constexpr (Policy == IdentifierSyntax::Either) { + return NodeTools::expect_identifier_or_string(expect_index_by_identifier(registry, callback, validation)); + } + else if constexpr (Policy == IdentifierSyntax::Identifier) { + return NodeTools::expect_identifier(expect_index_by_identifier(registry, callback, validation)); + } + else if constexpr (Policy == IdentifierSyntax::String) { + return NodeTools::expect_string(expect_index_by_identifier(registry, callback, validation)); + } + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr Callback auto expect_mutable_item_by_identifier( + OwningRegistry& registry, + Callback auto callback, + IdentifierValidation validation + ) { + assert_is_locked(registry); + return [®istry, callback, validation](std::string_view identifier) -> bool { + if (identifier.empty()) { + if (validation.allow_empty) { + return true; + } else { + spdlog::log_s( + validation.warn_on_invalid ? spdlog::level::warn : spdlog::level::err, + "Invalid {} identifier: empty!", OpenVic::type_name() + ); + return validation.warn_on_invalid; + } + } + const auto it = find(registry, identifier); + if (it == registry.end()) { + spdlog::log_s( + validation.warn_on_invalid ? spdlog::level::warn : spdlog::level::err, + "Invalid {} identifier: {}", OpenVic::type_name(), identifier + ); + return validation.warn_on_invalid; + } + + return callback(*it); + }; + } + template< + IdentifierSyntax Policy = IdentifierSyntax::Either, + typename ValueType, + typename SizeType, + typename Allocator + > + inline NodeTools::node_callback_t expect_mutable_item( + OwningRegistry& registry, + Callback auto callback, + IdentifierValidation validation = {} + ) { + if constexpr (Policy == IdentifierSyntax::Either) { + return NodeTools::expect_identifier_or_string(expect_mutable_item_by_identifier(registry, callback, validation)); + } + else if constexpr (Policy == IdentifierSyntax::Identifier) { + return NodeTools::expect_identifier(expect_mutable_item_by_identifier(registry, callback, validation)); + } + else if constexpr (Policy == IdentifierSyntax::String) { + return NodeTools::expect_string(expect_mutable_item_by_identifier(registry, callback, validation)); + } + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr Callback auto expect_item_by_identifier( + OwningRegistry const& registry, + Callback auto callback, + IdentifierValidation validation + ) { + assert_is_locked(registry); + return [®istry, callback, validation](std::string_view identifier) -> bool { + if (identifier.empty()) { + if (validation.allow_empty) { + return true; + } else { + spdlog::log_s( + validation.warn_on_invalid ? spdlog::level::warn : spdlog::level::err, + "Invalid {} identifier: empty!", OpenVic::type_name() + ); + return validation.warn_on_invalid; + } + } + const auto it = find(registry, identifier); + if (it == registry.end()) { + spdlog::log_s( + validation.warn_on_invalid ? spdlog::level::warn : spdlog::level::err, + "Invalid {} identifier: {}", OpenVic::type_name(), identifier + ); + return validation.warn_on_invalid; + } + + return callback(*it); + }; + } + template< + IdentifierSyntax Policy = IdentifierSyntax::Either, + typename ValueType, + typename SizeType, + typename Allocator + > + inline NodeTools::node_callback_t expect_item( + OwningRegistry const& registry, + Callback auto callback, + IdentifierValidation validation = {} + ) { + if constexpr (Policy == IdentifierSyntax::Either) { + return NodeTools::expect_identifier_or_string(expect_item_by_identifier(registry, callback, validation)); + } + else if constexpr (Policy == IdentifierSyntax::Identifier) { + return NodeTools::expect_identifier(expect_item_by_identifier(registry, callback, validation)); + } + else if constexpr (Policy == IdentifierSyntax::String) { + return NodeTools::expect_string(expect_item_by_identifier(registry, callback, validation)); + } + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + constexpr NodeTools::NodeCallback auto expect_item_dictionary( + OwningRegistry const& registry, + Callback auto callback + ) { + assert_is_locked(registry); + return NodeTools::expect_list_and_length( + NodeTools::default_length_callback, + NodeTools::expect_assign( + [®istry, callback]( + std::string_view identifier, + ovdl::v2script::ast::Node const* value + ) -> bool { + const auto it = find(registry, identifier); + if (it == registry.end()) { + return key_value_invalid_callback(OpenVic::type_name())(identifier, value); + } + + return callback( + SizeType(std::distance(registry.begin(), it)), + value + ); + } + ) + ); + } + + template< + typename ValueType, + typename SizeType, + typename Allocator, + FunctorConvertible FixedPointFunctor = std::identity + > + inline constexpr NodeTools::NodeCallback auto expect_item_decimal_map( + OwningRegistry const& registry, + Callback&&> auto callback, + FixedPointFunctor fixed_point_functor = {} + ) { + assert_is_locked(registry); + return [®istry, callback, fixed_point_functor](ovdl::v2script::ast::Node const* node) -> bool { + fixed_point_map_t map; + + bool ret = expect_item_dictionary( + registry, + [&map, fixed_point_functor](const SizeType index, ovdl::v2script::ast::Node const* value) -> bool { + return NodeTools::expect_fixed_point( + [&map, fixed_point_functor, index](fixed_point_t val) -> bool { + map.emplace(index, fixed_point_functor(val)); + return true; + } + )(value); + } + )(node); + + ret &= callback(std::move(map)); + + return ret; + }; + } +} \ No newline at end of file diff --git a/src/openvic-simulation/types/registries/OwningRegistry_Search.hpp b/src/openvic-simulation/types/registries/OwningRegistry_Search.hpp new file mode 100644 index 000000000..d331e606f --- /dev/null +++ b/src/openvic-simulation/types/registries/OwningRegistry_Search.hpp @@ -0,0 +1,126 @@ +#pragma once + +#include +#include +#include +#include + +#include "OwningRegistry.hpp" + +#include "openvic-simulation/core/stl/containers/TypedSpan.hpp" +#include "openvic-simulation/core/template/Concepts.hpp" +#include "openvic-simulation/utility/Logger.hpp" + +namespace OpenVic { + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr void assert_is_locked( + OwningRegistry const& registry + ) { + assert(registry.is_locked()); + if (!registry.is_locked()) { + spdlog::error_s("registry {} is used but not yet locked!", OpenVic::type_name()); + } + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires is_strongly_typed + [[nodiscard]] inline constexpr TypedSpan get_values(OwningRegistry& registry) { + assert_is_locked(registry); + return { registry }; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires is_strongly_typed + [[nodiscard]] inline constexpr TypedSpan get_values(OwningRegistry const& registry) { + assert_is_locked(registry); + return { registry }; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires (!is_strongly_typed) + [[nodiscard]] inline constexpr std::span get_values(OwningRegistry& registry) { + assert_is_locked(registry); + return { registry.data(), registry.size() }; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires (!is_strongly_typed) + [[nodiscard]] inline constexpr std::span get_values(OwningRegistry const& registry) { + assert_is_locked(registry); + return { registry.data(), registry.size() }; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires has_get_identifier + [[nodiscard]] inline constexpr auto get_identifiers( + OwningRegistry const& registry + ) { + assert_is_locked(registry); + return registry | std::views::transform([](auto const& x) -> std::string_view { + return x.get_identifier(); + }); + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires has_get_identifier + [[nodiscard]] inline constexpr bool has_identifier( + OwningRegistry const& registry, + std::string_view identifier + ) { + return std::ranges::any_of(registry.begin(), registry.end(), [&](ValueType const& value) { + return value.get_identifier() == identifier; + }); + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires has_get_identifier + [[nodiscard]] inline constexpr OwningRegistry::iterator find( + OwningRegistry& registry, + std::string_view identifier + ) { + assert_is_locked(registry); + return std::find_if(registry.begin(), registry.end(), [&](ValueType const& value) { + return value.get_identifier() == identifier; + }); + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires has_get_identifier + [[nodiscard]] inline constexpr OwningRegistry::const_iterator find( + OwningRegistry const& registry, + std::string_view identifier + ) { + assert_is_locked(registry); + return std::find_if(registry.begin(), registry.end(), [&](ValueType const& value) { + return value.get_identifier() == identifier; + }); + } +} \ No newline at end of file