new tag [insert_tag], as discussed on wiki/FutureWML
* note: there are ways you can make this crash with bad WML these will be safeguarded against further in a later update
This commit is contained in:
parent
e7a5e57055
commit
1348cf80d2
7 changed files with 239 additions and 49 deletions
|
@ -44,6 +44,7 @@ Version 1.5.0-svn:
|
|||
* Removed Wesbowl
|
||||
* Merged 4p A New Land by Bob_the_Mighty
|
||||
* WML engine:
|
||||
* new tag [insert_tag] to place dynamic WML content
|
||||
* Fixed most C++ probes for boolean WML attributes to use
|
||||
utils::string_bool() rather than true/false or yes/no string comparisons;
|
||||
as a result, they should accept true non-zero values, "on", "yes" or "true"
|
||||
|
|
|
@ -559,10 +559,12 @@ Xu ,Xu , Qxu , Qxu , Ql , Ql
|
|||
[filter]
|
||||
x,y=9,3
|
||||
[/filter]
|
||||
[endlevel]
|
||||
result="victory"
|
||||
bonus=yes
|
||||
[/endlevel]
|
||||
{VARIABLE endlevel_test.result "victory"}
|
||||
{VARIABLE endlevel_test.bonus "yes"}
|
||||
[insert_tag]
|
||||
name=endlevel
|
||||
variable=endlevel_test
|
||||
[/insert_tag]
|
||||
[/event]
|
||||
|
||||
[event]
|
||||
|
|
|
@ -282,12 +282,12 @@ bool conditional_passed(const unit_map* units,
|
|||
|
||||
// Handle [and], [or], and [not] with in-order precedence
|
||||
int or_count = 0;
|
||||
config::all_children_iterator cond_i = cond.get_config().ordered_begin();
|
||||
config::all_children_iterator cond_end = cond.get_config().ordered_end();
|
||||
vconfig::all_children_iterator cond_i = cond.ordered_begin();
|
||||
vconfig::all_children_iterator cond_end = cond.ordered_end();
|
||||
while(cond_i != cond_end)
|
||||
{
|
||||
const std::string& cond_name = *((*cond_i).first);
|
||||
const vconfig cond_filter(&(*((*cond_i).second)));
|
||||
const std::string& cond_name = cond_i.get_key();
|
||||
const vconfig& cond_filter = cond_i.get_child();
|
||||
|
||||
// Handle [and]
|
||||
if(cond_name == "and")
|
||||
|
@ -401,7 +401,7 @@ public:
|
|||
if (!kids.empty())
|
||||
return kids;
|
||||
else
|
||||
return cfg_.get_children("special_filter");
|
||||
return cfg_.get_children("special_filter");
|
||||
|
||||
}
|
||||
|
||||
|
@ -417,7 +417,7 @@ public:
|
|||
if (!kids.empty())
|
||||
return kids;
|
||||
else
|
||||
return cfg_.get_children("special_filter_second");
|
||||
return cfg_.get_children("special_filter_second");
|
||||
}
|
||||
|
||||
bool handle_event(const queued_event& event_info,
|
||||
|
@ -2812,13 +2812,11 @@ bool event_handler::handle_event(const queued_event& event_info, const vconfig c
|
|||
if(cfg.null()) {
|
||||
cfg = cfg_;
|
||||
}
|
||||
for(config::all_children_iterator i = cfg.get_config().ordered_begin();
|
||||
i != cfg.get_config().ordered_end(); ++i) {
|
||||
|
||||
const std::pair<const std::string*,const config*> item = *i;
|
||||
for(vconfig::all_children_iterator i = cfg.ordered_begin();
|
||||
i != cfg.ordered_end(); ++i) {
|
||||
|
||||
//mutated and skip_messages will be modified
|
||||
handle_event_command(event_info, *item.first, vconfig(item.second), mutated, skip_messages);
|
||||
handle_event_command(event_info, i.get_key(), i.get_child(), mutated, skip_messages);
|
||||
}
|
||||
|
||||
// We do this once the event has completed any music alterations
|
||||
|
@ -2940,12 +2938,12 @@ bool matches_special_filter(const config* cfg, const vconfig filter)
|
|||
}
|
||||
|
||||
// Handle [and], [or], and [not] with in-order precedence
|
||||
config::all_children_iterator cond_i = filter.get_config().ordered_begin();
|
||||
config::all_children_iterator cond_end = filter.get_config().ordered_end();
|
||||
vconfig::all_children_iterator cond_i = filter.ordered_begin();
|
||||
vconfig::all_children_iterator cond_end = filter.ordered_end();
|
||||
while(cond_i != cond_end)
|
||||
{
|
||||
const std::string& cond_name = *((*cond_i).first);
|
||||
const vconfig cond_filter(&(*((*cond_i).second)));
|
||||
const std::string& cond_name = cond_i.get_key();
|
||||
const vconfig& cond_filter = cond_i.get_child();
|
||||
|
||||
// Handle [and]
|
||||
if(cond_name == "and")
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#define ERR_NG LOG_STREAM(err, engine)
|
||||
|
||||
|
||||
terrain_filter::terrain_filter(const vconfig& cfg, const gamemap& map,
|
||||
terrain_filter::terrain_filter(const vconfig& cfg, const gamemap& map,
|
||||
const gamestatus& game_status, const unit_map& units, const bool flat_tod,
|
||||
const size_t max_loop) : cfg_(cfg), map_(map), status_(game_status), units_(units)
|
||||
{
|
||||
|
@ -48,12 +48,12 @@ terrain_filter::terrain_filter(const vconfig& cfg, const terrain_filter& origina
|
|||
flatten(original.flat_);
|
||||
}
|
||||
|
||||
terrain_filter::terrain_filter(const terrain_filter& other) :
|
||||
terrain_filter::terrain_filter(const terrain_filter& other) :
|
||||
xy_pred(), // We should construct this too, since it has no datamembers
|
||||
// use the default constructor.
|
||||
cfg_(other.cfg_),
|
||||
map_(other.map_),
|
||||
status_(other.status_),
|
||||
map_(other.map_),
|
||||
status_(other.status_),
|
||||
units_(other.units_)
|
||||
{
|
||||
restrict(other.max_loop_);
|
||||
|
@ -72,8 +72,8 @@ terrain_filter& terrain_filter::operator=(const terrain_filter& other)
|
|||
|
||||
namespace {
|
||||
struct cfg_isor {
|
||||
bool operator() (std::pair<const std::string*,const config*> val) {
|
||||
return *(val.first) == "or";
|
||||
bool operator() (std::pair<const std::string,const vconfig> val) {
|
||||
return val.first == "or";
|
||||
}
|
||||
};
|
||||
} //end anonymous namespace
|
||||
|
@ -177,7 +177,7 @@ bool terrain_filter::match_internal(const gamemap::location& loc, const bool ign
|
|||
}
|
||||
}
|
||||
static std::vector<std::pair<int,int> > default_counts = utils::parse_ranges("1-6");
|
||||
std::vector<std::pair<int,int> > counts = (*i).has_attribute("count")
|
||||
std::vector<std::pair<int,int> > counts = (*i).has_attribute("count")
|
||||
? utils::parse_ranges((*i)["count"]) : default_counts;
|
||||
std::vector<std::pair<int,int> >::const_iterator count, count_end = counts.end();
|
||||
bool count_matches = false;
|
||||
|
@ -278,12 +278,12 @@ bool terrain_filter::match(const gamemap::location& loc)
|
|||
bool matches = match_internal(*i, false);
|
||||
|
||||
//handle [and], [or], and [not] with in-order precedence
|
||||
config::all_children_iterator cond = cfg_.get_config().ordered_begin();
|
||||
config::all_children_iterator cond_end = cfg_.get_config().ordered_end();
|
||||
vconfig::all_children_iterator cond = cfg_.ordered_begin();
|
||||
vconfig::all_children_iterator cond_end = cfg_.ordered_end();
|
||||
while(cond != cond_end)
|
||||
{
|
||||
const std::string& cond_name = *((*cond).first);
|
||||
const vconfig cond_cfg(&(*((*cond).second)));
|
||||
const std::string& cond_name = cond.get_key();
|
||||
const vconfig& cond_cfg = cond.get_child();
|
||||
|
||||
//handle [and]
|
||||
if(cond_name == "and")
|
||||
|
@ -383,8 +383,8 @@ void terrain_filter::get_locations(std::set<gamemap::location>& locs)
|
|||
}
|
||||
|
||||
//handle [and], [or], and [not] with in-order precedence
|
||||
config::all_children_iterator cond = cfg_.get_config().ordered_begin();
|
||||
config::all_children_iterator cond_end = cfg_.get_config().ordered_end();
|
||||
vconfig::all_children_iterator cond = cfg_.ordered_begin();
|
||||
vconfig::all_children_iterator cond_end = cfg_.ordered_end();
|
||||
int ors_left = std::count_if(cond, cond_end, cfg_isor());
|
||||
while(cond != cond_end)
|
||||
{
|
||||
|
@ -393,8 +393,8 @@ void terrain_filter::get_locations(std::set<gamemap::location>& locs)
|
|||
return;
|
||||
}
|
||||
|
||||
const std::string& cond_name = *((*cond).first);
|
||||
const vconfig cond_cfg(&(*((*cond).second)));
|
||||
const std::string& cond_name = cond.get_key();
|
||||
const vconfig& cond_cfg = cond.get_child();
|
||||
|
||||
//handle [and]
|
||||
if(cond_name == "and") {
|
||||
|
|
|
@ -822,13 +822,13 @@ bool unit::matches_filter(const vconfig& cfg, const gamemap::location& loc, bool
|
|||
}
|
||||
|
||||
// Handle [and], [or], and [not] with in-order precedence
|
||||
config::all_children_iterator cond = cfg.get_config().ordered_begin();
|
||||
config::all_children_iterator cond_end = cfg.get_config().ordered_end();
|
||||
vconfig::all_children_iterator cond = cfg.ordered_begin();
|
||||
vconfig::all_children_iterator cond_end = cfg.ordered_end();
|
||||
while(cond != cond_end)
|
||||
{
|
||||
|
||||
const std::string& cond_name = *((*cond).first);
|
||||
const vconfig cond_filter(&(*((*cond).second)));
|
||||
const std::string& cond_name = cond.get_key();
|
||||
const vconfig& cond_filter = cond.get_child();
|
||||
|
||||
// Handle [and]
|
||||
if(cond_name == "and") {
|
||||
|
|
175
src/variable.cpp
175
src/variable.cpp
|
@ -37,24 +37,26 @@ namespace
|
|||
}
|
||||
|
||||
vconfig::vconfig() :
|
||||
cfg_(NULL)
|
||||
cfg_(NULL), volatile_(false)
|
||||
{
|
||||
}
|
||||
|
||||
vconfig::vconfig(const config* cfg) :
|
||||
cfg_(cfg)
|
||||
vconfig::vconfig(const config* cfg, bool is_volatile) :
|
||||
cfg_(cfg), volatile_(is_volatile)
|
||||
{
|
||||
}
|
||||
|
||||
vconfig& vconfig::operator=(const vconfig cfg)
|
||||
{
|
||||
cfg_ = cfg.cfg_;
|
||||
volatile_ = cfg.volatile_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
vconfig& vconfig::operator=(const config* cfg)
|
||||
{
|
||||
cfg_ = cfg;
|
||||
//is volatile? assume current setting
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -69,29 +71,97 @@ const config vconfig::get_parsed_config() const
|
|||
}
|
||||
|
||||
for(config::all_children_iterator child = cfg_->ordered_begin();
|
||||
child != cfg_->ordered_end(); ++child) {
|
||||
child != cfg_->ordered_end(); ++child)
|
||||
{
|
||||
|
||||
res.add_child(*(*child).first, vconfig((*child).second).get_parsed_config());
|
||||
const std::string &child_key = *(*child).first;
|
||||
if(child_key == "insert_tag") {
|
||||
vconfig insert_cfg(child->second);
|
||||
const t_string& name = insert_cfg["name"];
|
||||
variable_info vinfo(insert_cfg["variable"], true, variable_info::TYPE_CONTAINER);
|
||||
if(vinfo.explicit_index) {
|
||||
res.add_child(name, vconfig(&(vinfo.as_container()), true).get_parsed_config());
|
||||
} else {
|
||||
variable_info::array_range range = vinfo.as_array();
|
||||
if(range.first == range.second) {
|
||||
res.add_child(name); //add empty tag
|
||||
}
|
||||
while(range.first != range.second) {
|
||||
res.add_child(name, vconfig(*range.first++, true).get_parsed_config());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res.add_child(child_key, vconfig((*child).second).get_parsed_config());
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
vconfig::child_list vconfig::get_children(const std::string& key) const
|
||||
{
|
||||
const config::child_list& list = cfg_->get_children(key);
|
||||
vconfig::child_list res(list.size());
|
||||
std::copy(list.begin(), list.end(),res.begin());
|
||||
vconfig::child_list res;
|
||||
|
||||
for(config::all_children_iterator child = cfg_->ordered_begin();
|
||||
child != cfg_->ordered_end(); ++child)
|
||||
{
|
||||
const std::string &child_key = *(*child).first;
|
||||
if(child_key == key) {
|
||||
res.push_back(vconfig(child->second, volatile_));
|
||||
} else if(child_key == "insert_tag") {
|
||||
vconfig insert_cfg(child->second);
|
||||
if(insert_cfg["name"] == key) {
|
||||
variable_info vinfo(insert_cfg["variable"], true, variable_info::TYPE_CONTAINER);
|
||||
if(vinfo.explicit_index) {
|
||||
res.push_back(vconfig(&(vinfo.as_container()), true));
|
||||
} else {
|
||||
variable_info::array_range range = vinfo.as_array();
|
||||
if(range.first == range.second) {
|
||||
//push back an empty (volatile) tag
|
||||
res.push_back(vconfig(&(vinfo.as_container()), true));
|
||||
}
|
||||
while(range.first != range.second) {
|
||||
res.push_back(vconfig(*range.first++, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
vconfig vconfig::child(const std::string& key) const
|
||||
{
|
||||
return vconfig(cfg_->child(key));
|
||||
const config *natural = cfg_->child(key);
|
||||
if(natural)
|
||||
{
|
||||
return vconfig(natural, volatile_);
|
||||
}
|
||||
for(config::const_child_itors chitors = cfg_->child_range("insert_tag");
|
||||
chitors.first != chitors.second; ++chitors.first)
|
||||
{
|
||||
vconfig insert_cfg(*chitors.first);
|
||||
if(insert_cfg["name"] == key) {
|
||||
variable_info vinfo(insert_cfg["variable"], true, variable_info::TYPE_CONTAINER);
|
||||
return vconfig(&(vinfo.as_container()), true);
|
||||
}
|
||||
}
|
||||
return vconfig();
|
||||
}
|
||||
|
||||
bool vconfig::has_child(const std::string& key) const
|
||||
{
|
||||
return (cfg_->child(key) != NULL);
|
||||
if(cfg_->child(key) != NULL) {
|
||||
return true;
|
||||
}
|
||||
for(config::const_child_itors chitors = cfg_->child_range("insert_tag");
|
||||
chitors.first != chitors.second; ++chitors.first)
|
||||
{
|
||||
vconfig insert_cfg(*chitors.first);
|
||||
if(insert_cfg["name"] == key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const t_string vconfig::expand(const std::string& key) const
|
||||
|
@ -106,6 +176,91 @@ const t_string vconfig::expand(const std::string& key) const
|
|||
return t_string(val);
|
||||
}
|
||||
|
||||
vconfig::all_children_iterator::all_children_iterator(config::all_children_iterator i)
|
||||
: i_(i), inner_index_(0), index_offset_(0)
|
||||
{
|
||||
}
|
||||
|
||||
vconfig::all_children_iterator& vconfig::all_children_iterator::operator++()
|
||||
{
|
||||
if(i_.get_key() == "insert_tag") {
|
||||
variable_info vinfo(vconfig(&i_.get_child())["variable"], false, variable_info::TYPE_CONTAINER);
|
||||
if(vinfo.is_valid && !vinfo.explicit_index) {
|
||||
variable_info::array_range range = vinfo.as_array();
|
||||
if(range.first != range.second && range.first + (++inner_index_) != range.second) {
|
||||
++index_offset_;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
}
|
||||
++i_;
|
||||
inner_index_ = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
vconfig::all_children_iterator vconfig::all_children_iterator::operator++(int)
|
||||
{
|
||||
vconfig::all_children_iterator i = *this;
|
||||
this->operator++();
|
||||
return i;
|
||||
}
|
||||
|
||||
std::pair<const std::string,const vconfig> vconfig::all_children_iterator::operator*() const
|
||||
{
|
||||
return std::make_pair<const std::string, const vconfig>(get_key(), get_child());
|
||||
}
|
||||
|
||||
vconfig::all_children_iterator::pointer vconfig::all_children_iterator::operator->() const
|
||||
{
|
||||
return pointer(new std::pair<const std::string, const vconfig>(get_key(), get_child()));
|
||||
}
|
||||
|
||||
const std::string vconfig::all_children_iterator::get_key() const
|
||||
{
|
||||
const std::string& key = i_.get_key();
|
||||
if(key == "insert_tag") {
|
||||
return vconfig(&i_.get_child())["name"];
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
const vconfig vconfig::all_children_iterator::get_child() const
|
||||
{
|
||||
if(i_.get_key() == "insert_tag") {
|
||||
variable_info vinfo(vconfig(&i_.get_child())["variable"], true, variable_info::TYPE_CONTAINER);
|
||||
if(inner_index_ == 0) {
|
||||
return vconfig(&vinfo.as_container(), true);
|
||||
}
|
||||
return vconfig(*(vinfo.as_array().first + inner_index_), true);
|
||||
}
|
||||
return vconfig(&i_.get_child());
|
||||
}
|
||||
|
||||
size_t vconfig::all_children_iterator::get_index() const
|
||||
{
|
||||
return i_.get_index() + index_offset_;
|
||||
}
|
||||
|
||||
bool vconfig::all_children_iterator::operator==(all_children_iterator i) const
|
||||
{
|
||||
return (i_ == i.i_ && inner_index_ == i.inner_index_);
|
||||
}
|
||||
|
||||
bool vconfig::all_children_iterator::operator!=(all_children_iterator i) const
|
||||
{
|
||||
return (i_ != i.i_ || inner_index_ != i.inner_index_);
|
||||
}
|
||||
|
||||
vconfig::all_children_iterator vconfig::ordered_begin() const
|
||||
{
|
||||
return all_children_iterator(cfg_->ordered_begin());
|
||||
}
|
||||
|
||||
vconfig::all_children_iterator vconfig::ordered_end() const
|
||||
{
|
||||
return all_children_iterator(cfg_->ordered_end());
|
||||
}
|
||||
|
||||
namespace variable
|
||||
{
|
||||
manager::manager(game_state* repository)
|
||||
|
|
|
@ -33,7 +33,7 @@ class vconfig
|
|||
{
|
||||
public:
|
||||
vconfig();
|
||||
vconfig(const config* cfg);
|
||||
vconfig(const config* cfg, bool is_volatile=false);
|
||||
|
||||
vconfig& operator=(const vconfig cfg);
|
||||
vconfig& operator=(const config* cfg);
|
||||
|
@ -52,9 +52,43 @@ public:
|
|||
const t_string& get_attribute(const std::string& key) const { return (*cfg_)[key]; }
|
||||
bool has_attribute(const std::string& key) const { return cfg_->has_attribute(key); }
|
||||
bool empty() const { return (null() || cfg_->empty()); }
|
||||
bool is_volatile() const { return volatile_; }
|
||||
|
||||
struct all_children_iterator {
|
||||
typedef std::pair<const std::string, const vconfig> value_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef int difference_type;
|
||||
typedef std::auto_ptr<value_type> pointer;
|
||||
typedef value_type& reference;
|
||||
typedef config::all_children_iterator Itor;
|
||||
explicit all_children_iterator(Itor i=Itor());
|
||||
|
||||
all_children_iterator& operator++();
|
||||
all_children_iterator operator++(int);
|
||||
|
||||
value_type operator*() const;
|
||||
pointer operator->() const;
|
||||
|
||||
const std::string get_key() const;
|
||||
size_t get_index() const;
|
||||
const vconfig get_child() const;
|
||||
|
||||
bool operator==(all_children_iterator i) const;
|
||||
bool operator!=(all_children_iterator i) const;
|
||||
|
||||
private:
|
||||
Itor i_;
|
||||
unsigned inner_index_;
|
||||
unsigned index_offset_;
|
||||
};
|
||||
|
||||
//! In-order iteration over all children.
|
||||
all_children_iterator ordered_begin() const;
|
||||
all_children_iterator ordered_end() const;
|
||||
|
||||
private:
|
||||
const config* cfg_;
|
||||
bool volatile_;
|
||||
};
|
||||
|
||||
namespace variable
|
||||
|
|
Loading…
Add table
Reference in a new issue