diff options
author | hop311 <hop3114@gmail.com> | 2024-01-22 21:02:58 +0100 |
---|---|---|
committer | hop311 <hop3114@gmail.com> | 2024-01-23 23:14:53 +0100 |
commit | 268a6948c0400905dfc335427395519689f067f5 (patch) | |
tree | b30e9b5774130552fe97e27deaf0370d83920c43 /src | |
parent | d4e597da089a81f719a9c33b46111d1c2c590124 (diff) |
Added reserve_more, expect_dictionary_key[s|_map]_reserve_length[_and_default]reserve_more
Diffstat (limited to 'src')
41 files changed, 517 insertions, 346 deletions
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index cce766f..8d475a2 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -287,6 +287,9 @@ bool Dataloader::_load_interface_files(UIManager& ui_manager) const { static const std::vector<std::string_view> gui_files { "province_interface.gui", "topbar.gui" }; + + ui_manager.reserve_more_scenes(gui_files.size()); + for (std::string_view const& gui_file : gui_files) { if (!ui_manager.load_gui_file( gui_file, parse_defines(lookup_file(append_string_views(interface_directory, gui_file))).get_file_node() @@ -307,8 +310,10 @@ bool Dataloader::_load_pop_types(GameManager& game_manager) { IdeologyManager const& ideology_manager = game_manager.get_politics_manager().get_ideology_manager(); static constexpr std::string_view pop_type_directory = "poptypes"; + const path_vector_t pop_type_files = lookup_files_in_dir(pop_type_directory, ".txt"); - pop_manager.reserve_pop_types(pop_type_files.size()); + + pop_manager.reserve_all_pop_types(pop_type_files.size()); bool ret = apply_to_files( pop_type_files, @@ -318,8 +323,8 @@ bool Dataloader::_load_pop_types(GameManager& game_manager) { ); } ); - pop_manager.lock_stratas(); - pop_manager.lock_pop_types(); + + pop_manager.lock_all_pop_types(); if (pop_manager.get_slave_sprite() <= 0) { Logger::error("No slave pop type sprite found!"); @@ -343,8 +348,12 @@ bool Dataloader::_load_units(GameManager& game_manager) const { UnitManager& unit_manager = game_manager.get_military_manager().get_unit_manager(); + const path_vector_t unit_files = lookup_files_in_dir(units_directory, ".txt"); + + unit_manager.reserve_more_units(unit_files.size()); + bool ret = apply_to_files( - lookup_files_in_dir(units_directory, ".txt"), + unit_files, [&game_manager, &unit_manager](fs::path const& file) -> bool { return unit_manager.load_unit_file( game_manager.get_economy_manager().get_good_manager(), parse_defines(file).get_file_node() @@ -481,112 +490,152 @@ bool Dataloader::_load_decisions(GameManager& game_manager) { bool Dataloader::_load_history(GameManager& game_manager, bool unused_history_file_warnings) const { - /* Country History */ - static constexpr std::string_view country_history_directory = "history/countries"; - bool ret = apply_to_files( - lookup_basic_indentifier_prefixed_files_in_dir(country_history_directory, ".txt"), - [this, &game_manager, unused_history_file_warnings](fs::path const& file) -> bool { - const std::string filename = file.stem().string(); - const std::string_view country_id = extract_basic_identifier_prefix(filename); - - Country const* country = game_manager.get_country_manager().get_country_by_identifier(country_id); - if (country == nullptr) { - if (unused_history_file_warnings) { - Logger::warning("Found history file for non-existent country: ", country_id); + bool ret = true; + + { + /* Country History */ + CountryHistoryManager& country_history_manager = game_manager.get_history_manager().get_country_manager(); + + static constexpr std::string_view country_history_directory = "history/countries"; + const path_vector_t country_history_files = + lookup_basic_indentifier_prefixed_files_in_dir(country_history_directory, ".txt"); + + country_history_manager.reserve_more_country_histories(country_history_files.size()); + + ret &= apply_to_files( + country_history_files, + [this, &game_manager, &country_history_manager, unused_history_file_warnings](fs::path const& file) -> bool { + const std::string filename = file.stem().string(); + const std::string_view country_id = extract_basic_identifier_prefix(filename); + + Country const* country = game_manager.get_country_manager().get_country_by_identifier(country_id); + if (country == nullptr) { + if (unused_history_file_warnings) { + Logger::warning("Found history file for non-existent country: ", country_id); + } + return true; } - return true; + + return country_history_manager.load_country_history_file( + game_manager, *this, *country, parse_defines(file).get_file_node() + ); } + ); - return game_manager.get_history_manager().get_country_manager().load_country_history_file( - game_manager, *this, *country, parse_defines(file).get_file_node() - ); - } - ); - game_manager.get_history_manager().get_country_manager().lock_country_histories(); + country_history_manager.lock_country_histories(); + } { DeploymentManager& deployment_manager = game_manager.get_military_manager().get_deployment_manager(); + deployment_manager.lock_deployments(); + if (deployment_manager.get_missing_oob_file_count() > 0) { Logger::warning(deployment_manager.get_missing_oob_file_count(), " missing OOB files!"); } } - /* Province History */ - static constexpr std::string_view province_history_directory = "history/provinces"; - ret &= apply_to_files( - lookup_basic_indentifier_prefixed_files_in_dir_recursive(province_history_directory, ".txt"), - [this, &game_manager, unused_history_file_warnings](fs::path const& file) -> bool { - const std::string filename = file.stem().string(); - const std::string_view province_id = extract_basic_identifier_prefix(filename); - - Province const* province = game_manager.get_map().get_province_by_identifier(province_id); - if (province == nullptr) { - if (unused_history_file_warnings) { - Logger::warning("Found history file for non-existent province: ", province_id); + { + /* Province History */ + ProvinceHistoryManager& province_history_manager = game_manager.get_history_manager().get_province_manager(); + Map const& map = game_manager.get_map(); + + static constexpr std::string_view province_history_directory = "history/provinces"; + const path_vector_t province_history_files = + lookup_basic_indentifier_prefixed_files_in_dir_recursive(province_history_directory, ".txt"); + + province_history_manager.reserve_more_province_histories(province_history_files.size()); + + ret &= apply_to_files( + province_history_files, + [this, &game_manager, &province_history_manager, &map, unused_history_file_warnings](fs::path const& file) -> bool { + const std::string filename = file.stem().string(); + const std::string_view province_id = extract_basic_identifier_prefix(filename); + + Province const* province = map.get_province_by_identifier(province_id); + if (province == nullptr) { + if (unused_history_file_warnings) { + Logger::warning("Found history file for non-existent province: ", province_id); + } + return true; } - return true; + + return province_history_manager.load_province_history_file( + game_manager, *province, parse_defines(file).get_file_node() + ); } + ); - return game_manager.get_history_manager().get_province_manager().load_province_history_file( - game_manager, *province, parse_defines(file).get_file_node() - ); - } - ); + /* Pop History */ + static constexpr std::string_view pop_history_directory = "history/pops/"; + + const string_set_t pop_history_dirs = lookup_dirs_in_dir(pop_history_directory); + const Date last_bookmark_date = game_manager.get_history_manager().get_bookmark_manager().get_last_bookmark_date(); + + for (std::string const& dir : pop_history_dirs) { + bool successful = false; + const Date date = Date::from_string(dir, &successful); + + if (successful && date <= last_bookmark_date) { + bool non_integer_size = false; + + ret &= apply_to_files( + lookup_files_in_dir(StringUtils::append_string_views(pop_history_directory, dir), ".txt"), + [this, &game_manager, &province_history_manager, date, &non_integer_size](fs::path const& file) -> bool { + return province_history_manager.load_pop_history_file( + game_manager, date, parse_defines(file).get_file_node(), &non_integer_size + ); + } + ); - /* Pop History */ - static constexpr std::string_view pop_history_directory = "history/pops/"; - const string_set_t pop_history_dirs = lookup_dirs_in_dir(pop_history_directory); - const Date last_bookmark_date = game_manager.get_history_manager().get_bookmark_manager().get_last_bookmark_date(); - for (std::string const& dir : pop_history_dirs) { - bool successful = false; - const Date date = Date::from_string(dir, &successful); - if (successful && date <= last_bookmark_date) { - bool non_integer_size = false; - ret &= apply_to_files( - lookup_files_in_dir(StringUtils::append_string_views(pop_history_directory, dir), ".txt"), - [this, &game_manager, date, &non_integer_size](fs::path const& file) -> bool { - return game_manager.get_history_manager().get_province_manager().load_pop_history_file( - game_manager, date, parse_defines(file).get_file_node(), &non_integer_size - ); + if (non_integer_size) { + Logger::warning("Non-integer pop sizes in pop history files for ", date); } - ); - if (non_integer_size) { - Logger::warning("Non-integer pop sizes in pop history files for ", date); } } + + province_history_manager.lock_province_histories(map, false); } - game_manager.get_history_manager().get_province_manager().lock_province_histories(game_manager.get_map(), false); + { + /* Diplomacy History */ + DiplomaticHistoryManager& diplomatic_history_manager = game_manager.get_history_manager().get_diplomacy_manager(); - /* Diplomacy History */ - static constexpr std::string_view diplomacy_history_directory = "history/diplomacy"; - ret &= apply_to_files( - lookup_files_in_dir(diplomacy_history_directory, ".txt"), - [this, &game_manager](fs::path const& file) -> bool { - return game_manager.get_history_manager().get_diplomacy_manager().load_diplomacy_history_file( - game_manager.get_country_manager(), parse_defines(file).get_file_node() - ); - } - ); + static constexpr std::string_view diplomacy_history_directory = "history/diplomacy"; - /* War History */ - static constexpr std::string_view war_history_directory = "history/wars"; - ret &= apply_to_files( - lookup_files_in_dir(war_history_directory, ".txt"), - [this, &game_manager](fs::path const& file) -> bool { - return game_manager.get_history_manager().get_diplomacy_manager().load_war_history_file( - game_manager, parse_defines(file).get_file_node() - ); - } - ); - game_manager.get_history_manager().get_diplomacy_manager().lock_diplomatic_history(); + ret &= apply_to_files( + lookup_files_in_dir(diplomacy_history_directory, ".txt"), + [this, &game_manager, &diplomatic_history_manager](fs::path const& file) -> bool { + return diplomatic_history_manager.load_diplomacy_history_file( + game_manager.get_country_manager(), parse_defines(file).get_file_node() + ); + } + ); + + /* War History */ + static constexpr std::string_view war_history_directory = "history/wars"; + const path_vector_t war_history_files = lookup_files_in_dir(war_history_directory, ".txt"); + + diplomatic_history_manager.reserve_more_wars(war_history_files.size()); + + ret &= apply_to_files( + war_history_files, + [this, &game_manager, &diplomatic_history_manager](fs::path const& file) -> bool { + return diplomatic_history_manager.load_war_history_file( + game_manager, parse_defines(file).get_file_node() + ); + } + ); + + diplomatic_history_manager.lock_diplomatic_history(); + } return ret; } bool Dataloader::_load_events(GameManager& game_manager) { static constexpr std::string_view events_directory = "events"; + const bool ret = apply_to_files( lookup_files_in_dir(events_directory, ".txt"), [this, &game_manager](fs::path const& file) -> bool { @@ -595,6 +644,7 @@ bool Dataloader::_load_events(GameManager& game_manager) { ); } ); + game_manager.get_event_manager().lock_events(); return ret; } @@ -959,9 +1009,13 @@ bool Dataloader::load_defines(GameManager& game_manager) { return ret; } -#define PARSE_SCRIPTS(name, mgr) \ - if (!mgr.parse_scripts(game_manager)) { Logger::error("Failed to parse ", name, " scripts!"); ret = false; } \ - else Logger::info("Successfully parsed ", name, " scripts!"); +#define PARSE_SCRIPTS(name, manager) \ + if (!manager.parse_scripts(game_manager)) { \ + Logger::error("Failed to parse ", name, " scripts!"); \ + ret = false; \ + } else { \ + Logger::info("Successfully parsed ", name, " scripts!"); \ + } bool Dataloader::parse_scripts(GameManager& game_manager) const { bool ret = true; diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp index 0845e6c..9137d6a 100644 --- a/src/openvic-simulation/dataloader/NodeTools.hpp +++ b/src/openvic-simulation/dataloader/NodeTools.hpp @@ -32,6 +32,15 @@ namespace OpenVic { using name_list_t = std::vector<std::string>; std::ostream& operator<<(std::ostream& stream, name_list_t const& name_list); + template<typename T> + concept Reservable = requires(T& t, size_t size) { + { t.size() } -> std::same_as<size_t>; + t.reserve(size); + }; + constexpr void reserve_more(Reservable auto& t, size_t size) { + t.reserve(t.size() + size); + } + namespace NodeTools { template<typename Fn, typename Return = void, typename... Args> @@ -232,25 +241,43 @@ namespace OpenVic { ); } - template<typename T> - concept Reservable = requires(T& t) { - { t.size() } -> std::same_as<size_t>; - t.reserve(size_t {}); - }; - template<Reservable T> - LengthCallback auto reserve_length_callback(T& t) { - return [&t](size_t size) -> size_t { - t.reserve(size); + LengthCallback auto reserve_length_callback(Reservable auto& reservable) { + return [&reservable](size_t size) -> size_t { + reserve_more(reservable, size); return size; }; } - template<Reservable T> - NodeCallback auto expect_list_reserve_length(T& t, NodeCallback auto callback) { - return expect_list_and_length(reserve_length_callback(t), callback); + NodeCallback auto expect_list_reserve_length(Reservable auto& reservable, NodeCallback auto callback) { + return expect_list_and_length(reserve_length_callback(reservable), callback); } - template<Reservable T> - NodeCallback auto expect_dictionary_reserve_length(T& t, KeyValueCallback auto callback) { - return expect_list_reserve_length(t, expect_assign(callback)); + 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> + NodeCallback auto expect_dictionary_key_map_reserve_length_and_default( + Reservable auto& reservable, key_map_t 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> + NodeCallback auto expect_dictionary_key_map_reserve_length( + Reservable auto& reservable, key_map_t key_map, Args... args + ) { + return expect_dictionary_key_map_and_length(std::move(key_map), reserve_length_callback(reservable), args...); + } + template<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( + reserve_length_callback(reservable), default_callback, args... + ); + } + template<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...); } node_callback_t name_list_callback(callback_t<name_list_t&&> callback); diff --git a/src/openvic-simulation/economy/Good.cpp b/src/openvic-simulation/economy/Good.cpp index d674a68..961a82d 100644 --- a/src/openvic-simulation/economy/Good.cpp +++ b/src/openvic-simulation/economy/Good.cpp @@ -64,7 +64,7 @@ bool GoodManager::load_goods_file(ast::NodeCPtr root) { } )(root); lock_good_categories(); - goods.reserve(goods.size() + total_expected_goods); + reserve_more_goods(total_expected_goods); ret &= expect_good_category_dictionary([this](GoodCategory const& good_category, ast::NodeCPtr good_category_value) -> bool { return expect_dictionary([this, &good_category](std::string_view key, ast::NodeCPtr value) -> bool { colour_t colour = colour_t::null(); diff --git a/src/openvic-simulation/economy/ProductionType.cpp b/src/openvic-simulation/economy/ProductionType.cpp index 86f3c13..9c806e5 100644 --- a/src/openvic-simulation/economy/ProductionType.cpp +++ b/src/openvic-simulation/economy/ProductionType.cpp @@ -204,7 +204,7 @@ bool ProductionTypeManager::load_production_types_file( )(root); /* Pass #3: actually load production types */ - production_types.reserve(production_types.size() + expected_types); + reserve_more_production_types(expected_types); ret &= expect_dictionary( [this, &good_manager, &pop_manager, &template_target_map, &template_node_map]( std::string_view key, ast::NodeCPtr node) -> bool { diff --git a/src/openvic-simulation/history/Bookmark.cpp b/src/openvic-simulation/history/Bookmark.cpp index b758867..ee7b494 100644 --- a/src/openvic-simulation/history/Bookmark.cpp +++ b/src/openvic-simulation/history/Bookmark.cpp @@ -23,27 +23,30 @@ bool BookmarkManager::add_bookmark( } bool BookmarkManager::load_bookmark_file(ast::NodeCPtr root) { - const bool ret = expect_dictionary([this](std::string_view key, ast::NodeCPtr value) -> bool { - if (key != "bookmark") { - Logger::error("Invalid bookmark declaration ", key); - return false; + const bool ret = expect_dictionary_reserve_length( + bookmarks, + [this](std::string_view key, ast::NodeCPtr value) -> bool { + if (key != "bookmark") { + Logger::error("Invalid bookmark declaration ", key); + return false; + } + + std::string_view name, description; + Date date; + uint32_t initial_camera_x, initial_camera_y; + + bool ret = expect_dictionary_keys( + "name", ONE_EXACTLY, expect_string(assign_variable_callback(name)), + "desc", ONE_EXACTLY, expect_string(assign_variable_callback(description)), + "date", ONE_EXACTLY, expect_date(assign_variable_callback(date)), + "cameraX", ONE_EXACTLY, expect_uint(assign_variable_callback(initial_camera_x)), + "cameraY", ONE_EXACTLY, expect_uint(assign_variable_callback(initial_camera_y)) + )(value); + + ret &= add_bookmark(name, description, date, initial_camera_x, initial_camera_y); + return ret; } - - std::string_view name, description; - Date date; - uint32_t initial_camera_x, initial_camera_y; - - bool ret = expect_dictionary_keys( - "name", ONE_EXACTLY, expect_string(assign_variable_callback(name)), - "desc", ONE_EXACTLY, expect_string(assign_variable_callback(description)), - "date", ONE_EXACTLY, expect_date(assign_variable_callback(date)), - "cameraX", ONE_EXACTLY, expect_uint(assign_variable_callback(initial_camera_x)), - "cameraY", ONE_EXACTLY, expect_uint(assign_variable_callback(initial_camera_y)) - )(value); - - ret &= add_bookmark(name, description, date, initial_camera_x, initial_camera_y); - return ret; - })(root); + )(root); lock_bookmarks(); return ret; diff --git a/src/openvic-simulation/history/CountryHistory.cpp b/src/openvic-simulation/history/CountryHistory.cpp index 3b4dfd8..5ee5e38 100644 --- a/src/openvic-simulation/history/CountryHistory.cpp +++ b/src/openvic-simulation/history/CountryHistory.cpp @@ -180,6 +180,14 @@ bool CountryHistoryMap::_load_history_entry( )(root); } +void CountryHistoryManager::reserve_more_country_histories(size_t size) { + if (locked) { + Logger::error("Failed to reserve space for ", size, " countries in CountryHistoryManager - already locked!"); + } else { + reserve_more(country_histories, size); + } +} + void CountryHistoryManager::lock_country_histories() { Logger::info("Locked country history registry after registering ", country_histories.size(), " items"); locked = true; diff --git a/src/openvic-simulation/history/CountryHistory.hpp b/src/openvic-simulation/history/CountryHistory.hpp index 6d4392b..1c1b7f1 100644 --- a/src/openvic-simulation/history/CountryHistory.hpp +++ b/src/openvic-simulation/history/CountryHistory.hpp @@ -1,10 +1,8 @@ #pragma once -#include <map> #include <optional> #include "openvic-simulation/country/Country.hpp" -#include "openvic-simulation/history/Bookmark.hpp" #include "openvic-simulation/history/HistoryMap.hpp" #include "openvic-simulation/map/Province.hpp" #include "openvic-simulation/military/Deployment.hpp" @@ -17,7 +15,6 @@ #include "openvic-simulation/pop/Religion.hpp" #include "openvic-simulation/research/Invention.hpp" #include "openvic-simulation/research/Technology.hpp" -#include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/types/Date.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" @@ -88,6 +85,7 @@ namespace OpenVic { public: CountryHistoryManager() = default; + void reserve_more_country_histories(size_t size); void lock_country_histories(); bool is_locked() const; diff --git a/src/openvic-simulation/history/DiplomaticHistory.cpp b/src/openvic-simulation/history/DiplomaticHistory.cpp index 883a212..55d6d6b 100644 --- a/src/openvic-simulation/history/DiplomaticHistory.cpp +++ b/src/openvic-simulation/history/DiplomaticHistory.cpp @@ -47,6 +47,14 @@ SubjectHistory::SubjectHistory( const Period new_period ) : overlord { new_overlord }, subject { new_subject }, type { new_type }, period {new_period} {} +void DiplomaticHistoryManager::reserve_more_wars(size_t size) { + if (locked) { + Logger::error("Failed to reserve space for ", size, " wars in DiplomaticHistoryManager - already locked!"); + } else { + reserve_more(wars, size); + } +} + void DiplomaticHistoryManager::lock_diplomatic_history() { Logger::info("Locked diplomacy history registry after registering ", alliances.size() + subjects.size() + wars.size(), " items"); locked = true; @@ -184,7 +192,7 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file(CountryManager const& } bool DiplomaticHistoryManager::load_war_history_file(GameManager const& game_manager, ast::NodeCPtr root) { - std::string name = ""; + std::string_view name {}; std::vector<WarHistory::war_participant_t> attackers {}; std::vector<WarHistory::war_participant_t> defenders {}; std::vector<WarHistory::added_wargoal_t> wargoals {}; @@ -270,7 +278,7 @@ bool DiplomaticHistoryManager::load_war_history_file(GameManager const& game_man )(node); return ret; }, - "name", ZERO_OR_ONE, expect_string(assign_variable_callback_string(name)) + "name", ZERO_OR_ONE, expect_string(assign_variable_callback(name)) )(root); wars.push_back({ name, std::move(attackers), std::move(defenders), std::move(wargoals) }); diff --git a/src/openvic-simulation/history/DiplomaticHistory.hpp b/src/openvic-simulation/history/DiplomaticHistory.hpp index 07302ac..35ba6fb 100644 --- a/src/openvic-simulation/history/DiplomaticHistory.hpp +++ b/src/openvic-simulation/history/DiplomaticHistory.hpp @@ -1,8 +1,6 @@ #pragma once -#include <bitset> #include <vector> -#include <map> #include <optional> #include "openvic-simulation/country/Country.hpp" @@ -100,6 +98,7 @@ namespace OpenVic { public: DiplomaticHistoryManager() {} + void reserve_more_wars(size_t size); void lock_diplomatic_history(); bool is_locked() const; diff --git a/src/openvic-simulation/history/HistoryManager.hpp b/src/openvic-simulation/history/HistoryManager.hpp index 35aebbf..1e540cc 100644 --- a/src/openvic-simulation/history/HistoryManager.hpp +++ b/src/openvic-simulation/history/HistoryManager.hpp @@ -2,9 +2,8 @@ #include "openvic-simulation/history/Bookmark.hpp" #include "openvic-simulation/history/CountryHistory.hpp" -#include "openvic-simulation/history/ProvinceHistory.hpp" #include "openvic-simulation/history/DiplomaticHistory.hpp" -#include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/history/ProvinceHistory.hpp" namespace OpenVic { struct HistoryManager { diff --git a/src/openvic-simulation/history/HistoryMap.hpp b/src/openvic-simulation/history/HistoryMap.hpp index 64975bc..15f838d 100644 --- a/src/openvic-simulation/history/HistoryMap.hpp +++ b/src/openvic-simulation/history/HistoryMap.hpp @@ -1,6 +1,5 @@ #pragma once -#include <map> #include <memory> #include "openvic-simulation/dataloader/NodeTools.hpp" diff --git a/src/openvic-simulation/history/ProvinceHistory.cpp b/src/openvic-simulation/history/ProvinceHistory.cpp index fd174a3..b5b2210 100644 --- a/src/openvic-simulation/history/ProvinceHistory.cpp +++ b/src/openvic-simulation/history/ProvinceHistory.cpp @@ -112,6 +112,14 @@ bool ProvinceHistoryMap::_load_history_entry( )(root); } +void ProvinceHistoryManager::reserve_more_province_histories(size_t size) { + if (locked) { + Logger::error("Failed to reserve space for ", size, " provinces in ProvinceHistoryManager - already locked!"); + } else { + reserve_more(province_histories, size); + } +} + void ProvinceHistoryManager::lock_province_histories(Map const& map, bool detailed_errors) { std::vector<bool> province_checklist(map.get_province_count()); for (decltype(province_histories)::value_type const& entry : province_histories) { diff --git a/src/openvic-simulation/history/ProvinceHistory.hpp b/src/openvic-simulation/history/ProvinceHistory.hpp index 0bda35d..7611907 100644 --- a/src/openvic-simulation/history/ProvinceHistory.hpp +++ b/src/openvic-simulation/history/ProvinceHistory.hpp @@ -1,13 +1,10 @@ #pragma once -#include <bitset> -#include <map> #include <vector> #include "openvic-simulation/country/Country.hpp" #include "openvic-simulation/economy/BuildingType.hpp" #include "openvic-simulation/economy/Good.hpp" -#include "openvic-simulation/history/Bookmark.hpp" #include "openvic-simulation/history/HistoryMap.hpp" #include "openvic-simulation/map/Province.hpp" #include "openvic-simulation/map/TerrainType.hpp" @@ -63,7 +60,7 @@ namespace OpenVic { struct ProvinceHistoryManager { private: - ordered_map<Province const*, ProvinceHistoryMap> PROPERTY(province_histories); + ordered_map<Province const*, ProvinceHistoryMap> province_histories; bool locked = false; ProvinceHistoryMap* _get_or_make_province_history(Province const& province); @@ -71,6 +68,7 @@ namespace OpenVic { public: ProvinceHistoryManager() = default; + void reserve_more_province_histories(size_t size); void lock_province_histories(Map const& map, bool detailed_errors); bool is_locked() const; diff --git a/src/openvic-simulation/interface/GFX.cpp b/src/openvic-simulation/interface/GFX.cpp index d7b9042..0ec2954 100644 --- a/src/openvic-simulation/interface/GFX.cpp +++ b/src/openvic-simulation/interface/GFX.cpp @@ -7,8 +7,9 @@ using namespace OpenVic::NodeTools; Font::Font(std::string_view new_identifier, colour_argb_t new_colour, std::string_view new_fontname) : HasIdentifierAndAlphaColour { new_identifier, new_colour, false }, fontname { new_fontname } {} -node_callback_t Sprite::expect_sprite(callback_t<std::unique_ptr<Sprite>&&> callback) { - return expect_dictionary_keys( +node_callback_t Sprite::expect_sprites(length_callback_t length_callback, callback_t<std::unique_ptr<Sprite>&&> callback) { + return expect_dictionary_keys_and_length( + length_callback, "spriteType", ZERO_OR_MORE, _expect_instance<Sprite, TextureSprite>(callback), "progressbartype", ZERO_OR_MORE, _expect_instance<Sprite, ProgressBar>(callback), "PieChartType", ZERO_OR_MORE, _expect_instance<Sprite, PieChart>(callback), diff --git a/src/openvic-simulation/interface/GFX.hpp b/src/openvic-simulation/interface/GFX.hpp index 2bae4b3..efd2293 100644 --- a/src/openvic-simulation/interface/GFX.hpp +++ b/src/openvic-simulation/interface/GFX.hpp @@ -36,7 +36,9 @@ namespace OpenVic::GFX { OV_DETAIL_GET_BASE_TYPE(Sprite) OV_DETAIL_GET_TYPE - static NodeTools::node_callback_t expect_sprite(NodeTools::callback_t<std::unique_ptr<Sprite>&&> callback); + static NodeTools::node_callback_t expect_sprites( + NodeTools::length_callback_t length_callback, NodeTools::callback_t<std::unique_ptr<Sprite>&&> callback + ); }; class TextureSprite final : public Sprite { diff --git a/src/openvic-simulation/interface/UI.cpp b/src/openvic-simulation/interface/UI.cpp index 344fc15..b977406 100644 --- a/src/openvic-simulation/interface/UI.cpp +++ b/src/openvic-simulation/interface/UI.cpp @@ -39,7 +39,8 @@ bool UIManager::_load_font(ast::NodeCPtr node) { bool UIManager::load_gfx_file(ast::NodeCPtr root) { return expect_dictionary_keys( - "spriteTypes", ZERO_OR_ONE, Sprite::expect_sprite( + "spriteTypes", ZERO_OR_ONE, Sprite::expect_sprites( + NodeTools::reserve_length_callback(sprites), [this](std::unique_ptr<Sprite>&& sprite) -> bool { /* TODO - more checks on duplicates (the false here reduces them from * errors to warnings). The repeats in vanilla are identical (simple @@ -64,7 +65,8 @@ bool UIManager::load_gfx_file(ast::NodeCPtr root) { return sprites.add_item(std::move(sprite), duplicate_warning_callback); } ), - "bitmapfonts", ZERO_OR_ONE, expect_dictionary( + "bitmapfonts", ZERO_OR_ONE, expect_dictionary_reserve_length( + fonts, [this](std::string_view key, ast::NodeCPtr node) -> bool { if (key != "bitmapfont") { Logger::error("Invalid bitmapfonts key: ", key); diff --git a/src/openvic-simulation/map/Map.cpp b/src/openvic-simulation/map/Map.cpp index 1415e2c..9a97143 100644 --- a/src/openvic-simulation/map/Map.cpp +++ b/src/openvic-simulation/map/Map.cpp @@ -279,7 +279,7 @@ bool Map::set_water_province_list(std::vector<std::string_view> const& list) { return false; } bool ret = true; - water_provinces.reserve(water_provinces.size() + list.size()); + water_provinces.reserve_more(list.size()); for (std::string_view const& identifier : list) { ret &= set_water_province(identifier); } @@ -521,6 +521,7 @@ bool Map::load_province_definitions(std::vector<LineObject> const& lines) { Logger::error("No header or entries in province definition file!"); return false; } + { LineObject const& header = lines.front(); if (!_validate_province_definitions_header(header)) { @@ -529,11 +530,14 @@ bool Map::load_province_definitions(std::vector<LineObject> const& lines) { ); } } + if (lines.size() <= 1) { Logger::error("No entries in province definition file!"); return false; } - provinces.reserve(lines.size() - 1); + + reserve_more_provinces(lines.size() - 1); + bool ret = true; std::for_each(lines.begin() + 1, lines.end(), [this, &ret](LineObject const& line) -> void { const std::string_view identifier = line.get_value_for(0); @@ -546,7 +550,9 @@ bool Map::load_province_definitions(std::vector<LineObject> const& lines) { ret &= add_province(identifier, colour); } }); + lock_provinces(); + return ret; } @@ -557,7 +563,8 @@ bool Map::load_province_positions(BuildingTypeManager const& building_type_manag } bool Map::load_region_file(ast::NodeCPtr root) { - const bool ret = expect_dictionary_reserve_length(regions, + const bool ret = expect_dictionary_reserve_length( + regions, [this](std::string_view region_identifier, ast::NodeCPtr region_node) -> bool { Region::provinces_t provinces; bool ret = expect_list_reserve_length( @@ -567,7 +574,9 @@ bool Map::load_region_file(ast::NodeCPtr root) { return ret; } )(root); + lock_regions(); + for (Region const& region : regions.get_items()) { if (!region.meta) { for (Province const* province : region.get_provinces()) { @@ -575,6 +584,7 @@ bool Map::load_region_file(ast::NodeCPtr root) { } } } + return ret; } @@ -830,45 +840,48 @@ bool Map::generate_and_load_province_adjacencies(std::vector<LineObject> const& } bool Map::load_climate_file(ModifierManager const& modifier_manager, ast::NodeCPtr root) { - bool ret = expect_dictionary_reserve_length(climates, [this, &modifier_manager](std::string_view identifier, ast::NodeCPtr node) -> bool { - if (identifier.empty()) { - Logger::error("Invalid climate identifier - empty!"); - return false; - } + bool ret = expect_dictionary_reserve_length( + climates, + [this, &modifier_manager](std::string_view identifier, ast::NodeCPtr node) -> bool { + if (identifier.empty()) { + Logger::error("Invalid climate identifier - empty!"); + return false; + } - bool ret = true; - Climate* cur_climate = climates.get_item_by_identifier(identifier); - if (cur_climate == nullptr) { - ModifierValue values; - ret &= modifier_manager.expect_modifier_value(move_variable_callback(values))(node); - ret &= climates.add_item({ identifier, std::move(values) }); - } else { - ret &= expect_list_reserve_length(*cur_climate, expect_province_identifier( - [cur_climate, &identifier](Province& province) { - if (province.climate != cur_climate) { - cur_climate->add_province(&province); - if (province.climate != nullptr) { - Climate* old_climate = const_cast<Climate*>(province.climate); - old_climate->remove_province(&province); + bool ret = true; + Climate* cur_climate = climates.get_item_by_identifier(identifier); + if (cur_climate == nullptr) { + ModifierValue values; + ret &= modifier_manager.expect_modifier_value(move_variable_callback(values))(node); + ret &= climates.add_item({ identifier, std::move(values) }); + } else { + ret &= expect_list_reserve_length(*cur_climate, expect_province_identifier( + [cur_climate, &identifier](Province& province) { + if (province.climate != cur_climate) { + cur_climate->add_province(&province); + if (province.climate != nullptr) { + Climate* old_climate = const_cast<Climate*>(province.climate); + old_climate->remove_province(&province); + Logger::warning( + "Province with id ", province.get_identifier(), + " found in multiple climates: ", identifier, + " and ", old_climate->get_identifier() + ); + } + province.climate = cur_climate; + } else { Logger::warning( "Province with id ", province.get_identifier(), - " found in multiple climates: ", identifier, - " and ", old_climate->get_identifier() + " defined twice in climate ", identifier ); } - province.climate = cur_climate; - } else { - Logger::warning( - "Province with id ", province.get_identifier(), - " defined twice in climate ", identifier - ); + return true; } - return true; - } - ))(node); + ))(node); + } + return ret; } - return ret; - })(root); + )(root); for (Climate& climate : climates.get_items()) { climate.lock(); @@ -880,42 +893,45 @@ bool Map::load_climate_file(ModifierManager const& modifier_manager, ast::NodeCP } bool Map::load_continent_file(ModifierManager const& modifier_manager, ast::NodeCPtr root) { - bool ret = expect_dictionary_reserve_length(continents, [this, &modifier_manager](std::string_view identifier, ast::NodeCPtr node) -> bool { - if (identifier.empty()) { - Logger::error("Invalid continent identifier - empty!"); - return false; - } + bool ret = expect_dictionary_reserve_length( + continents, + [this, &modifier_manager](std::string_view identifier, ast::NodeCPtr node) -> bool { + if (identifier.empty()) { + Logger::error("Invalid continent identifier - empty!"); + return false; + } - ModifierValue values; - ProvinceSetModifier::provinces_t prov_list; - bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(values), - "provinces", ONE_EXACTLY, expect_list_reserve_length(prov_list, expect_province_identifier( - [&prov_list](Province const& province) -> bool { - if (province.continent == nullptr) { - prov_list.emplace_back(&province); - } else { - Logger::warning("Province ", province, " found in multiple continents"); + ModifierValue values; + ProvinceSetModifier::provinces_t prov_list; + bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(values), + "provinces", ONE_EXACTLY, expect_list_reserve_length(prov_list, expect_province_identifier( + [&prov_list](Province const& province) -> bool { + if (province.continent == nullptr) { + prov_list.emplace_back(&province); + } else { + Logger::warning("Province ", province, " found in multiple continents"); + } + return true; } - return true; - } - )) - )(node); + )) + )(node); - Continent continent = { identifier, std::move(values) }; - continent.add_provinces(prov_list); - continent.lock(); + Continent continent = { identifier, std::move(values) }; + continent.add_provinces(prov_list); + continent.lock(); - if (continents.add_item(std::move(continent))) { - Continent const& moved_continent = continents.get_items().back(); - for (Province const* prov : moved_continent.get_provinces()) { - remove_province_const(prov)->continent = &moved_continent; + if (continents.add_item(std::move(continent))) { + Continent const& moved_continent = continents.get_items().back(); + for (Province const* prov : moved_continent.get_provinces()) { + remove_province_const(prov)->continent = &moved_continent; + } + } else { + ret = false; } - } else { - ret = false; - } - return ret; - })(root); + return ret; + } + )(root); lock_continents(); diff --git a/src/openvic-simulation/map/Province.cpp b/src/openvic-simulation/map/Province.cpp index acabbf8..94c8dcb 100644 --- a/src/openvic-simulation/map/Province.cpp +++ b/src/openvic-simulation/map/Province.cpp @@ -77,7 +77,7 @@ bool Province::add_pop(Pop&& pop) { bool Province::add_pop_vec(std::vector<Pop> const& pop_vec) { if (!is_water()) { - pops.reserve(pops.size() + pop_vec.size()); + reserve_more(pops, pop_vec.size()); for (Pop const& pop : pop_vec) { pops.push_back(pop); } diff --git a/src/openvic-simulation/map/Region.cpp b/src/openvic-simulation/map/Region.cpp index 6f40338..c735279 100644 --- a/src/openvic-simulation/map/Region.cpp +++ b/src/openvic-simulation/map/Region.cpp @@ -83,6 +83,10 @@ void ProvinceSet::reserve(size_t size) { } } +void ProvinceSet::reserve_more(size_t size) { + OpenVic::reserve_more(*this, size); +} + bool ProvinceSet::contains_province(Province const* province) const { return province && std::find(provinces.begin(), provinces.end(), province) != provinces.end(); } diff --git a/src/openvic-simulation/map/Region.hpp b/src/openvic-simulation/map/Region.hpp index d8948b7..420d221 100644 --- a/src/openvic-simulation/map/Region.hpp +++ b/src/openvic-simulation/map/Region.hpp @@ -23,6 +23,7 @@ namespace OpenVic { bool empty() const; size_t size() const; void reserve(size_t size); + void reserve_more(size_t size); bool contains_province(Province const* province) const; provinces_t const& get_provinces() const; }; diff --git a/src/openvic-simulation/map/TerrainType.cpp b/src/openvic-simulation/map/TerrainType.cpp index a4529bf..e7dd068 100644 --- a/src/openvic-simulation/map/TerrainType.cpp +++ b/src/openvic-simulation/map/TerrainType.cpp @@ -130,11 +130,8 @@ 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_and_length_and_default( - [this](size_t size) -> size_t { - terrain_type_mappings.reserve(size - 2); - return size; - }, + const bool ret = expect_dictionary_keys_reserve_length_and_default( + terrain_type_mappings, std::bind_front(&TerrainTypeManager::_load_terrain_type_mapping, this), "terrain", ONE_EXACTLY, expect_uint(assign_variable_callback(terrain_texture_limit)), "categories", ONE_EXACTLY, _load_terrain_type_categories(modifier_manager) diff --git a/src/openvic-simulation/military/LeaderTrait.cpp b/src/openvic-simulation/military/LeaderTrait.cpp index 978a3ed..08bb923 100644 --- a/src/openvic-simulation/military/LeaderTrait.cpp +++ b/src/openvic-simulation/military/LeaderTrait.cpp @@ -26,20 +26,33 @@ bool LeaderTraitManager::add_leader_trait( } bool LeaderTraitManager::load_leader_traits_file(ModifierManager const& modifier_manager, ast::NodeCPtr root) { - using enum LeaderTrait::trait_type_t; - const auto trait_callback = [this, &modifier_manager](LeaderTrait::trait_type_t type) -> key_value_callback_t { - return [this, &modifier_manager, type](std::string_view trait_identifier, ast::NodeCPtr value) -> bool { - ModifierValue modifiers; - bool ret = - modifier_manager.expect_whitelisted_modifier_value(move_variable_callback(modifiers), allowed_modifiers)(value); - ret &= add_leader_trait(trait_identifier, type, std::move(modifiers)); - return ret; - }; + const auto trait_callback = [this, &modifier_manager](LeaderTrait::trait_type_t type) -> NodeCallback auto { + return expect_dictionary_reserve_length( + leader_traits, + [this, &modifier_manager, type](std::string_view trait_identifier, ast::NodeCPtr value) -> bool { + static const string_set_t allowed_modifiers = { + "attack", "defence", "morale", "organisation", "reconnaissance", + "speed", "attrition", "experience", "reliability" + }; + + ModifierValue modifiers; + bool ret = modifier_manager.expect_whitelisted_modifier_value( + move_variable_callback(modifiers), allowed_modifiers + )(value); + + ret &= add_leader_trait(trait_identifier, type, std::move(modifiers)); + return ret; + } + ); }; + + using enum LeaderTrait::trait_type_t; + const bool ret = expect_dictionary_keys( - "personality", ONE_EXACTLY, expect_dictionary(trait_callback(PERSONALITY)), - "background", ONE_EXACTLY, expect_dictionary(trait_callback(BACKGROUND)) + "personality", ONE_EXACTLY, trait_callback(PERSONALITY), + "background", ONE_EXACTLY, trait_callback(BACKGROUND) )(root); + lock_leader_traits(); return ret; diff --git a/src/openvic-simulation/military/LeaderTrait.hpp b/src/openvic-simulation/military/LeaderTrait.hpp index 0d84814..7dd5217 100644 --- a/src/openvic-simulation/military/LeaderTrait.hpp +++ b/src/openvic-simulation/military/LeaderTrait.hpp @@ -44,9 +44,6 @@ namespace OpenVic { struct LeaderTraitManager { private: IdentifierRegistry<LeaderTrait> IDENTIFIER_REGISTRY(leader_trait); - static inline const string_set_t allowed_modifiers = { - "attack", "defence", "morale", "organisation", "reconnaissance", "speed", "attrition", "experience", "reliability" - }; public: bool add_leader_trait(std::string_view identifier, LeaderTrait::trait_type_t type, ModifierValue&& modifiers); diff --git a/src/openvic-simulation/military/Wargoal.cpp b/src/openvic-simulation/military/Wargoal.cpp index 4045fa5..e81eaa0 100644 --- a/src/openvic-simulation/military/Wargoal.cpp +++ b/src/openvic-simulation/military/Wargoal.cpp @@ -69,7 +69,8 @@ bool WargoalTypeManager::add_wargoal_type( } bool WargoalTypeManager::load_wargoal_file(ast::NodeCPtr root) { - bool ret = expect_dictionary( + bool ret = expect_dictionary_reserve_length( + wargoal_types, [this](std::string_view identifier, ast::NodeCPtr value) -> bool { if (identifier == "peace_order") { return true; diff --git a/src/openvic-simulation/misc/Decision.cpp b/src/openvic-simulation/misc/Decision.cpp index df78c80..e0bd7c0 100644 --- a/src/openvic-simulation/misc/Decision.cpp +++ b/src/openvic-simulation/misc/Decision.cpp @@ -52,7 +52,8 @@ bool DecisionManager::add_decision( bool DecisionManager::load_decision_file(ast::NodeCPtr root) { return expect_dictionary_keys( - "political_decisions", ZERO_OR_ONE, expect_dictionary( + "political_decisions", ZERO_OR_ONE, expect_dictionary_reserve_length( + decisions, [this](std::string_view identifier, ast::NodeCPtr node) -> bool { bool alert = true, news = false; std::string_view news_title, news_desc_long, news_desc_medium, news_desc_short, picture; diff --git a/src/openvic-simulation/misc/Define.cpp b/src/openvic-simulation/misc/Define.cpp index 45584f7..e4e6b52 100644 --- a/src/openvic-simulation/misc/Define.cpp +++ b/src/openvic-simulation/misc/Define.cpp @@ -30,6 +30,10 @@ uint64_t Define::get_value_as_uint() const { } bool DefineManager::add_define(std::string_view name, std::string&& value, Define::Type type) { + if (name.empty()) { + Logger::error("Invalid define identifier - empty!"); + return false; + } return defines.add_item({ name, std::move(value), type }, duplicate_warning_callback); } @@ -55,62 +59,53 @@ bool DefineManager::add_date_define(std::string_view name, Date date) { } else if (name == "end_date") { end_date = date; } else { + Logger::error("Invalid date define identifier - \"", name, "\" (must be start_date or end_date)"); return false; } - return defines.add_item({ name, date.to_string(), Define::Type::None }); + return defines.add_item({ name, date.to_string(), Define::Type::Date }); } bool DefineManager::load_defines_file(ast::NodeCPtr root) { bool ret = expect_dictionary_keys( "defines", ONE_EXACTLY, expect_dictionary([this](std::string_view key, ast::NodeCPtr value) -> bool { - if (key == "country" || key == "economy" || key == "military" || key == "diplomacy" || - key == "pops" || key == "ai" || key == "graphics") { - return expect_dictionary([this, &key](std::string_view inner_key, ast::NodeCPtr value) -> bool { - std::string str_val; - - bool ret = expect_identifier_or_string(assign_variable_callback_string(str_val))(value); - - Define::Type type; - switch (key[0]) { - using enum Define::Type; - case 'c': // country - type = Country; - break; - case 'e': // economy - type = Economy; - break; - case 'm': // military - type = Military; - break; - case 'd': // diplomacy - type = Diplomacy; - break; - case 'p': // pops - type = Pops; - break; - case 'a': // ai - type = Ai; - break; - case 'g': // graphics - type = Graphics; - break; - default: - Logger::error("Unknown define type ", key, " found in defines!"); - return false; + using enum Define::Type; + static const string_map_t<Define::Type> type_map { + { "country", Country }, + { "economy", Economy }, + { "military", Military }, + { "diplomacy", Diplomacy }, + { "pops", Pops }, + { "ai", Ai }, + { "graphics", Graphics }, + }; + + const string_map_t<Define::Type>::const_iterator type_it = type_map.find(key); + + if (type_it != type_map.end()) { + + return expect_dictionary_reserve_length( + defines, + [this, &key, type = type_it->second](std::string_view inner_key, ast::NodeCPtr value) -> bool { + std::string str_val; + bool ret = expect_identifier_or_string(assign_variable_callback_string(str_val))(value); + ret &= add_define(inner_key, std::move(str_val), type); + return ret; } + )(value); - ret &= add_define(inner_key, std::move(str_val), type); - return ret; - })(value); } else if (key == "start_date" || key == "end_date") { - return expect_identifier_or_string(expect_date_str([this, &key](Date date) -> bool { - return add_date_define(key, date); - }))(value); + + return expect_identifier_or_string(expect_date_str( + std::bind_front(&DefineManager::add_date_define, this, key) + ))(value); + } else { return false; } }) )(root); + lock_defines(); + return ret; } diff --git a/src/openvic-simulation/misc/Define.hpp b/src/openvic-simulation/misc/Define.hpp index c3c7888..64eb605 100644 --- a/src/openvic-simulation/misc/Define.hpp +++ b/src/openvic-simulation/misc/Define.hpp @@ -1,6 +1,5 @@ #pragma once -#include <concepts> #include <optional> #include "openvic-simulation/types/IdentifierRegistry.hpp" @@ -12,7 +11,7 @@ namespace OpenVic { struct Define : HasIdentifier { friend struct DefineManager; - enum class Type : unsigned char { None, Country, Economy, Military, Diplomacy, Pops, Ai, Graphics }; + enum class Type : unsigned char { Date, Country, Economy, Military, Diplomacy, Pops, Ai, Graphics }; private: const std::string PROPERTY(value); diff --git a/src/openvic-simulation/misc/Event.cpp b/src/openvic-simulation/misc/Event.cpp index 34743e8..2617927 100644 --- a/src/openvic-simulation/misc/Event.cpp +++ b/src/openvic-simulation/misc/Event.cpp @@ -116,7 +116,8 @@ bool EventManager::add_on_action(std::string_view identifier, OnAction::weight_m } bool EventManager::load_event_file(IssueManager const& issue_manager, ast::NodeCPtr root) { - return expect_dictionary( + return expect_dictionary_reserve_length( + events, [this, &issue_manager](std::string_view key, ast::NodeCPtr value) -> bool { Event::event_type_t type; scope_t initial_scope; diff --git a/src/openvic-simulation/politics/Government.cpp b/src/openvic-simulation/politics/Government.cpp index 49e0f2f..28f5d09 100644 --- a/src/openvic-simulation/politics/Government.cpp +++ b/src/openvic-simulation/politics/Government.cpp @@ -47,7 +47,8 @@ bool GovernmentTypeManager::add_government_type( /* REQUIREMENTS: FS-525, SIM-27 */ bool GovernmentTypeManager::load_government_types_file(IdeologyManager const& ideology_manager, ast::NodeCPtr root) { - bool ret = expect_dictionary_reserve_length(government_types, + bool ret = expect_dictionary_reserve_length( + government_types, [this, &ideology_manager](std::string_view government_type_identifier, ast::NodeCPtr government_type_value) -> bool { std::vector<Ideology const*> ideologies; bool elections = false, appoint_ruling_party = false; diff --git a/src/openvic-simulation/politics/Ideology.cpp b/src/openvic-simulation/politics/Ideology.cpp index 692b809..1848a0a 100644 --- a/src/openvic-simulation/politics/Ideology.cpp +++ b/src/openvic-simulation/politics/Ideology.cpp @@ -68,7 +68,8 @@ bool IdeologyManager::add_ideology( */ bool IdeologyManager::load_ideology_file(ast::NodeCPtr root) { size_t expected_ideologies = 0; - bool ret = expect_dictionary_reserve_length(ideology_groups, + bool ret = expect_dictionary_reserve_length( + ideology_groups, [this, &expected_ideologies](std::string_view key, ast::NodeCPtr value) -> bool { bool ret = expect_length(add_variable_callback(expected_ideologies))(value); ret &= add_ideology_group(key); @@ -77,7 +78,7 @@ bool IdeologyManager::load_ideology_file(ast::NodeCPtr root) { )(root); lock_ideology_groups(); - ideologies.reserve(ideologies.size() + expected_ideologies); + reserve_more_ideologies(expected_ideologies); ret &= expect_dictionary([this](std::string_view ideology_group_key, ast::NodeCPtr ideology_group_value) -> bool { IdeologyGroup const* ideology_group = get_ideology_group_by_identifier(ideology_group_key); diff --git a/src/openvic-simulation/politics/Issue.cpp b/src/openvic-simulation/politics/Issue.cpp index 30dc1cd..d8fe52e 100644 --- a/src/openvic-simulation/politics/Issue.cpp +++ b/src/openvic-simulation/politics/Issue.cpp @@ -191,7 +191,8 @@ bool IssueManager::_load_reform( bool IssueManager::load_issues_file(ModifierManager const& modifier_manager, RuleManager const& rule_manager, ast::NodeCPtr root) { size_t expected_issue_groups = 0; size_t expected_reform_groups = 0; - bool ret = expect_dictionary_reserve_length(reform_types, + bool ret = expect_dictionary_reserve_length( + reform_types, [this, &expected_issue_groups, &expected_reform_groups](std::string_view key, ast::NodeCPtr value) -> bool { if (key == "party_issues") { return expect_length(add_variable_callback(expected_issue_groups))(value); @@ -206,12 +207,12 @@ bool IssueManager::load_issues_file(ModifierManager const& modifier_manager, Rul )(root); lock_reform_types(); - issue_groups.reserve(issue_groups.size() + expected_issue_groups); - reform_groups.reserve(reform_groups.size() + expected_reform_groups); + reserve_more_issue_groups(expected_issue_groups); + reserve_more_reform_groups(expected_reform_groups); size_t expected_issues = 0; size_t expected_reforms = 0; - ret &= expect_dictionary_reserve_length(issue_groups, + ret &= expect_dictionary( [this, &expected_issues, &expected_reforms](std::string_view type_key, ast::NodeCPtr type_value) -> bool { if (type_key == "party_issues") { return expect_dictionary([this, &expected_issues](std::string_view key, ast::NodeCPtr value) -> bool { @@ -230,28 +231,36 @@ bool IssueManager::load_issues_file(ModifierManager const& modifier_manager, Rul lock_issue_groups(); lock_reform_groups(); - issues.reserve(issues.size() + expected_issues); - reforms.reserve(reforms.size() + expected_reforms); - - ret &= expect_dictionary([this, &modifier_manager, &rule_manager](std::string_view type_key, ast::NodeCPtr type_value) -> bool { - return expect_dictionary([this, &modifier_manager, &rule_manager, type_key](std::string_view group_key, ast::NodeCPtr group_value) -> bool { - if (type_key == "party_issues") { - IssueGroup const* issue_group = get_issue_group_by_identifier(group_key); - return expect_dictionary([this, &modifier_manager, &rule_manager, issue_group](std::string_view key, ast::NodeCPtr value) -> bool { - return _load_issue(modifier_manager, rule_manager, key, issue_group, value); - })(group_value); - } else { - ReformGroup const* reform_group = get_reform_group_by_identifier(group_key); - size_t ordinal = 0; - return expect_dictionary([this, &modifier_manager, &rule_manager, reform_group, &ordinal](std::string_view key, ast::NodeCPtr value) -> bool { - if (key == "next_step_only" || key == "administrative") { - return true; - } - return _load_reform(modifier_manager, rule_manager, ordinal++, key, reform_group, value); - })(group_value); - } - })(type_value); - })(root); + reserve_more_issues(expected_issues); + reserve_more_reforms(expected_reforms); + + ret &= expect_dictionary( + [this, &modifier_manager, &rule_manager](std::string_view type_key, ast::NodeCPtr type_value) -> bool { + return expect_dictionary([this, &modifier_manager, &rule_manager, type_key]( + std::string_view group_key, ast::NodeCPtr group_value + ) -> bool { + if (type_key == "party_issues") { + IssueGroup const* issue_group = get_issue_group_by_identifier(group_key); + return expect_dictionary([this, &modifier_manager, &rule_manager, issue_group]( + std::string_view key, ast::NodeCPtr value + ) -> bool { + return _load_issue(modifier_manager, rule_manager, key, issue_group, value); + })(group_value); + } else { + ReformGroup const* reform_group = get_reform_group_by_identifier(group_key); + size_t ordinal = 0; + return expect_dictionary([this, &modifier_manager, &rule_manager, reform_group, &ordinal]( + std::string_view key, ast::NodeCPtr value + ) -> bool { + if (key == "next_step_only" || key == "administrative") { + return true; + } + return _load_reform(modifier_manager, rule_manager, ordinal++, key, reform_group, value); + })(group_value); + } + })(type_value); + } + )(root); lock_issues(); lock_reforms(); diff --git a/src/openvic-simulation/politics/NationalFocus.cpp b/src/openvic-simulation/politics/NationalFocus.cpp index f555172..22b91b2 100644 --- a/src/openvic-simulation/politics/NationalFocus.cpp +++ b/src/openvic-simulation/politics/NationalFocus.cpp @@ -84,7 +84,7 @@ bool NationalFocusManager::load_national_foci_file( )(root); lock_national_focus_groups(); - national_foci.reserve(expected_national_foci); + reserve_more_national_foci(expected_national_foci); ret &= expect_national_focus_group_dictionary([this, &pop_manager, &ideology_manager, &good_manager, &modifier_manager]( NationalFocusGroup const& group, ast::NodeCPtr group_node diff --git a/src/openvic-simulation/politics/NationalValue.cpp b/src/openvic-simulation/politics/NationalValue.cpp index 57c5652..a149acf 100644 --- a/src/openvic-simulation/politics/NationalValue.cpp +++ b/src/openvic-simulation/politics/NationalValue.cpp @@ -16,7 +16,8 @@ bool NationalValueManager::add_national_value(std::string_view identifier, Modif } bool NationalValueManager::load_national_values_file(ModifierManager const& modifier_manager, ast::NodeCPtr root) { - bool ret = expect_dictionary( + bool ret = expect_dictionary_reserve_length( + national_values, [this, &modifier_manager](std::string_view national_value_identifier, ast::NodeCPtr value) -> bool { ModifierValue modifiers; @@ -26,6 +27,7 @@ bool NationalValueManager::load_national_values_file(ModifierManager const& modi return ret; } )(root); + lock_national_values(); return ret; diff --git a/src/openvic-simulation/politics/Rebel.cpp b/src/openvic-simulation/politics/Rebel.cpp index 2f39bee..ce99d08 100644 --- a/src/openvic-simulation/politics/Rebel.cpp +++ b/src/openvic-simulation/politics/Rebel.cpp @@ -95,7 +95,8 @@ bool RebelManager::load_rebels_file( { "any", RebelType::independence_t::ANY } }; - bool ret = expect_dictionary( + bool ret = expect_dictionary_reserve_length( + rebel_types, [this, &ideology_manager, &government_type_manager](std::string_view identifier, ast::NodeCPtr node) -> bool { RebelType::icon_t icon = 0; RebelType::area_t area = RebelType::area_t::ALL; diff --git a/src/openvic-simulation/politics/Rule.cpp b/src/openvic-simulation/politics/Rule.cpp index 19e92af..ce0c319 100644 --- a/src/openvic-simulation/politics/Rule.cpp +++ b/src/openvic-simulation/politics/Rule.cpp @@ -161,7 +161,7 @@ bool RuleManager::setup_rules(BuildingTypeManager const& building_type_manager) for (auto const& [group, rule_list] : hardcoded_rules) { rule_count += rule_list.size(); } - rules.reserve(rule_count); + reserve_more_rules(rule_count); for (auto const& [group, rule_list] : hardcoded_rules) { for (std::string_view const& rule : rule_list) { diff --git a/src/openvic-simulation/pop/Culture.cpp b/src/openvic-simulation/pop/Culture.cpp index 53273f5..9466e9f 100644 --- a/src/openvic-simulation/pop/Culture.cpp +++ b/src/openvic-simulation/pop/Culture.cpp @@ -74,7 +74,8 @@ bool CultureManager::add_culture( } bool CultureManager::load_graphical_culture_type_file(ast::NodeCPtr root) { - const bool ret = expect_list_reserve_length(graphical_culture_types, + const bool ret = expect_list_reserve_length( + graphical_culture_types, expect_identifier(std::bind_front(&CultureManager::add_graphical_culture_type, this)) )(root); lock_graphical_culture_types(); @@ -169,7 +170,7 @@ bool CultureManager::load_culture_file(CountryManager const& country_manager, as } )(root); lock_culture_groups(); - cultures.reserve(cultures.size() + total_expected_cultures); + reserve_more_cultures(total_expected_cultures); ret &= expect_culture_group_dictionary( [this, &country_manager](CultureGroup const& culture_group, ast::NodeCPtr culture_group_value) -> bool { diff --git a/src/openvic-simulation/pop/Pop.cpp b/src/openvic-simulation/pop/Pop.cpp index d422038..643f313 100644 --- a/src/openvic-simulation/pop/Pop.cpp +++ b/src/openvic-simulation/pop/Pop.cpp @@ -273,10 +273,19 @@ bool PopManager::add_pop_type( return ret; } -void PopManager::reserve_pop_types(size_t count) { - stratas.reserve(stratas.size() + count); - pop_types.reserve(pop_types.size() + count); - delayed_parse_nodes.reserve(delayed_parse_nodes.size() + count); +void PopManager::reserve_all_pop_types(size_t size) { + reserve_more_stratas(size); + if (pop_types_are_locked()) { + Logger::error("Failed to reserve space for ", size, " pop types in PopManager - already locked!"); + } else { + reserve_more_pop_types(size); + reserve_more(delayed_parse_nodes, size); + } +} + +void PopManager::lock_all_pop_types() { + lock_stratas(); + lock_pop_types(); } static NodeCallback auto expect_needs_income(PopType::income_type_t& types) { diff --git a/src/openvic-simulation/pop/Pop.hpp b/src/openvic-simulation/pop/Pop.hpp index 4e173bb..3e50c4d 100644 --- a/src/openvic-simulation/pop/Pop.hpp +++ b/src/openvic-simulation/pop/Pop.hpp @@ -286,7 +286,8 @@ namespace OpenVic { ast::NodeCPtr issues_node ); - void reserve_pop_types(size_t count); + void reserve_all_pop_types(size_t size); + void lock_all_pop_types(); bool load_pop_type_file( std::string_view filestem, UnitManager const& unit_manager, GoodManager const& good_manager, diff --git a/src/openvic-simulation/pop/Religion.cpp b/src/openvic-simulation/pop/Religion.cpp index 0527da7..3fa81bf 100644 --- a/src/openvic-simulation/pop/Religion.cpp +++ b/src/openvic-simulation/pop/Religion.cpp @@ -47,7 +47,8 @@ bool ReligionManager::add_religion( */ bool ReligionManager::load_religion_file(ast::NodeCPtr root) { size_t total_expected_religions = 0; - bool ret = expect_dictionary_reserve_length(religion_groups, + bool ret = expect_dictionary_reserve_length( + religion_groups, [this, &total_expected_religions](std::string_view key, ast::NodeCPtr value) -> bool { bool ret = expect_length(add_variable_callback(total_expected_religions))(value); ret &= add_religion_group(key); @@ -55,22 +56,24 @@ bool ReligionManager::load_religion_file(ast::NodeCPtr root) { } )(root); lock_religion_groups(); - religions.reserve(religions.size() + total_expected_religions); - ret &= expect_religion_group_dictionary([this](ReligionGroup const& religion_group, ast::NodeCPtr religion_group_value) -> bool { - return expect_dictionary([this, &religion_group](std::string_view key, ast::NodeCPtr value) -> bool { - colour_t colour = colour_t::null(); - Religion::icon_t icon = 0; - bool pagan = false; + reserve_more_religions(total_expected_religions); + ret &= expect_religion_group_dictionary( + [this](ReligionGroup const& religion_group, ast::NodeCPtr religion_group_value) -> bool { + return expect_dictionary([this, &religion_group](std::string_view key, ast::NodeCPtr value) -> bool { + colour_t colour = colour_t::null(); + Religion::icon_t icon = 0; + bool pagan = false; - bool ret = expect_dictionary_keys( - "icon", ONE_EXACTLY, expect_uint(assign_variable_callback(icon)), - "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)), - "pagan", ZERO_OR_ONE, expect_bool(assign_variable_callback(pagan)) - )(value); - ret &= add_religion(key, colour, religion_group, icon, pagan); - return ret; - })(religion_group_value); - })(root); + bool ret = expect_dictionary_keys( + "icon", ONE_EXACTLY, expect_uint(assign_variable_callback(icon)), + "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)), + "pagan", ZERO_OR_ONE, expect_bool(assign_variable_callback(pagan)) + )(value); + ret &= add_religion(key, colour, religion_group, icon, pagan); + return ret; + })(religion_group_value); + } + )(root); lock_religions(); return ret; } diff --git a/src/openvic-simulation/types/IdentifierRegistry.hpp b/src/openvic-simulation/types/IdentifierRegistry.hpp index 68013d5..10248cc 100644 --- a/src/openvic-simulation/types/IdentifierRegistry.hpp +++ b/src/openvic-simulation/types/IdentifierRegistry.hpp @@ -155,6 +155,7 @@ namespace OpenVic { public: using storage_type = typename StorageInfo::storage_type; + static constexpr bool storage_type_reservable = Reservable<storage_type>; private: const std::string name; @@ -224,14 +225,22 @@ namespace OpenVic { } constexpr void reserve(std::size_t size) { - if (locked) { - Logger::error("Failed to reserve space for ", size, " items in ", name, " registry - already locked!"); + if constexpr (storage_type_reservable) { + if (locked) { + Logger::error("Failed to reserve space for ", size, " items in ", name, " registry - already locked!"); + } else { + items.reserve(size); + identifier_index_map.reserve(size); + } } else { - items.reserve(size); - identifier_index_map.reserve(size); + Logger::error("Cannot reserve space for ", size, " ", name, " - storage_type not reservable!"); } } + constexpr void reserve_more(std::size_t size) { + OpenVic::reserve_more(*this, size); + } + static constexpr NodeTools::KeyValueCallback auto key_value_invalid_callback(std::string_view name) { return [name](std::string_view key, ast::NodeCPtr) { Logger::error("Invalid ", name, ": ", key); @@ -285,7 +294,7 @@ namespace OpenVic { value_type CONST* item = get_item_by_identifier(key); \ if (item != nullptr) { \ return callback(*item, value); \ - } else {\ + } else { \ return default_callback(key, value); \ } \ } \ @@ -334,25 +343,23 @@ namespace OpenVic { callback \ ); \ } \ - template<NodeTools::Reservable T> \ constexpr NodeTools::NodeCallback auto expect_item_dictionary_reserve_length_and_default( \ - T& t, \ + Reservable auto& reservable, \ NodeTools::KeyValueCallback auto default_callback, \ NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \ ) CONST { \ return expect_item_dictionary_and_length_and_default( \ - NodeTools::reserve_length_callback(t), \ + NodeTools::reserve_length_callback(reservable), \ default_callback, \ callback \ ); \ } \ - template<NodeTools::Reservable T> \ constexpr NodeTools::NodeCallback auto expect_item_dictionary_reserve_length( \ - T& t, \ + Reservable auto& reservable, \ NodeTools::Callback<value_type CONST&, ast::NodeCPtr> auto callback \ ) CONST { \ return expect_item_dictionary_and_length_and_default( \ - NodeTools::reserve_length_callback(t), \ + NodeTools::reserve_length_callback(reservable), \ key_value_invalid_callback(name), \ callback \ ); \ @@ -454,7 +461,7 @@ namespace OpenVic { IDENTIFIER_REGISTRY_FULL_CUSTOM(name, name##s, name##s, name##s, index_offset) #define IDENTIFIER_REGISTRY_FULL_CUSTOM(singular, plural, registry, debug_name, index_offset) \ - registry { #debug_name };\ + registry { #debug_name }; \ public: \ constexpr void lock_##plural() { \ registry.lock(); \ @@ -462,6 +469,14 @@ public: \ constexpr bool plural##_are_locked() const { \ return registry.is_locked(); \ } \ + template<typename = void> \ + constexpr void reserve_##plural(size_t size) requires(decltype(registry)::storage_type_reservable) { \ + registry.reserve(size); \ + } \ + template<typename = void> \ + constexpr void reserve_more_##plural(size_t size) requires(decltype(registry)::storage_type_reservable) { \ + registry.reserve_more(size); \ + } \ constexpr bool has_##singular##_identifier(std::string_view identifier) const { \ return registry.has_identifier(identifier); \ } \ @@ -555,19 +570,17 @@ private: ) const_kw { \ return registry.expect_item_dictionary(callback); \ } \ - template<NodeTools::Reservable T> \ constexpr NodeTools::NodeCallback auto expect_##singular##_dictionary_reserve_length_and_default( \ - T& t, \ + Reservable auto& reservable, \ NodeTools::KeyValueCallback auto default_callback, \ NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \ ) const_kw { \ - return registry.expect_item_dictionary_reserve_length_and_default(t, default_callback, callback); \ + return registry.expect_item_dictionary_reserve_length_and_default(reservable, default_callback, callback); \ } \ - template<NodeTools::Reservable T> \ constexpr NodeTools::NodeCallback auto expect_##singular##_dictionary_reserve_length( \ - T& t, \ + Reservable auto& reservable, \ NodeTools::Callback<decltype(registry)::value_type const_kw&, ast::NodeCPtr> auto callback \ ) const_kw { \ - return registry.expect_item_dictionary_reserve_length(t, callback); \ + return registry.expect_item_dictionary_reserve_length(reservable, callback); \ } } diff --git a/src/openvic-simulation/utility/BMP.cpp b/src/openvic-simulation/utility/BMP.cpp index c615aea..e359c2e 100644 --- a/src/openvic-simulation/utility/BMP.cpp +++ b/src/openvic-simulation/utility/BMP.cpp @@ -1,7 +1,6 @@ #include "BMP.hpp" #include <cstring> -#include <set> #include "openvic-simulation/types/OrderedContainers.hpp" #include "openvic-simulation/utility/Logger.hpp" |