Skip to content

Commit

Permalink
attempt to fix server crashes with ordered simple_wml
Browse files Browse the repository at this point in the history
  • Loading branch information
davewx7 committed Jan 20, 2009
1 parent b5dd70e commit 2f95e5b
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 1 deletion.
61 changes: 60 additions & 1 deletion src/server/simple_wml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,13 @@ node::node(document& doc, node* parent, const char** str, int depth) :
}

const int list_index = get_children(string_span(s, end - s));
check_ordered_children();

s = end + 1;

children_[list_index].second.push_back(new node(doc, this, str, depth+1));
ordered_children_.push_back(node_pos(list_index, children_[list_index].second.size() - 1));
check_ordered_children();

break;
}
Expand Down Expand Up @@ -246,6 +248,7 @@ node::node(document& doc, node* parent, const char** str, int depth) :
}

output_cache_ = string_span(begin, s - begin);
check_ordered_children();
}

node::~node()
Expand Down Expand Up @@ -346,8 +349,19 @@ node& node::add_child_at(const char* name, size_t index)
index = list.size();
}

fprintf(stderr, "add child at: %d, %d\n", list_index, index);
for(int n = 0; n != ordered_children_.size(); ++n) {
fprintf(stderr, "ordered child: %d, %d\n", ordered_children_[n].child_map_index, ordered_children_[n].child_list_index);
}

check_ordered_children();
list.insert(list.begin() + index, new node(*doc_, this));
insert_ordered_child(list_index, index);
fprintf(stderr, "done add child at: %d, %d\n", list_index, index);
for(int n = 0; n != ordered_children_.size(); ++n) {
fprintf(stderr, "ordered child: %d, %d\n", ordered_children_[n].child_map_index, ordered_children_[n].child_list_index);
}
check_ordered_children();
return *list[index];
}

Expand All @@ -357,9 +371,11 @@ node& node::add_child(const char* name)
set_dirty();

const int list_index = get_children(name);
check_ordered_children();
child_list& list = children_[list_index].second;
list.push_back(new node(*doc_, this));
ordered_children_.push_back(node_pos(list_index, list.size() - 1));
check_ordered_children();
return *list.back();
}

Expand Down Expand Up @@ -391,19 +407,24 @@ void node::remove_child(const string_span& name, size_t index)

void node::insert_ordered_child(int child_map_index, int child_list_index)
{

bool inserted = false;
std::vector<node_pos>::iterator i = ordered_children_.begin();
while(i != ordered_children_.end()) {
if(i->child_map_index == child_map_index && i->child_list_index > child_list_index) {
i->child_list_index++;
} else if(i->child_map_index == child_map_index && i->child_list_index == child_list_index) {
inserted = true;
i->child_list_index++;
i = ordered_children_.insert(i, node_pos(child_map_index, child_list_index));
++i;
}

++i;
}

if(!inserted) {
ordered_children_.push_back(node_pos(child_map_index, child_list_index));
}
}

void node::remove_ordered_child(int child_map_index, int child_list_index)
Expand All @@ -425,6 +446,16 @@ void node::remove_ordered_child(int child_map_index, int child_list_index)
assert(erase_count == 1);
}

void node::insert_ordered_child_list(int child_map_index)
{
std::vector<node_pos>::iterator i = ordered_children_.begin();
while(i != ordered_children_.end()) {
if(i->child_map_index >= child_map_index) {
i->child_map_index++;
}
}
}

void node::remove_ordered_child_list(int child_map_index)
{
std::vector<node_pos>::iterator i = ordered_children_.begin();
Expand All @@ -442,6 +473,33 @@ void node::remove_ordered_child_list(int child_map_index)
}
}

void node::check_ordered_children() const
{
std::vector<node_pos>::const_iterator i = ordered_children_.begin();
while(i != ordered_children_.end()) {
assert(i->child_map_index < children_.size());
assert(i->child_list_index < children_[i->child_map_index].second.size());
++i;
}

for(child_map::const_iterator j = children_.begin(); j != children_.end(); ++j) {
const unsigned short child_map_index = j - children_.begin();
for(child_list::const_iterator k = j->second.begin(); k != j->second.end(); ++k) {
const unsigned short child_list_index = k - j->second.begin();
bool found = false;
for(int n = 0; n != ordered_children_.size(); ++n) {
if(ordered_children_[n].child_map_index == child_map_index &&
ordered_children_[n].child_list_index == child_list_index) {
found = true;
break;
}
}

assert(found);
}
}
}

void node::remove_child(const char* name, size_t index)
{
remove_child(string_span(name), index);
Expand Down Expand Up @@ -539,6 +597,7 @@ const string_span& node::first_child() const

int node::output_size() const
{
check_ordered_children();
if(output_cache_.empty() == false) {
return output_cache_.size();
}
Expand Down
17 changes: 17 additions & 0 deletions src/server/simple_wml.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,23 @@ class node

bool has_attr(const char* key) const;

//sets an attribute in the WML node. The node will keep a direct reference
//to key and value which it will maintain for its lifetime. The caller
//MUST guarantee that the key and value buffers remain valid for the
//lifetime of the node.
node& set_attr(const char* key, const char* value);

//functions which are identical to set_attr() except that the buffer
//referred to by 'value' will be duplicated and the new buffer managed by
//the node. The caller may destroy the value buffer as soon as the function
//returns. The key buffer must remain valid for the lifetime of the node.
node& set_attr_dup(const char* key, const char* value);
node& set_attr_dup(const char* key, const string_span& value);

//sets an attribute with identical behavior to set_attr_dup, except that
//the buffer referred to by 'key' will also be duplicated and managed by
//the node. The caller may destroy both key and value as soon as the
//call returns.
node& set_attr_dup_key_and_value(const char* key, const char* value);

node& set_attr_int(const char* key, int value);
Expand Down Expand Up @@ -179,8 +193,11 @@ class node

void insert_ordered_child(int child_map_index, int child_list_index);
void remove_ordered_child(int child_map_index, int child_list_index);
void insert_ordered_child_list(int child_map_index);
void remove_ordered_child_list(int child_map_index);

void check_ordered_children() const;

string_span output_cache_;
};

Expand Down

0 comments on commit 2f95e5b

Please sign in to comment.