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:
Patrick Parker 2007-10-16 05:07:42 +00:00
parent 689fe4bad4
commit 421158867b
3 changed files with 70 additions and 52 deletions

View file

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

View file

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

View file

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