Skip to content

Commit

Permalink
Xml_generator: fix exception handling in Node(...)
Browse files Browse the repository at this point in the history
When the functor provided to the Node constructor throws an exception,
do revert all changes in reverse order. Previously, the changes made
to the parent node were not considered by the exception handler which
caused unnecessary characters to remain in the out buffer for each
reverted node.

Issue genodelabs#2967
  • Loading branch information
m-stein committed Sep 16, 2018
1 parent f4ef0c2 commit df13c6b
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 6 deletions.
30 changes: 28 additions & 2 deletions repos/base/include/util/xml_generator.h
Expand Up @@ -60,6 +60,9 @@ class Genode::Xml_generator
_used += len;
}

void undo_append(size_t const len) {
_used = len < _used ? _used - len : 0; }

/**
* Append character
*/
Expand Down Expand Up @@ -162,6 +165,8 @@ class Genode::Xml_generator
unsigned const _indent_level;

Node * const _parent_node = 0;
bool const _parent_was_indented;
bool const _parent_had_content;

Out_buffer _out_buffer;

Expand Down Expand Up @@ -197,6 +202,20 @@ class Genode::Xml_generator
return _out_buffer.remainder();
}

void _undo_content_buffer(bool indented,
bool was_indented,
bool had_content)
{
_is_indented = was_indented;
_has_content = had_content;

if (indented)
_out_buffer.undo_append(1);

if (!_has_content)
_out_buffer.undo_append(1);
}

/**
* Called by sub node
*/
Expand All @@ -217,7 +236,7 @@ class Genode::Xml_generator
dst.append(name);
dst.append("=\"");
dst.append(value, strlen(value));
dst.append("\"");
dst.append('\"');

_attr_offset += gap;
}
Expand All @@ -241,6 +260,8 @@ class Genode::Xml_generator
:
_indent_level(xml._curr_indent),
_parent_node(xml._curr_node),
_parent_was_indented(_parent_node ? _parent_node->is_indented() : false),
_parent_had_content (_parent_node ? _parent_node->has_content() : false),
_out_buffer(_parent_node ? _parent_node->_content_buffer(true)
: xml._out_buffer)
{
Expand All @@ -259,8 +280,10 @@ class Genode::Xml_generator
func();
} catch (...) {
/* reset and drop changes by not committing it */
xml._curr_node = _parent_node;
xml._curr_indent--;
xml._curr_node = _parent_node;
if (_parent_node) {
_parent_node->_undo_content_buffer(true, _parent_was_indented, _parent_had_content); }
throw;
}

Expand All @@ -286,6 +309,9 @@ class Genode::Xml_generator

_out_buffer.append('\0');
}

bool has_content() { return _has_content; }
bool is_indented() { return _is_indented; }
};

Out_buffer _out_buffer;
Expand Down
5 changes: 1 addition & 4 deletions repos/os/run/xml_generator.run
Expand Up @@ -53,20 +53,17 @@ compare_output_to {
[init -> test-xml_generator] exception on level3 (expected exception value=11)
[init -> test-xml_generator] exception on level3 (expected exception value=12)
[init -> test-xml_generator]
[init -> test-xml_generator] used 183 bytes, result:
[init -> test-xml_generator] used 180 bytes, result:
[init -> test-xml_generator]
[init -> test-xml_generator] <config>
[init -> test-xml_generator] <level1>
[init -> test-xml_generator] <level2>
[init -> test-xml_generator]
[init -> test-xml_generator] <level3>
[init -> test-xml_generator] <level4/>
[init -> test-xml_generator] </level3>
[init -> test-xml_generator]
[init -> test-xml_generator] <level3>
[init -> test-xml_generator] <level4/>
[init -> test-xml_generator] </level3>
[init -> test-xml_generator]
[init -> test-xml_generator] <level3>
[init -> test-xml_generator] <level4/>
[init -> test-xml_generator] </level3>
Expand Down

0 comments on commit df13c6b

Please sign in to comment.