From ae7cc0a6d27d7c3769d7c8e5fdfac5e9b7fc6151 Mon Sep 17 00:00:00 2001 From: Guillaume Melquiond Date: Thu, 19 Aug 2010 22:07:53 +0000 Subject: [PATCH] Modified vconfig so that it is no longer forced... ...to return translatable strings after variable expansion. In particular, the engine no longer tries to expand variables inside plain numbers or booleans. --- src/config.hpp | 9 ++++++++ src/formula_string_utils.cpp | 13 +++++------ src/formula_string_utils.hpp | 1 + src/game_events.cpp | 29 +++++++++++-------------- src/gamestatus.cpp | 17 ++++++++------- src/gamestatus.hpp | 2 +- src/gui/auxiliary/formula.hpp | 1 + src/gui/dialogs/gamestate_inspector.cpp | 2 +- src/scripting/lua.cpp | 26 ---------------------- src/serialization/preprocessor.cpp | 2 +- src/serialization/string_utils.cpp | 4 ---- src/serialization/string_utils.hpp | 11 ++-------- src/storyscreen/part.cpp | 14 ++++++------ src/text.cpp | 1 + src/unit.cpp | 2 +- src/unit_display.cpp | 2 +- src/variable.cpp | 27 ++++++++++++++++++----- src/variable.hpp | 5 +++-- 18 files changed, 79 insertions(+), 89 deletions(-) diff --git a/src/config.hpp b/src/config.hpp index 46bf7a3f831..f751b6abf50 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -42,6 +42,7 @@ typedef std::map string_map; class config; +class vconfig; struct lua_State; bool operator==(const config &, const config &); @@ -202,6 +203,7 @@ public: friend std::ostream& operator<<(std::ostream &os, const attribute_value &v); friend void luaW_pushscalar(lua_State *, const attribute_value &); friend void write_key_val(std::ostream &, const std::string &, const attribute_value &, unsigned, std::string &); + friend class vconfig; }; typedef std::map attribute_map; @@ -482,4 +484,11 @@ private: std::vector ordered_children; }; +class variable_set +{ +public: + virtual ~variable_set() {} + virtual config::attribute_value get_variable_const(const std::string &id) const = 0; +}; + #endif diff --git a/src/formula_string_utils.cpp b/src/formula_string_utils.cpp index 237234ad277..12773549674 100644 --- a/src/formula_string_utils.cpp +++ b/src/formula_string_utils.cpp @@ -30,15 +30,14 @@ class string_map_variable_set : public variable_set public: string_map_variable_set(const string_map& map) : map_(map) {}; - virtual t_string get_variable_const (const std::string& key) const + virtual config::attribute_value get_variable_const(const std::string &key) const { + config::attribute_value val; const string_map::const_iterator itor = map_.find(key); - if (itor == map_.end()) { - return t_string(); - } else { - return itor->second; - } - }; + if (itor != map_.end()) + val = itor->second; + return val; + } private: const string_map& map_; diff --git a/src/formula_string_utils.hpp b/src/formula_string_utils.hpp index 8af6ecce65b..523fb6d1954 100644 --- a/src/formula_string_utils.hpp +++ b/src/formula_string_utils.hpp @@ -17,6 +17,7 @@ #define FORMULA_STRING_UTILS_HPP_INCLUDED #include "serialization/string_utils.hpp" +#include "config.hpp" namespace utils { diff --git a/src/game_events.cpp b/src/game_events.cpp index 7f38215003f..dfd6f6cc46c 100644 --- a/src/game_events.cpp +++ b/src/game_events.cpp @@ -408,20 +408,19 @@ namespace game_events { foreach (const vconfig &values, variables) { const std::string name = values["name"]; - std::string value = resources::state_of_game->get_variable_const(name); - - const double num_value = atof(value.c_str()); + config::attribute_value value = resources::state_of_game->get_variable_const(name); + double num_value = value.to_double(); #define TEST_STR_ATTR(name, test) do { \ if (values.has_attribute(name)) { \ - std::string attr_str = values[name].str(); \ + config::attribute_value attr_str = values[name]; \ if (!(test)) return false; \ } \ } while (0) #define TEST_NUM_ATTR(name, test) do { \ if (values.has_attribute(name)) { \ - double attr_num = atof(values[name].c_str()); \ + double attr_num = values[name].to_double(); \ if (!(test)) return false; \ } \ } while (0) @@ -434,11 +433,9 @@ namespace game_events { TEST_NUM_ATTR("less_than", num_value < attr_num); TEST_NUM_ATTR("greater_than_equal_to", num_value >= attr_num); TEST_NUM_ATTR("less_than_equal_to", num_value <= attr_num); - TEST_STR_ATTR("boolean_equals", - utils::string_bool(value) == utils::string_bool(attr_str)); - TEST_STR_ATTR("boolean_not_equals", - utils::string_bool(value) != utils::string_bool(attr_str)); - TEST_STR_ATTR("contains", value.find(attr_str) != std::string::npos); + TEST_STR_ATTR("boolean_equals", value == attr_str); + TEST_STR_ATTR("boolean_not_equals", value != attr_str); + TEST_STR_ATTR("contains", value.str().find(attr_str.str()) != std::string::npos); #undef TEST_STR_ATTR #undef TEST_NUM_ATTR @@ -1805,7 +1802,7 @@ WML_HANDLER_FUNCTION(object, event_info, cfg) if (u != resources::units->end() && (filter.null() || game_events::unit_matches_filter(*u, filter))) { - text = cfg["description"]; + text = cfg["description"].str(); u->add_modification("object", cfg.get_parsed_config()); @@ -1815,7 +1812,7 @@ WML_HANDLER_FUNCTION(object, event_info, cfg) // Mark this item as used up. used_items.insert(id); } else { - text = cfg["cannot_use_message"]; + text = cfg["cannot_use_message"].str(); command_type = "else"; } @@ -2038,13 +2035,13 @@ WML_HANDLER_FUNCTION(set_menu_item, /*event_info*/, cfg) mref = new wml_menu_item(id); } if(cfg.has_attribute("image")) { - mref->image = cfg["image"]; + mref->image = cfg["image"].str(); } if(cfg.has_attribute("description")) { mref->description = cfg["description"]; } if(cfg.has_attribute("needs_select")) { - mref->needs_select = utils::string_bool(cfg["needs_select"], false); + mref->needs_select = cfg["needs_select"].to_bool(); } if(cfg.has_child("show_if")) { mref->show_if = cfg.child("show_if").get_config(); @@ -2308,7 +2305,7 @@ WML_HANDLER_FUNCTION(endlevel, /*event_info*/, cfg) end_level_data &data = resources::controller->get_end_level_data(); std::string result = cfg["result"]; - data.custom_endlevel_music = cfg["music"]; + data.custom_endlevel_music = cfg["music"].str(); data.carryover_report = utils::string_bool(cfg["carryover_report"], true); data.prescenario_save = utils::string_bool(cfg["save"], true); data.linger_mode = utils::string_bool(cfg["linger_mode"], true) @@ -2542,7 +2539,7 @@ std::string get_image(const vconfig& cfg, unit_map::iterator speaker) image::locator locator(image); if(!locator.file_exists()) { - image = cfg["image"]; + image = cfg["image"].str(); } } return image; diff --git a/src/gamestatus.cpp b/src/gamestatus.cpp index 392fa9cab82..8c04bdd9130 100644 --- a/src/gamestatus.cpp +++ b/src/gamestatus.cpp @@ -475,16 +475,17 @@ config::attribute_value &game_state::get_variable(const std::string& key) return variable_info(key, true, variable_info::TYPE_SCALAR).as_scalar(); } -t_string game_state::get_variable_const(const std::string& key) const +config::attribute_value game_state::get_variable_const(const std::string &key) const { variable_info to_get(key, false, variable_info::TYPE_SCALAR); - if(!to_get.is_valid) { - config::attribute_value &to_return = temporaries[key]; - if (key.size() > 7 && key.substr(key.size()-7) == ".length") { - // length is a special attribute, so guarantee its correctness - to_return = "0"; - } - return to_return; + if (!to_get.is_valid) + { + config::attribute_value &to_return = temporaries[key]; + if (key.size() > 7 && key.substr(key.size() - 7) == ".length") { + // length is a special attribute, so guarantee its correctness + to_return = 0; + } + return to_return; } return to_get.as_scalar(); } diff --git a/src/gamestatus.hpp b/src/gamestatus.hpp index b5949d2ff43..57995c7b7a2 100644 --- a/src/gamestatus.hpp +++ b/src/gamestatus.hpp @@ -103,7 +103,7 @@ public: // Variable access config::attribute_value &get_variable(const std::string &varname); - virtual t_string get_variable_const(const std::string& varname) const; + virtual config::attribute_value get_variable_const(const std::string& varname) const; config& get_variable_cfg(const std::string& varname); void set_variable(const std::string& varname, const t_string& value); diff --git a/src/gui/auxiliary/formula.hpp b/src/gui/auxiliary/formula.hpp index f5c6b9330d2..1c1fd16022d 100644 --- a/src/gui/auxiliary/formula.hpp +++ b/src/gui/auxiliary/formula.hpp @@ -20,6 +20,7 @@ #include "gui/widgets/helper.hpp" #include "serialization/string_utils.hpp" #include "util.hpp" +#include "tstring.hpp" #include diff --git a/src/gui/dialogs/gamestate_inspector.cpp b/src/gui/dialogs/gamestate_inspector.cpp index 8708b615639..2b649424c07 100644 --- a/src/gui/dialogs/gamestate_inspector.cpp +++ b/src/gui/dialogs/gamestate_inspector.cpp @@ -79,7 +79,7 @@ public: model(const vconfig &c) : cfg(c), name(), stuff_list(),stuff_types_list(),inspect(),inspector_name() { - name = cfg["name"]; + name = cfg["name"].str(); } vconfig cfg; diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index 29e22aa1905..48919e30927 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -165,32 +165,6 @@ void luaW_pushscalar(lua_State *L, config::attribute_value const &v) boost::apply_visitor(luaW_pushscalar_visitor(L), v.value); } -/** - * Converts a string into a Lua object pushed at the top of the stack. - * Boolean ("yes"/"no") and numbers are detected and typed accordingly. - */ -static void luaW_pushscalar(lua_State *L, t_string const &v) -{ - if (!v.translatable()) - { - char *pe; - char const *pb = v.c_str(); - double d = strtod(v.c_str(), &pe); - if (pe != pb && *pe == '\0') - lua_pushnumber(L, d); - else if (v == "yes") - lua_pushboolean(L, true); - else if (v == "no") - lua_pushboolean(L, false); - else - lua_pushstring(L, pb); - } - else - { - luaW_pushtstring(L, v); - } -} - /** * Returns true if the metatable of the object is the one found in the registry. */ diff --git a/src/serialization/preprocessor.cpp b/src/serialization/preprocessor.cpp index 168edd60066..dcb6c828f32 100644 --- a/src/serialization/preprocessor.cpp +++ b/src/serialization/preprocessor.cpp @@ -335,7 +335,7 @@ std::string lineno_string(const std::string &lineno) void preprocessor_streambuf::error(const std::string& error_type, int l) { - utils::string_map i18n_symbols; + string_map i18n_symbols; std::string position, error; std::ostringstream pos; pos << l << ' ' << location_; diff --git a/src/serialization/string_utils.cpp b/src/serialization/string_utils.cpp index 6979cc75478..3429ca163f3 100644 --- a/src/serialization/string_utils.cpp +++ b/src/serialization/string_utils.cpp @@ -30,10 +30,6 @@ static lg::log_domain log_engine("engine"); #define ERR_GENERAL LOG_STREAM(err, lg::general) #define ERR_NG LOG_STREAM(err, log_engine) -variable_set::~variable_set() -{ -} - namespace utils { bool isnewline(const char c) diff --git a/src/serialization/string_utils.hpp b/src/serialization/string_utils.hpp index b4ea2495b97..5fede712a1d 100644 --- a/src/serialization/string_utils.hpp +++ b/src/serialization/string_utils.hpp @@ -24,18 +24,9 @@ #include #include #include -#include "../tstring.hpp" #include "SDL_types.h" -class variable_set -{ -public: - virtual ~variable_set(); - - virtual t_string get_variable_const(const std::string& id) const = 0; -}; - /** The type we use to represent Unicode strings. */ typedef std::vector wide_string; @@ -44,6 +35,8 @@ typedef std::vector ucs2_string; typedef std::vector ucs4_string; typedef std::string utf8_string; +class t_string; + namespace utils { const std::string unicode_minus = "−"; diff --git a/src/storyscreen/part.cpp b/src/storyscreen/part.cpp index 548b0747a57..f2743834448 100644 --- a/src/storyscreen/part.cpp +++ b/src/storyscreen/part.cpp @@ -142,19 +142,19 @@ void part::resolve_wml(const vconfig &cfg) } if(cfg.has_attribute("background")) { - background_file_ = cfg["background"]; + background_file_ = cfg["background"].str(); } if(cfg.has_attribute("scale_background")) { - scale_background_ = utils::string_bool(cfg["scale_background"], true); + scale_background_ = cfg["scale_background"].to_bool(true); } if(cfg.has_attribute("show_title")) { - show_title_ = utils::string_bool(cfg["show_title"]); + show_title_ = cfg["show_title"].to_bool(); } if(cfg.has_attribute("story")) { - text_ = cfg["story"]; + text_ = cfg["story"].str(); } if(cfg.has_attribute("title")) { - text_title_ = cfg["title"]; + text_title_ = cfg["title"].str(); if(!cfg.has_attribute("show_title")) { show_title_ = true; } @@ -166,10 +166,10 @@ void part::resolve_wml(const vconfig &cfg) title_alignment_ = string_title_align(cfg["title_alignment"]); } if(cfg.has_attribute("music")) { - music_ = cfg["music"]; + music_ = cfg["music"].str(); } if(cfg.has_attribute("sound")) { - sound_ = cfg["sound"]; + sound_ = cfg["sound"].str(); } // Execution flow/branching/[image] diff --git a/src/text.cpp b/src/text.cpp index d57efdf87e4..b6ba773f89c 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -21,6 +21,7 @@ #include "gui/auxiliary/log.hpp" #include "font.hpp" #include "serialization/string_utils.hpp" +#include "tstring.hpp" #include #include diff --git a/src/unit.cpp b/src/unit.cpp index e60825dbceb..2d379cdf4f2 100644 --- a/src/unit.cpp +++ b/src/unit.cpp @@ -1496,7 +1496,7 @@ bool unit::internal_matches_filter(const vconfig& cfg, const map_location& loc, if (cfg.has_attribute("lua_function")) { bool b = resources::lua_kernel->run_filter - (cfg["lua_function"].c_str(), *this); + (cfg["lua_function"].str().c_str(), *this); if (!b) return false; } diff --git a/src/unit_display.cpp b/src/unit_display.cpp index ffe176ea78f..49a30f9b722 100644 --- a/src/unit_display.cpp +++ b/src/unit_display.cpp @@ -557,7 +557,7 @@ void wml_animation_internal(unit_animator &animator, const vconfig &cfg, const m if(cfg["red"].empty() && cfg["green"].empty() && cfg["blue"].empty()) { text_color = display::rgb(0xff,0xff,0xff); } else { - text_color = display::rgb(atoi(cfg["red"].c_str()),atoi(cfg["green"].c_str()),atoi(cfg["blue"].c_str())); + text_color = display::rgb(cfg["red"], cfg["green"], cfg["blue"]); } resources::screen->scroll_to_tile(u->get_location(), game_display::ONSCREEN, true, false); vconfig t_filter = cfg.child("facing"); diff --git a/src/variable.cpp b/src/variable.cpp index e148bab7efc..c092d2b78da 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -32,6 +32,8 @@ #include "unit_map.hpp" #include "team.hpp" +#include + static lg::log_domain log_engine("engine"); #define LOG_NG LOG_STREAM(info, log_engine) #define WRN_NG LOG_STREAM(warn, log_engine) @@ -346,12 +348,27 @@ bool vconfig::has_child(const std::string& key) const return false; } -const t_string vconfig::expand(const std::string& key) const +struct vconfig_expand_visitor : boost::static_visitor { - const t_string& val = (*cfg_)[key]; - if(repos != NULL) - return utils::interpolate_variables_into_tstring(val, *repos); - return t_string(val); + config::attribute_value &result; + vconfig_expand_visitor(config::attribute_value &r): result(r) {} + template void operator()(T const &) const {} + void operator()(const std::string &s) const + { + result = utils::interpolate_variables_into_string(s, *repos); + } + void operator()(const t_string &s) const + { + result = utils::interpolate_variables_into_tstring(s, *repos); + } +}; + +config::attribute_value vconfig::expand(const std::string &key) const +{ + config::attribute_value val = (*cfg_)[key]; + if (repos) + boost::apply_visitor(vconfig_expand_visitor(val), val.value); + return val; } vconfig::all_children_iterator::all_children_iterator(const Itor &i, const config *cache_key) diff --git a/src/variable.hpp b/src/variable.hpp index 9c27b26e741..7517ea71063 100644 --- a/src/variable.hpp +++ b/src/variable.hpp @@ -69,8 +69,9 @@ public: * lifetime ends which causes UB. Instead use: * const std::string temp = vcfg["foo"]; */ - const t_string operator[](const std::string& key) const { return expand(key); } - const t_string expand(const std::string&) const; /** < Synonym for operator[] */ + const config::attribute_value operator[](const std::string &key) const + { return expand(key); } + config::attribute_value expand(const std::string&) const; /** < Synonym for operator[] */ bool has_attribute(const std::string& key) const { return cfg_->has_attribute(key); } bool empty() const { return (null() || cfg_->empty()); }