A more correct fix for bug #10152
Also fixed a bug with removing abilities Added some utility functions related to config iteration Code cleanup
This commit is contained in:
parent
689fe4bad4
commit
421158867b
3 changed files with 70 additions and 52 deletions
|
@ -209,6 +209,32 @@ void config::clear_children(const std::string& key)
|
|||
}
|
||||
}
|
||||
|
||||
config::all_children_iterator config::erase(const config::all_children_iterator& i)
|
||||
{
|
||||
config* found_config = NULL;
|
||||
std::vector<child_pos>::iterator erase_pos, j, j_end = ordered_children.end();
|
||||
for(j = ordered_children.begin(); j != j_end; ++j) {
|
||||
if(i.get_key() == j->pos->first) {
|
||||
if(i.get_index() == j->index) {
|
||||
erase_pos = j;
|
||||
found_config = *(j->pos->second.begin() + j->index);
|
||||
} else if(i.get_index() < j->index) {
|
||||
//decrement subsequent child indeces of the same key
|
||||
j->index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
child_list& vec = children[i.get_key()];
|
||||
if(!found_config || erase_pos->index >= vec.size()) {
|
||||
ERR_CF << "Error: attempting to delete non-existing child: "
|
||||
<< i.get_key() << "[" << i.get_index() << "]\n";
|
||||
return ordered_end();
|
||||
}
|
||||
delete found_config;
|
||||
vec.erase(vec.begin()+i.get_index());
|
||||
return all_children_iterator(ordered_children.erase(erase_pos));
|
||||
}
|
||||
|
||||
void config::remove_child(const std::string& key, size_t index)
|
||||
{
|
||||
// Remove from the ordering
|
||||
|
@ -346,6 +372,26 @@ std::pair<const std::string*,const config*> config::all_children_iterator::opera
|
|||
return std::pair<const std::string*,const config*>(&(i_->pos->first),i_->pos->second[i_->index]);
|
||||
}
|
||||
|
||||
config::all_children_iterator::pointer config::all_children_iterator::operator->() const
|
||||
{
|
||||
return pointer(new std::pair<const std::string*,const config*>(&(i_->pos->first),i_->pos->second[i_->index]));
|
||||
}
|
||||
|
||||
const std::string& config::all_children_iterator::get_key() const
|
||||
{
|
||||
return i_->pos->first;
|
||||
}
|
||||
|
||||
const config& config::all_children_iterator::get_child() const
|
||||
{
|
||||
return *(i_->pos->second[i_->index]);
|
||||
}
|
||||
|
||||
size_t config::all_children_iterator::get_index() const
|
||||
{
|
||||
return i_->index;
|
||||
}
|
||||
|
||||
bool config::all_children_iterator::operator==(all_children_iterator i) const
|
||||
{
|
||||
return i_ == i.i_;
|
||||
|
@ -563,36 +609,6 @@ void config::merge_with(const config& c)
|
|||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
// Create a new config tree as a copy of 'this' overridden by 'c'.
|
||||
// Nodes are matched up by name and with name by order.
|
||||
// Nodes in 'c', but not in 'this' are added at the end,
|
||||
// in the order they appeared in 'c'.
|
||||
config config::merge_with(const config& c) const
|
||||
{
|
||||
config n;
|
||||
for(string_map::const_iterator j = this->values.begin();
|
||||
j != this->values.end(); ++j) {
|
||||
n.values[j->first] = j->second;
|
||||
}
|
||||
// This ends up copying values twice (in config initialization
|
||||
// and append), but is simpler than dealing with the guts of m.
|
||||
config m(c);
|
||||
for(all_children_iterator i = this->ordered_begin();
|
||||
i != this->ordered_end(); ++i) {
|
||||
const std::pair<const std::string*,const config*>& value = *i;
|
||||
config *mc = m.child(*value.first);
|
||||
if (mc == NULL) {
|
||||
n.add_child(*value.first, *value.second);
|
||||
}
|
||||
else {
|
||||
n.add_child(*value.first, value.second->merge_with(*mc));
|
||||
m.remove_child(*value.first, 0);
|
||||
}
|
||||
}
|
||||
n.append(m);
|
||||
return n;
|
||||
}*/
|
||||
|
||||
bool config::matches(const config &filter) const
|
||||
{
|
||||
|
|
|
@ -108,15 +108,20 @@ public:
|
|||
typedef std::pair<const std::string*,const config*> value_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef int difference_type;
|
||||
typedef value_type* pointer;
|
||||
typedef std::auto_ptr<value_type> pointer;
|
||||
typedef value_type& reference;
|
||||
typedef std::vector<child_pos>::const_iterator Itor;
|
||||
explicit all_children_iterator(Itor i);
|
||||
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 config& get_child() const;
|
||||
|
||||
bool operator==(all_children_iterator i) const;
|
||||
bool operator!=(all_children_iterator i) const;
|
||||
|
@ -128,6 +133,7 @@ public:
|
|||
//! In-order iteration over all children.
|
||||
all_children_iterator ordered_begin() const;
|
||||
all_children_iterator ordered_end() const;
|
||||
all_children_iterator erase(const all_children_iterator& i);
|
||||
|
||||
//! A function to get the differences between this object,
|
||||
//! and 'c', as another config object.
|
||||
|
|
36
src/unit.cpp
36
src/unit.cpp
|
@ -771,14 +771,12 @@ void unit::remove_ability_by_id(const std::string &ability)
|
|||
{
|
||||
config* abil = cfg_.child("abilities");
|
||||
if(abil) {
|
||||
for(config::child_map::const_iterator i = abil->all_children().begin(); i != abil->all_children().end(); ++i) {
|
||||
int offset = 0;
|
||||
for(config::child_list::const_iterator j = i->second.begin(); j != i->second.end(); ++j, ++offset) {
|
||||
if((**j)["id"] == ability) {
|
||||
abil->remove_child(i->first, offset);
|
||||
return; /* Abilities are unique by id, so we won't find another. */
|
||||
/* Besides, we just wrecked our iterator. Bye. */
|
||||
}
|
||||
config::all_children_iterator i = abil->ordered_begin(), i_end = abil->ordered_end();
|
||||
while(i != i_end) {
|
||||
if(i.get_child()["id"] == ability) {
|
||||
i = abil->erase(i);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2722,23 +2720,21 @@ void unit::add_modification(const std::string& type, const config& mod, bool no_
|
|||
}
|
||||
ab_effect = (**i.first).child("abilities");
|
||||
if (ab_effect) {
|
||||
for(config::child_map::const_iterator j = ab_effect->all_children().begin(); j != ab_effect->all_children().end(); ++j) {
|
||||
config::child_list::const_iterator k = j->second.begin();
|
||||
if(k != j->second.end() && !has_ability_by_id((**k)["id"])) {
|
||||
do {
|
||||
ab->add_child(j->first, **k);
|
||||
} while(++k != j->second.end());
|
||||
config to_append;
|
||||
config::all_children_iterator j, j_end = ab_effect->ordered_end();
|
||||
for(j = ab_effect->ordered_begin(); j != j_end; ++j) {
|
||||
if(!has_ability_by_id(j.get_child()["id"])) {
|
||||
to_append.add_child(j.get_key(), j.get_child());
|
||||
}
|
||||
}
|
||||
ab->append(to_append);
|
||||
}
|
||||
} else if (apply_to == "remove_ability") {
|
||||
config *ab_effect = (**i.first).child("abilities");
|
||||
config *ab = cfg_.child("abilities");
|
||||
if (ab && ab_effect) {
|
||||
for(config::child_map::const_iterator j = ab_effect->all_children().begin(); j != ab_effect->all_children().end(); ++j) {
|
||||
for (config::child_list::const_iterator k = j->second.begin(); k != j->second.end(); ++k) {
|
||||
remove_ability_by_id((**k)["id"]);
|
||||
}
|
||||
if (ab_effect) {
|
||||
config::all_children_iterator j, j_end = ab_effect->ordered_end();
|
||||
for(j = ab_effect->ordered_begin(); j != j_end; ++j) {
|
||||
remove_ability_by_id(j.get_child()["id"]);
|
||||
}
|
||||
}
|
||||
} else if (apply_to == "image_mod") {
|
||||
|
|
Loading…
Add table
Reference in a new issue