diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/core/StarFormat.hpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/core/StarFormat.hpp')
-rw-r--r-- | source/core/StarFormat.hpp | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/source/core/StarFormat.hpp b/source/core/StarFormat.hpp new file mode 100644 index 0000000..bb0327e --- /dev/null +++ b/source/core/StarFormat.hpp @@ -0,0 +1,100 @@ +#ifndef STAR_FORMAT_HPP +#define STAR_FORMAT_HPP + +#include "StarMemory.hpp" + +namespace Star { + +struct FormatException : public std::exception { + FormatException(std::string what) : whatmsg(move(what)) {} + + char const* what() const noexcept override { + return whatmsg.c_str(); + } + + std::string whatmsg; +}; + +} + +#define TINYFORMAT_ERROR(reason) throw Star::FormatException(reason) + +#include "tinyformat.h" + +namespace Star { + +template <typename... Args> +void format(std::ostream& out, char const* fmt, Args const&... args) { + tinyformat::format(out, fmt, args...); +} + +// Automatically flushes, use format to avoid flushing. +template <typename... Args> +void coutf(char const* fmt, Args const&... args) { + format(std::cout, fmt, args...); + std::cout.flush(); +} + +// Automatically flushes, use format to avoid flushing. +template <typename... Args> +void cerrf(char const* fmt, Args const&... args) { + format(std::cerr, fmt, args...); + std::cerr.flush(); +} + +template <typename... Args> +std::string strf(char const* fmt, Args const&... args) { + std::ostringstream os; + format(os, fmt, args...); + return os.str(); +} + +namespace OutputAnyDetail { + template<typename T, typename CharT, typename Traits> + std::basic_ostream<CharT, Traits>& output(std::basic_ostream<CharT, Traits>& os, T const& t) { + return os << "<type " << typeid(T).name() << " at address: " << &t << ">"; + } + + namespace Operator { + template<typename T, typename CharT, typename Traits> + std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, T const& t) { + return output(os, t); + } + } + + template <typename T> + struct Wrapper { + T const& wrapped; + }; + + template <typename T> + std::ostream& operator<<(std::ostream& os, Wrapper<T> const& wrapper) { + using namespace Operator; + return os << wrapper.wrapped; + } +} + +// Wraps a type so that is printable no matter what.. If no operator<< is +// defined for a type, then will print <type [typeid] at address: [address]> +template <typename T> +OutputAnyDetail::Wrapper<T> outputAny(T const& t) { + return OutputAnyDetail::Wrapper<T>{t}; +} + +struct OutputProxy { + typedef function<void(std::ostream&)> PrintFunction; + + OutputProxy(PrintFunction p) + : print(move(p)) {} + + PrintFunction print; +}; + +inline std::ostream& operator<<(std::ostream& os, OutputProxy const& p) { + p.print(os); + return os; +} + +} + +#endif |