xml_generator: support appending of node content

The new 'Xml_generator::append' method can be used to append strings
into the body of an XML node.
This commit is contained in:
Norman Feske 2015-09-22 17:09:22 +02:00 committed by Christian Helmuth
parent a80d944944
commit e590d90bf6
1 changed files with 49 additions and 7 deletions

View File

@ -15,6 +15,7 @@
#define _INCLUDE__UTIL__XML_GENERATOR_H_
#include <util/string.h>
#include <util/print_lines.h>
#include <base/snprintf.h>
namespace Genode { class Xml_generator; }
@ -110,10 +111,20 @@ class Genode::Xml_generator
return Out_buffer(_dst + at, len);
}
bool has_trailing_newline() const
{
return (_used > 1) && (_dst[_used - 1] == '\n');
}
/**
* Return number of unused bytes of the buffer
*/
size_t used() const { return _used; }
void discard_trailing_whitespace()
{
for (; _used > 0 && is_whitespace(_dst[_used - 1]); _used--);
}
};
@ -130,7 +141,8 @@ class Genode::Xml_generator
Out_buffer _out_buffer;
bool _has_sub_nodes = false;
bool _has_content = false;
bool _is_indented = false;
bool _has_attributes = false;
/**
@ -140,15 +152,23 @@ class Genode::Xml_generator
/**
* Called by sub node
*
* \param indented if true, the returned buffer and the
* end tag start at a fresh line. This is the
* case if the content buffer contains sub
* nodes. But when inserting raw content,
* such additional whitespaces are not desired.
*/
Out_buffer _content_buffer()
Out_buffer _content_buffer(bool indented)
{
if (!_has_sub_nodes)
if (!_has_content)
_out_buffer.append(">");
_out_buffer.append("\n");
if (indented)
_out_buffer.append("\n");
_has_sub_nodes = true;
_has_content = true;
_is_indented = indented;
return _out_buffer.remainder();
}
@ -178,12 +198,21 @@ class Genode::Xml_generator
_attr_offset += gap;
}
void append(char const *src, size_t src_len)
{
Out_buffer content_buffer = _content_buffer(false);
content_buffer.append(src, src_len);
_commit_content(content_buffer);
}
template <typename FUNC>
Node(Xml_generator &xml, char const *name, FUNC const &func)
:
_indent_level(xml._curr_indent),
_parent_node(xml._curr_node),
_out_buffer(_parent_node ? _parent_node->_content_buffer()
_out_buffer(_parent_node ? _parent_node->_content_buffer(true)
: xml._out_buffer)
{
_out_buffer.append('\t', _indent_level);
@ -202,9 +231,12 @@ class Genode::Xml_generator
xml._curr_node = _parent_node;
xml._curr_indent--;
if (_has_sub_nodes) {
if (_is_indented) {
_out_buffer.append("\n");
_out_buffer.append('\t', _indent_level);
}
if (_has_content) {
_out_buffer.append("</");
_out_buffer.append(name);
_out_buffer.append(">");
@ -258,6 +290,16 @@ class Genode::Xml_generator
_curr_node->insert_attribute(name, buf);
}
/**
* Append content to XML node
*
* This method must not be followed by calls of 'attribute'.
*/
void append(char const *str, size_t str_len = ~0UL)
{
_curr_node->append(str, str_len == ~0UL ? strlen(str) : str_len);
}
size_t used() const { return _out_buffer.used(); }
};