diff --git a/repos/os/include/util/formatted_output.h b/repos/os/include/util/formatted_output.h new file mode 100644 index 0000000000..dc4aa7651c --- /dev/null +++ b/repos/os/include/util/formatted_output.h @@ -0,0 +1,122 @@ +/* + * \brief Utilities for formatted text output + * \author Norman Feske + * \date 2022-03-14 + */ + +/* + * Copyright (C) 2022 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. + */ + +#ifndef _INCLUDE__OS__UTIL__FORMATTED_OUTPUT_H_ +#define _INCLUDE__OS__UTIL__FORMATTED_OUTPUT_H_ + +#include + +namespace Genode { + + template struct Truncated; + template struct Repeated; + template struct Left_aligned; + template struct Right_aligned; + + /** + * Return the number of characters needed when rendering 'args' as text + */ + template + static unsigned printed_length(ARGS &&... args) + { + struct _Output : Output + { + unsigned count = 0; + void out_char(char) override { count++; } + } _output; + + print(_output, args...); + return _output.count; + } +} + + +template +struct Genode::Truncated +{ + unsigned const _limit; + T const &_arg; + + Truncated(unsigned limit, T const &arg) : _limit(limit), _arg(arg) { } + + void print(Output &out) const + { + struct _Output : Output + { + Output &out; + unsigned const limit; + unsigned count = 0; + + void out_char(char c) override + { + if (count++ < limit) + out.out_char(c); + } + + _Output(Output &out, unsigned limit) : out(out), limit(limit) { } + + } _output(out, _limit); + + Genode::print(_output, _arg); + } +}; + + +template +struct Genode::Repeated +{ + unsigned const _n; + T const &_arg; + + Repeated(unsigned n, T const &arg) : _n(n), _arg(arg) { } + + void print(Output &out) const + { + for (unsigned i = 0; i < _n; i++) + Genode::print(out, _arg); + } +}; + + +template +struct Genode::Left_aligned +{ + unsigned const _n; + T const &_arg; + + Left_aligned(unsigned n, T const &arg) : _n(n), _arg(arg) { } + + void print(Output &out) const + { + unsigned const len = min(printed_length(_arg), _n); + Genode::print(out, Truncated(len, _arg), Repeated(_n - len, Char(' '))); + } +}; + + +template +struct Genode::Right_aligned +{ + unsigned const _n; + T const &_arg; + + Right_aligned(unsigned n, T const &arg) : _n(n), _arg(arg) { } + + void print(Output &out) const + { + unsigned const len = min(printed_length(_arg), _n); + Genode::print(out, Repeated(_n - len, Char(' ')), Truncated(len, _arg)); + } +}; + +#endif /* _INCLUDE__OS__UTIL__FORMATTED_OUTPUT_H_ */