/* * \brief Interface for textual output * \author Norman Feske * \date 2016-05-03 */ /* * Copyright (C) 2016-2017 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__BASE__OUTPUT_H_ #define _INCLUDE__BASE__OUTPUT_H_ #include namespace Genode { struct Output; } struct Genode::Output { /** * Output single character */ virtual void out_char(char) = 0; /** * Output string * * \param n maximum number of characters to output * * The output stops on the first occurrence of a null character in the * string or after 'n' characters. * * The default implementation uses 'out_char'. This method may be * overridden by the backend for improving efficiency. */ virtual void out_string(char const *str, size_t n = ~0UL); /** * Helper for the sequential output of a variable list of arguments */ template static void out_args(Output &output, HEAD && head, TAIL &&... tail) { print(output, head); out_args(output, tail...); } template static void out_args(Output &output, LAST && last) { print(output, last); } }; namespace Genode { /** * Print null-terminated string */ void print(Output &output, char const *); /** * Disallow printing non-const character buffers * * For 'char *' types, it is unclear whether the argument should be printed * as a pointer or a string. The call must resolve this ambiguity by either * casting the argument to 'void *' or wrapping it in a 'Cstring' object. */ void print(Output &, char *) = delete; /** * Print pointer value */ void print(Output &output, void const *); /** * Print arbitrary pointer types * * This function template takes precedence over the one that takes a * constant object reference as argument. */ template static inline void print(Output &output, T *ptr) { print(output, (void const *)ptr); } /** * Print unsigned long value */ void print(Output &output, unsigned long); /** * Print unsigned long long value */ void print(Output &output, unsigned long long); /* * Overloads for unsigned integer types */ static inline void print(Output &o, unsigned char v) { print(o, (unsigned long)v); } static inline void print(Output &o, unsigned short v) { print(o, (unsigned long)v); } static inline void print(Output &o, unsigned int v) { print(o, (unsigned long)v); } /** * Print signed long value */ void print(Output &output, long); /** * Print signed long long value */ void print(Output &output, long long); /* * Overloads for signed integer types */ static inline void print(Output &o, char v) { print(o, (long)v); } static inline void print(Output &o, short v) { print(o, (long)v); } static inline void print(Output &o, int v) { print(o, (long)v); } /** * Print bool value */ static inline void print(Output &output, bool value) { print(output, (int)value); } /** * Print single-precision float */ void print(Output &output, float); /** * Print double-precision float */ void print(Output &output, double); /** * Helper for the hexadecimal output of integer values * * To output an integer value as hexadecimal number, the value can be * wrapped into an 'Hex' object, thereby selecting the corresponding * overloaded 'print' function below. */ class Hex { public: enum Prefix { PREFIX, OMIT_PREFIX }; enum Pad { PAD, NO_PAD }; private: unsigned long long const _value; size_t const _digits; Prefix const _prefix; Pad const _pad; public: /** * Constructor * * \param prefix by default, the value is prepended with the prefix * '0x'. The prefix can be suppressed by specifying * 'OMIT_PREFIX' as argument. * \param pad by default, leading zeros are stripped from the * output. If set to 'PAD', the leading zeros will be * printed. */ template explicit Hex(T value, Prefix prefix = PREFIX, Pad pad = NO_PAD) : _value(value), _digits(2*sizeof(T)), _prefix(prefix), _pad(pad) { } void print(Output &output) const; }; /** * Print range as hexadecimal format * * This helper is intended for the output for memory-address ranges. For * brevity, it omits the '0x' prefix from the numbers. The numbers are * padded with leading zeros to foster the horizontal alignment of * consecutive outputs (like a table of address ranges). */ template struct Hex_range { T const base; size_t const len; Hex_range(T base, size_t len) : base(base), len(len) { } void print(Output &out) const; }; /** * Helper for the output of an individual character * * When printing a 'char' value, it appears as an integral number. By * wrapping the value in a 'Char' object, it appears as character instead. */ struct Char { char const c; explicit Char(char c) : c(c) { } void print(Output &output) const { output.out_char(c); } }; /** * Print information about object 'obj' * * The object type must provide a const 'print(Output &)' method that * produces the textual representation of the object. * * In contrast to overloads of the 'Genode::print' function, the 'T::print' * method is able to access object-internal state, which can thereby be * incorporated into the textual output. */ template static inline void print(Output &output, T const &obj) { obj.print(output); } /** * Print a variable number of arguments */ template static inline void print(Output &output, HEAD const &head, TAIL &&... tail) { Output::out_args(output, head, tail...); } } template void Genode::Hex_range::print(Output &out) const { using Genode::print; Hex const from(base, Hex::OMIT_PREFIX, Hex::PAD); T const end = base + len; /* if end at integer limit, use ']' as closing delimiter */ if (base && end == 0) { Hex const inclusive_to((T)(end - 1), Hex::OMIT_PREFIX, Hex::PAD); print(out, "[", from, ",", inclusive_to, "]"); return; } /* use exclusive upper limit for ordinary ranges */ print(out, "[", from, ",", Hex(end, Hex::OMIT_PREFIX, Hex::PAD), ")"); /* output warning on integer-overflowing upper limit or empty range */ if (base && end < base) print(out, " (overflow!)"); if (len == 0) print(out, " (empty!)"); } #endif /* _INCLUDE__BASE__OUTPUT_H_ */