#pragma once #if !defined(MIJIN_LOGGING_STDIO_SINK_HPP_INCLUDED) #define MIJIN_LOGGING_STDIO_SINK_HPP_INCLUDED 1 #include "./formatting.hpp" #include "../util/traits.hpp" namespace mijin { template requires(allocator_type>) class BaseStdioSink : public BaseFormattingLogSink { public: using base_t = BaseFormattingLogSink; using typename base_t::char_t; using typename base_t::allocator_t; using typename base_t::formatter_ptr_t; using typename base_t::message_t; private: int mMinStderrLevel = MIJIN_LOG_LEVEL_VALUE_WARNING; public: explicit BaseStdioSink(not_null_t formatter, allocator_t allocator = {}) MIJIN_NOEXCEPT_IF(std::is_nothrow_move_constructible_v) : base_t(std::move(formatter), std::move(allocator)) {} [[nodiscard]] int getMinStderrLevel() const MIJIN_NOEXCEPT { return mMinStderrLevel; } void setMinStderrLevel(int level) MIJIN_NOEXCEPT { mMinStderrLevel = level; } void setMinStderrLevel(const BaseLogLevel& level) MIJIN_NOEXCEPT { mMinStderrLevel = level.value; } void handleMessageFormatted(const message_t& message, const char_t* formatted) MIJIN_NOEXCEPT override { FILE* stream = (message.level->value >= mMinStderrLevel) ? stderr : stdout; if constexpr (std::is_same_v) { std::fputs(formatted, stream); std::fputc('\n', stream); } else if constexpr (std::is_same_v) { std::fputws(formatted, stream); std::fputwc(L'\n', stream); } else if constexpr (sizeof(char_t) == sizeof(char)) { // char8_t etc. std::fputs(std::bit_cast(formatted), stream); std::fputc('\n', stream); } else { static_assert(always_false_v, "Character type not supported."); } std::fflush(stream); } }; #define SINK_SET_ARGS(chr_type) chr_type, std::char_traits, TAllocator, TDeleter MIJIN_DEFINE_CHAR_VERSIONS_TMPL(StdioSink, MIJIN_FORMATTING_SINK_COMMON_ARGS, SINK_SET_ARGS) #undef SINK_SET_ARGS } // namespace mijin #endif // !defined(MIJIN_LOGGING_STDIO_SINK_HPP_INCLUDED)