// returns a variable_access that cannot be used to change the game variables variable_access_create get_variable_access_write(const std::string& varname) { assert(this != NULL); activate_scope_variable(varname); return variable_access_create(varname, variables_); }
///Used to delete variables. variable_access_throw get_variable_access_throw(const std::string& varname) { activate_scope_variable(varname); return variable_access_throw(varname, variables_); }
// returns a variable_access that cannot be used to change the game variables variable_access_const get_variable_access_read(const std::string& varname) const { assert(this != NULL); activate_scope_variable(varname); return variable_access_const(varname, variables_); }
variable_info::variable_info(const std::string& varname, bool force_valid, TYPE validation_type) : vartype(validation_type), is_valid(false), key(), explicit_index(false), index(0), vars(NULL) { assert(repos != NULL); activate_scope_variable(varname); vars = &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; } } }