#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 void format(std::ostream& out, char const* fmt, Args const&... args) { tinyformat::format(out, fmt, args...); } // Automatically flushes, use format to avoid flushing. template void coutf(char const* fmt, Args const&... args) { format(std::cout, fmt, args...); std::cout.flush(); } // Automatically flushes, use format to avoid flushing. template void cerrf(char const* fmt, Args const&... args) { format(std::cerr, fmt, args...); std::cerr.flush(); } template std::string strf(char const* fmt, Args const&... args) { std::ostringstream os; format(os, fmt, args...); return os.str(); } namespace OutputAnyDetail { template std::basic_ostream& output(std::basic_ostream& os, T const& t) { return os << ""; } namespace Operator { template std::basic_ostream& operator<<(std::basic_ostream& os, T const& t) { return output(os, t); } } template struct Wrapper { T const& wrapped; }; template std::ostream& operator<<(std::ostream& os, Wrapper 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 template OutputAnyDetail::Wrapper outputAny(T const& t) { return OutputAnyDetail::Wrapper{t}; } struct OutputProxy { typedef function 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