Skip to content

Commit

Permalink
move variable_info to own file
Browse files Browse the repository at this point in the history
and also move game_data::temporarites_ to that file as a static
variable.

This fixes variable_info being dependent on game_data.
  • Loading branch information
gfgtdf committed Jun 29, 2014
1 parent 16938d3 commit 5d3040c
Show file tree
Hide file tree
Showing 8 changed files with 266 additions and 209 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Expand Up @@ -905,6 +905,7 @@ set(wesnoth-main_SRC
unit_types.cpp
utils/sha1.cpp
variable.cpp
variable_info.cpp
variant.cpp
whiteboard/action.cpp
whiteboard/attack.cpp
Expand Down
1 change: 1 addition & 0 deletions src/SConscript
Expand Up @@ -537,6 +537,7 @@ wesnoth_sources = Split("""
unit_types.cpp
utils/sha1.cpp
variable.cpp
variable_info.cpp
variant.cpp
whiteboard/action.cpp
whiteboard/attack.cpp
Expand Down
5 changes: 1 addition & 4 deletions src/game_data.cpp
Expand Up @@ -75,7 +75,6 @@ game_data::game_data()
, wml_menu_items_()
, rng_()
, variables_()
, temporaries_()
, phase_(INITIAL)
, can_end_turn_(true)
, scenario_()
Expand All @@ -88,7 +87,6 @@ game_data::game_data(const config& level)
, wml_menu_items_()
, rng_(level)
, variables_(level.child_or_empty("variables"))
, temporaries_()
, phase_(INITIAL)
, can_end_turn_(level["can_end_turn"].to_bool(true))
, scenario_(level["id"])
Expand All @@ -104,7 +102,6 @@ game_data::game_data(const game_data& data)
, wml_menu_items_(data.wml_menu_items_)
, rng_(data.rng_)
, variables_(data.variables_)
, temporaries_()
, phase_(data.phase_)
, can_end_turn_(data.can_end_turn_)
, scenario_(data.scenario_)
Expand All @@ -121,7 +118,7 @@ config::attribute_value game_data::get_variable_const(const std::string &key) co
variable_info to_get = get_variable_access(key, false, variable_info::TYPE_SCALAR);
if (!to_get.is_valid)
{
config::attribute_value &to_return = temporaries_[key];
config::attribute_value &to_return = variable_info::get_temporaries()[key];
if (key.size() > 7 && key.substr(key.size() - 7) == ".length") {
// length is a special attribute, so guarantee its correctness
to_return = 0;
Expand Down
3 changes: 1 addition & 2 deletions src/game_data.hpp
Expand Up @@ -22,7 +22,7 @@
#include "game_events/wmi_container.hpp"
#include "map_location.hpp"
#include "simple_rng.hpp"
#include "variable.hpp"
#include "variable_info.hpp"

#include <boost/shared_ptr.hpp>

Expand Down Expand Up @@ -117,7 +117,6 @@ class game_data : public variable_set {
game_events::wmi_container wml_menu_items_;
rand_rng::simple_rng rng_;
config variables_;
mutable config temporaries_; // lengths of arrays, etc.
friend struct variable_info;
PHASE phase_;
bool can_end_turn_;
Expand Down
171 changes: 0 additions & 171 deletions src/variable.cpp
Expand Up @@ -443,174 +443,3 @@ void scoped_recall_unit::activate()
}


variable_info::variable_info(config& source, const std::string& varname,
bool force_valid, TYPE validation_type) :
vartype(validation_type),
is_valid(false),
key(),
explicit_index(false),
index(0),
vars(NULL)
{

vars = &source;//&resources::gamedata->variables_;
key = varname;
std::string::const_iterator itor = std::find(key.begin(),key.end(),'.');
int dot_index = key.find('.');

bool force_length = false;
// example varname = "unit_store.modifications.trait[0]"
while(itor != key.end()) { // subvar access
std::string element=key.substr(0,dot_index);
key = key.substr(dot_index+1);

size_t inner_index = 0;
const std::string::iterator index_start = std::find(element.begin(),element.end(),'[');
const bool inner_explicit_index = index_start != element.end();
if(inner_explicit_index) {
const std::string::iterator index_end = std::find(index_start,element.end(),']');
const std::string index_str(index_start+1,index_end);
inner_index = static_cast<size_t>(lexical_cast_default<int>(index_str));
if(inner_index > game_config::max_loop) {
ERR_NG << "variable_info: index greater than " << game_config::max_loop
<< ", truncated\n";
inner_index = game_config::max_loop;
}
element = std::string(element.begin(),index_start);
}

size_t size = vars->child_count(element);
if(size <= inner_index) {
if(force_valid) {
// Add elements to the array until the requested size is attained
if(inner_explicit_index || key != "length") {
for(; size <= inner_index; ++size) {
vars->add_child(element);
}
}
} else if(inner_explicit_index) {
WRN_NG << "variable_info: invalid WML array index, "
<< varname << std::endl;
return;
} else if(varname.length() >= 7 && varname.substr(varname.length()-7) == ".length") {
// require '.' to avoid matching suffixes -> requires varname over key to always find length
// return length 0 for non-existent WML array (handled below)
force_length = true;
} else {
WRN_NG << "variable_info: retrieving member of non-existent WML container, "
<< varname << std::endl;
return;
}
}
if((!inner_explicit_index && key == "length") || force_length) {
switch(vartype) {
case variable_info::TYPE_ARRAY:
case variable_info::TYPE_CONTAINER:
WRN_NG << "variable_info: using reserved WML variable as wrong type, "
<< varname << std::endl;
is_valid = force_valid || resources::gamedata->temporaries_.child(varname);
break;
case variable_info::TYPE_SCALAR:
default:
// Store the length of the array as a temporary variable
resources::gamedata->temporaries_[varname] = int(size);
is_valid = true;
break;
}
key = varname;
vars = &resources::gamedata->temporaries_;
return;
}

vars = &vars->child(element, inner_index);
itor = std::find(key.begin(),key.end(),'.');
dot_index = key.find('.');
} // end subvar access

const std::string::iterator index_start = std::find(key.begin(),key.end(),'[');
explicit_index = index_start != key.end();
if(explicit_index) {
const std::string::iterator index_end = std::find(index_start,key.end(),']');
const std::string index_str(index_start+1,index_end);
index = static_cast<size_t>(lexical_cast_default<int>(index_str));
if(index > game_config::max_loop) {
ERR_NG << "variable_info: index greater than " << game_config::max_loop
<< ", truncated\n";
index = game_config::max_loop;
}
key = std::string(key.begin(),index_start);
size_t size = vars->child_count(key);
if(size <= index) {
if(!force_valid) {
WRN_NG << "variable_info: invalid WML array index, " << varname << std::endl;
return;
}
for(; size <= index; ++size) {
vars->add_child(key);
}
}
switch(vartype) {
case variable_info::TYPE_ARRAY:
vars = &vars->child(key, index);
key = "__array";
is_valid = force_valid || vars->child(key);
break;
case variable_info::TYPE_SCALAR:
vars = &vars->child(key, index);
key = "__value";
is_valid = force_valid || vars->has_attribute(key);
break;
case variable_info::TYPE_CONTAINER:
case variable_info::TYPE_UNSPECIFIED:
default:
is_valid = true;
return;
}
if (force_valid) {
WRN_NG << "variable_info: using explicitly indexed "
"container as wrong WML type, " << varname << '\n';
}
explicit_index = false;
index = 0;
} else {
// Final variable is not an explicit index [...]
switch(vartype) {
case variable_info::TYPE_ARRAY:
case variable_info::TYPE_CONTAINER:
is_valid = force_valid || vars->child(key);
break;
case variable_info::TYPE_SCALAR:
is_valid = force_valid || vars->has_attribute(key);
break;
case variable_info::TYPE_UNSPECIFIED:
default:
is_valid = true;
break;
}
}
}

config::attribute_value &variable_info::as_scalar()
{
assert(is_valid);
return (*vars)[key];
}

config& variable_info::as_container() {
assert(is_valid);
if(explicit_index) {
// Empty data for explicit index was already created if it was needed
return vars->child(key, index);
}
if (config &temp = vars->child(key)) {
// The container exists, index not specified, return index 0
return temp;
}
// Add empty data for the new variable, since it does not exist yet
return vars->add_child(key);
}

variable_info::array_range variable_info::as_array() {
assert(is_valid);
return vars->child_range(key);
}
32 changes: 0 additions & 32 deletions src/variable.hpp
Expand Up @@ -209,36 +209,4 @@ class scoped_recall_unit : public scoped_wml_variable
unsigned int recall_index_;
};

/** Information on a WML variable. */
struct variable_info
{
typedef config::child_itors array_range;

/**
* TYPE: the correct variable type should be decided by the user of the info structure
* Note: an Array can also be considered a Container, since index 0 will be used by default
*/
enum TYPE { TYPE_SCALAR, //a Scalar variable resolves to a t_string attribute of *vars
TYPE_ARRAY, //an Array variable is a series of Containers
TYPE_CONTAINER, //a Container is a specific index of an Array (contains Scalars)
TYPE_UNSPECIFIED };

variable_info(config& source, const std::string& varname, bool force_valid=true,
TYPE validation_type=TYPE_UNSPECIFIED);

TYPE vartype; //default is TYPE_UNSPECIFIED
bool is_valid;
std::string key; //the name of the internal attribute or child
bool explicit_index; //true if query ended in [...] specifier
size_t index; //the index of the child
config *vars; //the containing node in game_data s variables
/**
* Results: after deciding the desired type, these methods can retrieve the result
* Note: first you should force_valid or check is_valid, otherwise these may fail
*/
config::attribute_value &as_scalar();
config& as_container();
array_range as_array(); //range may be empty
};

#endif

0 comments on commit 5d3040c

Please sign in to comment.