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

View File

@ -15,6 +15,7 @@
#define _INCLUDE__UTIL__XML_GENERATOR_H_ #define _INCLUDE__UTIL__XML_GENERATOR_H_
#include <util/string.h> #include <util/string.h>
#include <util/print_lines.h>
#include <base/snprintf.h> #include <base/snprintf.h>
namespace Genode { class Xml_generator; } namespace Genode { class Xml_generator; }
@ -110,10 +111,20 @@ class Genode::Xml_generator
return Out_buffer(_dst + at, len); 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 * Return number of unused bytes of the buffer
*/ */
size_t used() const { return _used; } 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; Out_buffer _out_buffer;
bool _has_sub_nodes = false; bool _has_content = false;
bool _is_indented = false;
bool _has_attributes = false; bool _has_attributes = false;
/** /**
@ -140,15 +152,23 @@ class Genode::Xml_generator
/** /**
* Called by sub node * 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(">");
_out_buffer.append("\n"); if (indented)
_out_buffer.append("\n");
_has_sub_nodes = true; _has_content = true;
_is_indented = indented;
return _out_buffer.remainder(); return _out_buffer.remainder();
} }
@ -178,12 +198,21 @@ class Genode::Xml_generator
_attr_offset += gap; _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> template <typename FUNC>
Node(Xml_generator &xml, char const *name, FUNC const &func) Node(Xml_generator &xml, char const *name, FUNC const &func)
: :
_indent_level(xml._curr_indent), _indent_level(xml._curr_indent),
_parent_node(xml._curr_node), _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) : xml._out_buffer)
{ {
_out_buffer.append('\t', _indent_level); _out_buffer.append('\t', _indent_level);
@ -202,9 +231,12 @@ class Genode::Xml_generator
xml._curr_node = _parent_node; xml._curr_node = _parent_node;
xml._curr_indent--; xml._curr_indent--;
if (_has_sub_nodes) { if (_is_indented) {
_out_buffer.append("\n"); _out_buffer.append("\n");
_out_buffer.append('\t', _indent_level); _out_buffer.append('\t', _indent_level);
}
if (_has_content) {
_out_buffer.append("</"); _out_buffer.append("</");
_out_buffer.append(name); _out_buffer.append(name);
_out_buffer.append(">"); _out_buffer.append(">");
@ -258,6 +290,16 @@ class Genode::Xml_generator
_curr_node->insert_attribute(name, buf); _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(); } size_t used() const { return _out_buffer.used(); }
}; };