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.
This commit is contained in:
Guillaume Melquiond 2010-08-19 22:07:53 +00:00
parent 79f2309489
commit ae7cc0a6d2
18 changed files with 79 additions and 89 deletions

View file

@ -42,6 +42,7 @@
typedef std::map<std::string, t_string> 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<std::string, attribute_value> attribute_map;
@ -482,4 +484,11 @@ private:
std::vector<child_pos> ordered_children;
};
class variable_set
{
public:
virtual ~variable_set() {}
virtual config::attribute_value get_variable_const(const std::string &id) const = 0;
};
#endif

View file

@ -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_;

View file

@ -17,6 +17,7 @@
#define FORMULA_STRING_UTILS_HPP_INCLUDED
#include "serialization/string_utils.hpp"
#include "config.hpp"
namespace utils {

View file

@ -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;

View file

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

View file

@ -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);

View file

@ -20,6 +20,7 @@
#include "gui/widgets/helper.hpp"
#include "serialization/string_utils.hpp"
#include "util.hpp"
#include "tstring.hpp"
#include <boost/static_assert.hpp>

View file

@ -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;

View file

@ -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.
*/

View file

@ -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_;

View file

@ -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)

View file

@ -24,18 +24,9 @@
#include <string>
#include <vector>
#include <boost/next_prior.hpp>
#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<wchar_t> wide_string;
@ -44,6 +35,8 @@ typedef std::vector<Uint16> ucs2_string;
typedef std::vector<Uint32> ucs4_string;
typedef std::string utf8_string;
class t_string;
namespace utils {
const std::string unicode_minus = "";

View file

@ -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]

View file

@ -21,6 +21,7 @@
#include "gui/auxiliary/log.hpp"
#include "font.hpp"
#include "serialization/string_utils.hpp"
#include "tstring.hpp"
#include <cassert>
#include <cstring>

View file

@ -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;
}

View file

@ -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");

View file

@ -32,6 +32,8 @@
#include "unit_map.hpp"
#include "team.hpp"
#include <boost/variant.hpp>
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<void>
{
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<typename T> 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)

View file

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