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()); }