From dc8dd3396d5e463639f4db738e85df7822b41117 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Thu, 11 Mar 2021 21:32:11 +0100 Subject: [PATCH] base: move Xml_generator::Node::Node behind ABI Fixes #4063 --- repos/base/include/util/xml_generator.h | 74 +++++++----------------- repos/base/lib/mk/base-common.inc | 1 + repos/base/lib/symbols/ld | 3 + repos/base/src/lib/base/xml_generator.cc | 72 +++++++++++++++++++++++ 4 files changed, 97 insertions(+), 53 deletions(-) create mode 100644 repos/base/src/lib/base/xml_generator.cc diff --git a/repos/base/include/util/xml_generator.h b/repos/base/include/util/xml_generator.h index d115e8c7a1..b3b4915a7a 100644 --- a/repos/base/include/util/xml_generator.h +++ b/repos/base/include/util/xml_generator.h @@ -223,6 +223,23 @@ class Genode::Xml_generator _out_buffer.advance(content_buffer.used()); } + /* + * Helper used to pass the 'fn' argument of the public 'Node' + * constructor through an ABI to the implementation of the + * private 'Node' constructor. + */ + struct _Fn : Interface { virtual void call() const = 0; }; + + template + struct _Typed_fn : _Fn + { + T const &_fn; + _Typed_fn(T const &fn) : _fn(fn) { } + void call() const override { _fn(); } + }; + + Node(Xml_generator &, char const *, _Fn const &); + public: void insert_attribute(char const *name, char const *value) @@ -264,60 +281,11 @@ class Genode::Xml_generator _commit_content(content_buffer); } - template - Node(Xml_generator &xml, char const *name, FUNC const &func) + template + Node(Xml_generator &xml, char const *name, FN const &fn) : - _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) - { - _out_buffer.append('\t', _indent_level); - _out_buffer.append("<"); - _out_buffer.append(name); - _attr_offset = _out_buffer.used(); - - xml._curr_node = this; - xml._curr_indent++; - - try { - /* - * Process attributes and sub nodes - */ - func(); - } catch (...) { - /* reset and drop changes by not committing it */ - xml._curr_node = _parent_node; - xml._curr_indent--; - if (_parent_node) { - _parent_node->_undo_content_buffer(true, _parent_was_indented, _parent_had_content); } - throw; - } - - xml._curr_node = _parent_node; - xml._curr_indent--; - - if (_is_indented) { - _out_buffer.append("\n"); - _out_buffer.append('\t', _indent_level); - } - - if (_has_content) { - _out_buffer.append(""); - } else - _out_buffer.append("/>"); - - if (_parent_node) - _parent_node->_commit_content(_out_buffer); - else - xml._out_buffer = _out_buffer; - - _out_buffer.append('\0'); - } + Node(xml, name, static_cast<_Fn const &>(_Typed_fn(fn))) + { } bool has_content() { return _has_content; } bool is_indented() { return _is_indented; } diff --git a/repos/base/lib/mk/base-common.inc b/repos/base/lib/mk/base-common.inc index 9dfbd7471e..4a839634ae 100644 --- a/repos/base/lib/mk/base-common.inc +++ b/repos/base/lib/mk/base-common.inc @@ -32,6 +32,7 @@ SRC_CC += trace.cc SRC_CC += root_proxy.cc SRC_CC += env_session_id_space.cc SRC_CC += stack_protector.cc +SRC_CC += xml_generator.cc INC_DIR += $(REP_DIR)/src/include $(BASE_DIR)/src/include diff --git a/repos/base/lib/symbols/ld b/repos/base/lib/symbols/ld index 2374417f9b..241714c659 100644 --- a/repos/base/lib/symbols/ld +++ b/repos/base/lib/symbols/ld @@ -101,6 +101,8 @@ _ZN6Genode13Vm_connection4Vcpu5pauseEv T _ZN6Genode13Vm_connection4Vcpu5stateEv T _ZN6Genode13Vm_connection4VcpuC1ERS0_RNS_9AllocatorERNS_17Vcpu_handler_baseERKNS0_11Exit_configE T _ZN6Genode13Vm_connection4VcpuC2ERS0_RNS_9AllocatorERNS_17Vcpu_handler_baseERKNS0_11Exit_configE T +_ZN6Genode13Xml_generator4NodeC1ERS0_PKcRKNS1_3_FnE T +_ZN6Genode13Xml_generator4NodeC2ERS0_PKcRKNS1_3_FnE T _ZN6Genode13sleep_foreverEv T _ZN6Genode14Capability_map6insertEmm T _ZN6Genode14Dynamic_linker23_for_each_loaded_objectERNS_3EnvERKNS0_11For_each_fnE T @@ -424,6 +426,7 @@ memset W stdout_reconnect T wait_for_continue T + # # C++ runtime # diff --git a/repos/base/src/lib/base/xml_generator.cc b/repos/base/src/lib/base/xml_generator.cc new file mode 100644 index 0000000000..74a64db3af --- /dev/null +++ b/repos/base/src/lib/base/xml_generator.cc @@ -0,0 +1,72 @@ +/* + * \brief XML generator + * \author Norman Feske + * \date 2021-03-11 + */ + +/* + * Copyright (C) 2021 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include + +using namespace Genode; + + +Xml_generator::Node::Node(Xml_generator &xml, char const *name, _Fn const &func) +: + _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) +{ + _out_buffer.append('\t', _indent_level); + _out_buffer.append("<"); + _out_buffer.append(name); + _attr_offset = _out_buffer.used(); + + xml._curr_node = this; + xml._curr_indent++; + + try { + /* + * Process attributes and sub nodes + */ + func.call(); + } catch (...) { + /* reset and drop changes by not committing it */ + xml._curr_node = _parent_node; + xml._curr_indent--; + if (_parent_node) { + _parent_node->_undo_content_buffer(true, _parent_was_indented, _parent_had_content); } + throw; + } + + xml._curr_node = _parent_node; + xml._curr_indent--; + + if (_is_indented) { + _out_buffer.append("\n"); + _out_buffer.append('\t', _indent_level); + } + + if (_has_content) { + _out_buffer.append(""); + } else + _out_buffer.append("/>"); + + if (_parent_node) + _parent_node->_commit_content(_out_buffer); + else + xml._out_buffer = _out_buffer; + + _out_buffer.append('\0'); +}