/* * Copyright (C) 2022 Riyyi * * SPDX-License-Identifier: MIT */ #ifndef UTIL_FORMAT_FORMAT_H #define UTIL_FORMAT_FORMAT_H #include // size_t #include // stringstream #include #include #include #include "util/format/builder.h" #include "util/format/parser.h" #include "util/format/toformat.h" namespace Util::Format { struct Parameter { const void* value; void (*format)(Builder& builder, const void* value); }; template void formatParameterValue(Builder& builder, const void* value) { format(builder, *static_cast(value)); } class TypeErasedParameters { public: const Parameter parameter(size_t index) { return m_parameters[index]; } size_t tell() const { return m_index; } size_t size() const { return m_parameters.size(); } bool isEOF() const { return m_index >= m_parameters.size(); } void ignore() { m_index++; } protected: size_t m_index { 0 }; std::vector m_parameters; }; template class VariadicParameters final : public TypeErasedParameters { public: VariadicParameters(const Parameters&... parameters) { m_parameters = { { ¶meters, formatParameterValue }... }; } }; // ----------------------------------------- void variadicFormatImpl(Builder& builder, Parser& parser, TypeErasedParameters& parameters); void variadicFormat(std::stringstream& stream, std::string_view format, TypeErasedParameters& parameters); // ----------------------------------------- enum class Type { None, // Foreground Info, // Blue Warn, // Yellow Danger, // Red Success, // Green Comment, // White }; void prettyVariadicFormat(Type type, bool bold, std::string_view format, TypeErasedParameters& parameters); #define FORMAT_FUNCTION(name, type, bold) \ template \ void name(const char(&format)[N] = "", const Parameters&... parameters) \ { \ VariadicParameters variadicParameters { parameters... }; \ prettyVariadicFormat(Type::type, bold, { format, N - 1 }, variadicParameters); \ } FORMAT_FUNCTION(dbgln, None, false); FORMAT_FUNCTION(dbgbln, None, true); FORMAT_FUNCTION(infoln, Info, false); FORMAT_FUNCTION(infobln, Info, true); FORMAT_FUNCTION(warnln, Warn, false); FORMAT_FUNCTION(warnbln, Warn, true); FORMAT_FUNCTION(dangerln, Danger, false); FORMAT_FUNCTION(dangerbln, Danger, true); FORMAT_FUNCTION(successln, Success, false); FORMAT_FUNCTION(successbln, Success, true); FORMAT_FUNCTION(commentln, Comment, false); FORMAT_FUNCTION(commentbln, Comment, true); // ----------------------------------------- class Dbg { public: Dbg(Type type, bool bold); virtual ~Dbg(); Builder& builder() { return m_builder; } private: Type m_type; bool m_bold; std::stringstream m_stream; Builder m_builder; }; template const Dbg& operator<<(const Dbg& debug, const T& value) { format(const_cast(debug).builder(), value); return debug; } Dbg dbg(); Dbg dbgb(); Dbg info(); Dbg infob(); Dbg warn(); Dbg warnb(); Dbg danger(); Dbg dangerb(); Dbg success(); Dbg successb(); Dbg comment(); Dbg commentb(); // ----------------------------------------- template void strln(std::string& fill, std::string_view format, const Parameters&... parameters) { std::stringstream stream; VariadicParameters variadicParameters { parameters... }; variadicFormat(stream, format, variadicParameters); fill = stream.str(); } class Str { public: Str(std::string& fill); virtual ~Str(); Builder& builder() { return m_builder; } private: std::string& m_fill; std::stringstream m_stream; Builder m_builder; }; template const Str& operator<<(const Str& string, const T& value) { format(const_cast(string).builder(), value); return string; } Str str(std::string& fill); } // namespace Util::Format using Util::Format::commentbln; using Util::Format::commentln; using Util::Format::dangerbln; using Util::Format::dangerln; using Util::Format::dbgbln; using Util::Format::dbgln; using Util::Format::infobln; using Util::Format::infoln; using Util::Format::successbln; using Util::Format::successln; using Util::Format::warnbln; using Util::Format::warnln; using Util::Format::comment; using Util::Format::commentb; using Util::Format::danger; using Util::Format::dangerb; using Util::Format::dbg; using Util::Format::dbgb; using Util::Format::info; using Util::Format::infob; using Util::Format::success; using Util::Format::successb; using Util::Format::warn; using Util::Format::warnb; using Util::Format::str; using Util::Format::strln; using FormatBuilder = Util::Format::Builder; #endif // UTIL_FORMAT_FORMAT_H