Different approach to chrono::duration serialization

Since we're relying on free functions to parse and serialize time_points, it makes more sense to do likewise for durations rather than relying on a config_attribute_value member function. Leaves the assignment support for now.
This commit is contained in:
Charles Dang 2024-11-05 01:52:42 -05:00
parent 6dc65f6483
commit 9a77b72aac
12 changed files with 50 additions and 28 deletions

View file

@ -149,21 +149,12 @@ public:
std::string str(const std::string& fallback = "") const;
t_string t_str() const;
template<typename Duration>
auto to_duration(const Duration& def = Duration{0}) const
{
return Duration{to_long_long(def.count())};
}
bool to(const bool def) const { return to_bool(def); }
int to(int def) const { return to_int(def); }
unsigned to(unsigned def) const { return to_unsigned(def); }
double to(double def) const { return to_double(def); }
std::string to(const std::string& def) const { return str(def); }
template<typename... Args>
auto to(const std::chrono::duration<Args...>& def) const { return to_duration(def); }
// Implicit conversions:
operator std::string() const { return str(); }
operator t_string() const { return t_str(); }

View file

@ -18,6 +18,7 @@
#include "config.hpp"
#include "log.hpp"
#include "preferences/preferences.hpp"
#include "serialization/chrono.hpp"
#include "serialization/string_utils.hpp"
#include "game_version.hpp"
#include "game_config_manager.hpp"
@ -51,7 +52,7 @@ game_classification::game_classification(const config& cfg)
, abbrev(cfg["abbrev"])
, end_credits(cfg["end_credits"].to_bool(true))
, end_text(cfg["end_text"])
, end_text_duration(std::clamp(cfg["end_text_duration"].to_duration(0ms), 0ms, 5000ms))
, end_text_duration(std::clamp(chrono::parse_duration(cfg["end_text_duration"], 0ms), 0ms, 5000ms))
, difficulty(cfg["difficulty"].empty() ? DEFAULT_DIFFICULTY : cfg["difficulty"].str())
, random_mode(cfg["random_mode"])
, oos_debug(cfg["oos_debug"].to_bool(false))

View file

@ -20,6 +20,7 @@
#include "gettext.hpp"
#include "log.hpp"
#include "game_version.hpp"
#include "serialization/chrono.hpp"
#include "serialization/string_utils.hpp"
#include <cmath>
@ -271,7 +272,7 @@ void load_config(const config &v)
recall_cost = v["recall_cost"].to_int(20);
kill_experience = v["kill_experience"].to_int(8);
combat_experience= v["combat_experience"].to_int(1);
lobby_refresh = v["lobby_refresh"].to_duration(2000ms);
lobby_refresh = chrono::parse_duration(v["lobby_refresh"], 2000ms);
default_terrain = v["default_terrain"].str();
tile_size = v["tile_size"].to_int(72);

View file

@ -28,6 +28,7 @@
#include "side_controller.hpp"
#include "wml_exception.hpp"
#include "serialization/chrono.hpp"
#include "serialization/preprocessor.hpp"
#include "serialization/parser.hpp"
@ -405,7 +406,7 @@ void create_engine::prepare_for_campaign(const std::string& difficulty)
state_.classification().abbrev = current_level_data["abbrev"].str();
state_.classification().end_text = current_level_data["end_text"].str();
state_.classification().end_text_duration = current_level_data["end_text_duration"].to_duration<std::chrono::milliseconds>();
state_.classification().end_text_duration = chrono::parse_duration<std::chrono::milliseconds>(current_level_data["end_text_duration"]);
state_.classification().end_credits = current_level_data["end_credits"].to_bool(true);
state_.classification().campaign_define = current_level_data["define"].str();

View file

@ -22,6 +22,7 @@
#include "gui/core/log.hpp"
#include "gui/core/static_registry.hpp"
#include "gui/widgets/settings.hpp"
#include "serialization/chrono.hpp"
#include "wml_exception.hpp"
namespace gui2
@ -125,12 +126,12 @@ gui_definition::gui_definition(const config& cfg)
const config& settings = cfg.mandatory_child("settings");
using namespace std::chrono_literals;
popup_show_delay_ = settings["popup_show_delay"].to_duration(0ms);
popup_show_time_ = settings["popup_show_time"].to_duration(0ms);
help_show_time_ = settings["help_show_time"].to_duration(0ms);
double_click_time_ = settings["double_click_time"].to_duration(0ms);
popup_show_delay_ = chrono::parse_duration(settings["popup_show_delay"], 0ms);
popup_show_time_ = chrono::parse_duration(settings["popup_show_time"], 0ms);
help_show_time_ = chrono::parse_duration(settings["help_show_time"], 0ms);
double_click_time_ = chrono::parse_duration(settings["double_click_time"], 0ms);
repeat_button_repeat_time_ = settings["repeat_button_repeat_time"].to_duration(0ms);
repeat_button_repeat_time_ = chrono::parse_duration(settings["repeat_button_repeat_time"], 0ms);
VALIDATE(!settings["double_click_time"].blank(), missing_mandatory_wml_key("settings", "double_click_time"));

View file

@ -36,6 +36,7 @@
#include "map_settings.hpp"
#include "map/map.hpp"
#include "resources.hpp"
#include "serialization/chrono.hpp"
#include "serialization/parser.hpp"
#include "sound.hpp"
#include "units/unit.hpp"
@ -1597,7 +1598,8 @@ void prefs::set_options(const config& values)
std::chrono::seconds prefs::countdown_init_time()
{
return std::clamp(preferences_[prefs_list::mp_countdown_init_time].to_duration(240s), 0s, 1500s);
auto val = chrono::parse_duration(preferences_[prefs_list::mp_countdown_init_time], 240s);
return std::clamp(val, 0s, 1500s);
}
void prefs::set_countdown_init_time(const std::chrono::seconds& value)
@ -1612,7 +1614,8 @@ void prefs::clear_countdown_init_time()
std::chrono::seconds prefs::countdown_reservoir_time()
{
return std::clamp(preferences_[prefs_list::mp_countdown_reservoir_time].to_duration(360s), 30s, 1500s);
auto val = chrono::parse_duration(preferences_[prefs_list::mp_countdown_reservoir_time], 360s);
return std::clamp(val, 30s, 1500s);
}
void prefs::set_countdown_reservoir_time(const std::chrono::seconds& value)
@ -1627,7 +1630,8 @@ void prefs::clear_countdown_reservoir_time()
std::chrono::seconds prefs::countdown_turn_bonus()
{
return std::clamp(preferences_[prefs_list::mp_countdown_turn_bonus].to_duration(240s), 0s, 300s);
auto val = chrono::parse_duration(preferences_[prefs_list::mp_countdown_turn_bonus], 240s);
return std::clamp(val, 0s, 300s);
}
void prefs::set_countdown_turn_bonus(const std::chrono::seconds& value)
@ -1642,7 +1646,8 @@ void prefs::clear_countdown_turn_bonus()
std::chrono::seconds prefs::countdown_action_bonus()
{
return std::clamp(preferences_[prefs_list::mp_countdown_action_bonus].to_duration(0s), 0s, 30s);
auto val = chrono::parse_duration(preferences_[prefs_list::mp_countdown_action_bonus], 0s);
return std::clamp(val, 0s, 30s);
}
void prefs::set_countdown_action_bonus(const std::chrono::seconds& value)
@ -1655,6 +1660,16 @@ void prefs::clear_countdown_action_bonus()
preferences_.remove_attribute(prefs_list::mp_countdown_action_bonus);
}
std::chrono::minutes prefs::chat_message_aging()
{
return chrono::parse_duration(preferences_[prefs_list::chat_message_aging], 20min);
}
void prefs::set_chat_message_aging(const std::chrono::minutes& value)
{
preferences_[prefs_list::chat_message_aging] = value;
}
int prefs::village_gold()
{
return settings::get_village_gold(preferences_[prefs_list::mp_village_gold]);

View file

@ -386,6 +386,9 @@ class prefs
void set_countdown_action_bonus(const std::chrono::seconds& value);
void clear_countdown_action_bonus();
std::chrono::minutes chat_message_aging();
void set_chat_message_aging(const std::chrono::minutes& value);
int village_gold();
void set_village_gold(int value);
@ -556,7 +559,6 @@ class prefs
PREF_GETTER_SETTER(floating_labels, bool, true)
PREF_GETTER_SETTER(chat_timestamp, bool, false)
PREF_GETTER_SETTER(chat_lines, int, 6)
PREF_GETTER_SETTER(chat_message_aging, std::chrono::minutes, std::chrono::minutes{20})
PREF_GETTER_SETTER(show_all_units_in_help, bool, false)
PREF_GETTER_SETTER(custom_command, std::string, std::string(""))
PREF_GETTER_SETTER(player_joins_sound, bool, true)

View file

@ -34,6 +34,7 @@
#include "preferences/preferences.hpp"
#include "replay_recorder_base.hpp"
#include "resources.hpp"
#include "serialization/chrono.hpp"
#include "synced_context.hpp"
#include "units/unit.hpp"
#include "whiteboard/manager.hpp"
@ -856,7 +857,7 @@ REPLAY_RETURN do_replay_handle(bool one_move)
}
else if (auto countdown_update = cfg->optional_child("countdown_update"))
{
auto val = countdown_update["value"].to_duration<std::chrono::milliseconds>();
auto val = chrono::parse_duration<std::chrono::milliseconds>(countdown_update["value"]);
int tval = countdown_update["team"].to_int();
if (tval <= 0 || tval > static_cast<int>(resources::gameboard->teams().size())) {
std::stringstream errbuf;

View file

@ -29,4 +29,11 @@ inline auto serialize_timestamp(const std::chrono::system_clock::time_point& tim
{
return std::chrono::system_clock::to_time_t(time);
}
template<typename Duration>
inline auto parse_duration(const config_attribute_value& val, const Duration& def = Duration{0})
{
return Duration{val.to_long_long(def.count())};
}
} // namespace chrono

View file

@ -346,7 +346,7 @@ void server::load_config()
compress_level_ = cfg_["compress_level"].to_int(6);
// One month probably will be fine (#TODO: testing needed)
constexpr std::chrono::seconds seconds_in_a_month{30 * 24 * 60 * 60};
update_pack_lifespan_ = cfg_["update_pack_lifespan"].to_duration(seconds_in_a_month);
update_pack_lifespan_ = chrono::parse_duration(cfg_["update_pack_lifespan"], seconds_in_a_month);
const auto& svinfo_cfg = server_info();
@ -979,7 +979,7 @@ void server::handle_request_campaign_list(const server::request& req)
std::chrono::system_clock::time_point before;
if(before_flag) {
if(relative_to_now) {
auto time_delta = req.cfg["before"].to_duration<std::chrono::seconds>();
auto time_delta = chrono::parse_duration<std::chrono::seconds>(req.cfg["before"]);
before = now + time_delta; // delta may be negative
} else {
before = chrono::parse_timestamp(req.cfg["before"]);
@ -990,7 +990,7 @@ void server::handle_request_campaign_list(const server::request& req)
std::chrono::system_clock::time_point after;
if(after_flag) {
if(relative_to_now) {
auto time_delta = req.cfg["after"].to_duration<std::chrono::seconds>();
auto time_delta = chrono::parse_duration<std::chrono::seconds>(req.cfg["after"]);
after = now + time_delta; // delta may be negative
} else {
after = chrono::parse_timestamp(req.cfg["after"]);

View file

@ -15,6 +15,7 @@
#include "display.hpp"
#include "random.hpp"
#include "serialization/chrono.hpp"
#include "sound.hpp"
#include "soundsource.hpp"
@ -240,7 +241,7 @@ void sourcespec::write(config& cfg) const
sourcespec::sourcespec(const config& cfg)
: id_(cfg["id"])
, files_(cfg["sounds"])
, min_delay_(cfg["delay"].to_duration(DEFAULT_DELAY))
, min_delay_(chrono::parse_duration(cfg["delay"], DEFAULT_DELAY))
, chance_(cfg["chance"].to_int(DEFAULT_CHANCE))
, loops_(cfg["loop"].to_int())
, range_(cfg["full_range"].to_int(3))

View file

@ -30,6 +30,7 @@
#include "play_controller.hpp"
#include "playsingle_controller.hpp"
#include "resources.hpp"
#include "serialization/chrono.hpp"
#include "serialization/string_utils.hpp"
#include "synced_context.hpp"
#include "units/types.hpp"
@ -392,7 +393,7 @@ void team::build(const config& cfg, const gamemap& map, int gold)
}
}
countdown_time_ = cfg["countdown_time"].to_duration<std::chrono::milliseconds>();
countdown_time_ = chrono::parse_duration<std::chrono::milliseconds>(cfg["countdown_time"]);
action_bonus_count_ = cfg["action_bonus_count"].to_int();
planned_actions_.reset(new wb::side_actions());