From 9a702bb80c2c860a765b55fa26b484db1428a4f9 Mon Sep 17 00:00:00 2001 From: Pavel Artsishevsky Date: Sun, 5 Jan 2025 23:47:23 +0100 Subject: [PATCH] progress2... Signed-off-by: Pavel Artsishevsky --- include/slimlog/format-inl.h | 11 +- include/slimlog/logger.h | 63 +++++++--- include/slimlog/pattern-inl.h | 18 +-- include/slimlog/record-inl.h | 8 +- include/slimlog/record.h | 10 +- include/slimlog/sink-inl.h | 40 +++---- include/slimlog/sink.h | 146 ++++++++++++++--------- include/slimlog/sinks/file_sink-inl.h | 24 ++-- include/slimlog/sinks/file_sink.h | 16 ++- include/slimlog/sinks/null_sink-inl.h | 18 +-- include/slimlog/sinks/null_sink.h | 12 +- include/slimlog/sinks/ostream_sink-inl.h | 19 +-- include/slimlog/sinks/ostream_sink.h | 27 +++-- src/slimlog.cpp | 36 +++--- 14 files changed, 233 insertions(+), 215 deletions(-) diff --git a/include/slimlog/format-inl.h b/include/slimlog/format-inl.h index e7a9b34..2b54be8 100644 --- a/include/slimlog/format-inl.h +++ b/include/slimlog/format-inl.h @@ -7,9 +7,7 @@ // IWYU pragma: private, include -#ifndef SLIMLOG_HEADER_ONLY -#include -#endif +#include // IWYU pragma: associated #ifdef SLIMLOG_FMTLIB #if __has_include() @@ -17,17 +15,10 @@ #else #include #endif - -#include -#include #else #include #endif -#include -#include -#include - namespace SlimLog { #ifndef SLIMLOG_FMTLIB diff --git a/include/slimlog/logger.h b/include/slimlog/logger.h index 125e55a..f9eefda 100644 --- a/include/slimlog/logger.h +++ b/include/slimlog/logger.h @@ -22,10 +22,15 @@ namespace SlimLog { /** - * @brief Default buffer size for log messages. + * @brief Default buffer size for raw log messages. */ static constexpr auto DefaultBufferSize = 256U; +/** + * @brief Default threading policy for logger sinks. + */ +using DefaultThreadingPolicy = MultiThreadedPolicy; + /** * @brief Logger front-end class. * @@ -34,13 +39,15 @@ static constexpr auto DefaultBufferSize = 256U; * @tparam String Type used for logging messages (e.g., `std::string`). * @tparam Char Underlying character type for the string. * @tparam ThreadingPolicy Threading policy for sink operations. - * @tparam StaticBufferSize Size of the internal pre-allocated buffer. + * @tparam BufferSize Size of the internal pre-allocated buffer. + * @tparam Allocator Allocator type for the internal buffer. */ template< typename String, typename Char = Util::Types::UnderlyingCharType, - typename ThreadingPolicy = MultiThreadedPolicy, - std::size_t StaticBufferSize = DefaultBufferSize> + typename ThreadingPolicy = DefaultThreadingPolicy, + std::size_t BufferSize = DefaultBufferSize, + typename Allocator = std::allocator> class Logger { public: /** @brief String type for log messages. */ @@ -49,8 +56,10 @@ class Logger { using CharType = Char; /** @brief String view type for log categories. */ using StringViewType = std::basic_string_view; - /** @brief Size of the internal buffer. */ - static constexpr auto BufferSize = StaticBufferSize; + /** @brief Base sink type for the logger. */ + using SinkType = Sink; + /** @brief Buffer type used for log message formatting. */ + using FormatBufferType = FormatBuffer; Logger(Logger const&) = delete; Logger(Logger&&) = delete; @@ -114,23 +123,47 @@ class Logger { * @param sink Shared pointer to the sink. * @return true if the sink was added, false if it already exists. */ - auto add_sink(const std::shared_ptr>& sink) -> bool + auto add_sink(const std::shared_ptr& sink) -> bool { return m_sinks.add_sink(sink); } + /** + * @brief Creates and adds a new formattable sink to this logger. + * + * @tparam T Sink type template (e.g., OStreamSink). + * @tparam SinkBufferSize Size of the internal buffer for the sink. + * @tparam SinkAllocator Allocator type for the sink buffer. + * @tparam Args Argument types for the sink constructor. + * @param args Arguments forwarded to the sink constructor. + * @return Shared pointer to the created sink. + */ + template< + template + typename T, + std::size_t SinkBufferSize = DefaultBufferSize, + typename SinkAllocator = Allocator, + typename... Args> + requires(IsFormattableSink>) + auto add_sink(Args&&... args) -> std::shared_ptr + { + return m_sinks.template add_sink>( + std::forward(args)...); + } + /** * @brief Creates and adds a new sink to this logger. * * @tparam T Sink type template (e.g., OStreamSink). - * @tparam Args Constructor argument types for the sink. + * @tparam Args Argument types for the sink constructor. * @param args Arguments forwarded to the sink constructor. * @return Shared pointer to the created sink. */ - template class T, typename... Args> - auto add_sink(Args&&... args) -> std::shared_ptr> + template class T, typename... Args> + requires(!IsFormattableSink>) + auto add_sink(Args&&... args) -> std::shared_ptr { - return m_sinks.template add_sink>(std::forward(args)...); + return m_sinks.template add_sink>(std::forward(args)...); } /** @@ -140,7 +173,7 @@ class Logger { * @return \b true if the sink was actually removed. * @return \b false if the sink does not exist in this logger. */ - auto remove_sink(const std::shared_ptr>& sink) -> bool + auto remove_sink(const std::shared_ptr& sink) -> bool { return m_sinks.remove_sink(sink); } @@ -153,7 +186,7 @@ class Logger { * @return \b true if the sink exists and is enabled. * @return \b false if the sink does not exist in this logger. */ - auto set_sink_enabled(const std::shared_ptr>& sink, bool enabled) -> bool + auto set_sink_enabled(const std::shared_ptr& sink, bool enabled) -> bool { return m_sinks.set_sink_enabled(sink, enabled); } @@ -165,7 +198,7 @@ class Logger { * @return \b true if the sink is enabled. * @return \b false if the sink is disabled. */ - [[nodiscard]] auto sink_enabled(const std::shared_ptr>& sink) const -> bool + [[nodiscard]] auto sink_enabled(const std::shared_ptr& sink) const -> bool { return m_sinks.sink_enabled(sink); } @@ -238,7 +271,7 @@ class Logger { void message(Level level, Format...> fmt, Args&&... args) const { - auto callback = [&fmt = fmt.fmt()](auto& buffer, Args&&... args) { + auto callback = [&fmt = fmt.fmt()](FormatBufferType& buffer, Args&&... args) { buffer.format(fmt, std::forward(args)...); }; diff --git a/include/slimlog/pattern-inl.h b/include/slimlog/pattern-inl.h index e8e27e5..e16aaca 100644 --- a/include/slimlog/pattern-inl.h +++ b/include/slimlog/pattern-inl.h @@ -7,32 +7,18 @@ // IWYU pragma: private, include -#ifndef SLIMLOG_HEADER_ONLY -#include -#endif - #include #include +#include // IWYU pragma: associated #include #include #include #include -#include -#include #include -#include -#include #include -#include #include #include -#include -#include -#include -#include -#include -#include namespace SlimLog { @@ -144,7 +130,7 @@ auto Pattern::format(auto& out, Record& record) -> void case Placeholder::Type::Message: std::visit( Util::Types::Overloaded{ - [&out, &value = item.value](std::reference_wrapper arg) { + [&out, &value = item.value](std::reference_wrapper arg) { if constexpr (Detail::HasConvertString) { format_string( out, diff --git a/include/slimlog/record-inl.h b/include/slimlog/record-inl.h index 7391798..b5eb873 100644 --- a/include/slimlog/record-inl.h +++ b/include/slimlog/record-inl.h @@ -7,15 +7,9 @@ // IWYU pragma: private, include -#ifndef SLIMLOG_HEADER_ONLY -#include -#endif - +#include // IWYU pragma: associated #include -#include -#include -#include #include namespace SlimLog { diff --git a/include/slimlog/record.h b/include/slimlog/record.h index 7e5a8c2..6da1e85 100644 --- a/include/slimlog/record.h +++ b/include/slimlog/record.h @@ -115,13 +115,17 @@ struct RecordLocation { */ template struct Record { + /** @brief String reference type. */ + using StringRefType = std::reference_wrapper; + /** @brief String view type. */ + using StringViewType = RecordStringView; + Level level = {}; ///< Log level. RecordLocation location = {}; ///< Source code location. - RecordStringView category = {}; ///< Log category. + StringViewType category = {}; ///< Log category. std::size_t thread_id = {}; ///< Thread ID. RecordTime time = {}; ///< Record time. - std::variant, RecordStringView> message - = RecordStringView{}; ///< Log message. + std::variant message = StringViewType{}; ///< Log message. }; } // namespace SlimLog diff --git a/include/slimlog/sink-inl.h b/include/slimlog/sink-inl.h index ee2ac96..c61ee36 100644 --- a/include/slimlog/sink-inl.h +++ b/include/slimlog/sink-inl.h @@ -9,44 +9,38 @@ #ifndef SLIMLOG_HEADER_ONLY #include -#include #endif #include #include -#include #include #include +#include // IWYU pragma: associated #include #include // IWYU pragma: keep -#include -#include #include -#include -#include #include -#include -#include -#include namespace SlimLog { -template -auto Sink::set_pattern(StringViewType pattern) -> void +template +auto FormattableSink::set_levels( + std::initializer_list> levels) -> void { - m_pattern.set_pattern(std::move(pattern)); + m_pattern.set_levels(std::move(levels)); } -template -auto Sink::set_levels(std::initializer_list> levels) +template +auto FormattableSink::set_pattern(StringViewType pattern) -> void { - m_pattern.set_levels(std::move(levels)); + m_pattern.set_pattern(std::move(pattern)); } -template -auto Sink::format(FormatBufferType& result, RecordType& record) -> void +template +auto FormattableSink::format( + FormatBufferType& result, RecordType& record) -> void { m_pattern.format(result, record); } @@ -75,8 +69,7 @@ SinkDriver::~SinkDriver() } template -auto SinkDriver::add_sink(const std::shared_ptr>& sink) - -> bool +auto SinkDriver::add_sink(const std::shared_ptr& sink) -> bool { const typename ThreadingPolicy::WriteLock lock(m_mutex); const auto result = m_sinks.insert_or_assign(sink, true).second; @@ -85,8 +78,7 @@ auto SinkDriver::add_sink(const std::shared_ptr -auto SinkDriver::remove_sink(const std::shared_ptr>& sink) - -> bool +auto SinkDriver::remove_sink(const std::shared_ptr& sink) -> bool { const typename ThreadingPolicy::WriteLock lock(m_mutex); if (m_sinks.erase(sink) > 0) { @@ -98,7 +90,7 @@ auto SinkDriver::remove_sink(const std::shared_ptr auto SinkDriver::set_sink_enabled( - const std::shared_ptr>& sink, bool enabled) -> bool + const std::shared_ptr& sink, bool enabled) -> bool { const typename ThreadingPolicy::WriteLock lock(m_mutex); if (const auto itr = m_sinks.find(sink); itr != m_sinks.end()) { @@ -110,8 +102,8 @@ auto SinkDriver::set_sink_enabled( } template -auto SinkDriver::sink_enabled( - const std::shared_ptr>& sink) const -> bool +auto SinkDriver::sink_enabled(const std::shared_ptr& sink) const + -> bool { const typename ThreadingPolicy::ReadLock lock(m_mutex); if (const auto itr = m_sinks.find(sink); itr != m_sinks.end()) { diff --git a/include/slimlog/sink.h b/include/slimlog/sink.h index 4ea0dc1..600e764 100644 --- a/include/slimlog/sink.h +++ b/include/slimlog/sink.h @@ -11,7 +11,9 @@ #include #include #include +#include +#include #include #include #include @@ -25,23 +27,69 @@ namespace SlimLog { /** * @brief Base abstract sink class. * - * A sink represents a logging backend that processes and outputs log messages. + * A sink is a destination for log messages. * - * @tparam Logger The logger class type intended for use with this sink. + * @tparam String String type for log messages. + * @tparam Char Character type for the string. */ -template +template> class Sink { +public: + /** @brief Log record type. */ + using RecordType = Record; + + /** @brief Default constructor. */ + Sink() = default; + /** @brief Copy constructor. */ + Sink(Sink const&) = default; + /** @brief Move constructor. */ + Sink(Sink&&) noexcept = default; + + /** @brief Assignment operator. */ + auto operator=(Sink const&) -> Sink& = default; + /** @brief Move assignment operator. */ + auto operator=(Sink&&) noexcept -> Sink& = default; + + /** @brief Destructor. */ + virtual ~Sink() = default; + + /** + * @brief Processes a log record. + * + * Formats and outputs the log record. + * + * @param record The log record to process. + */ + virtual auto message(RecordType& record) -> void = 0; + + /** + * @brief Flushes any buffered log messages. + */ + virtual auto flush() -> void = 0; +}; + +/** + * @brief Abstract formattable sink class. + * + * A sink that supports custom message formatting. + * Allocates another buffer for message formatting. + * + * @tparam String String type for log messages. + * @tparam Char Character type for the string. + * @tparam BufferSize Size of the internal pre-allocated buffer. + * @tparam Allocator Allocator type for the internal buffer. + */ +template +class FormattableSink : public Sink { public: /** @brief String type for log messages. */ - using StringType = typename Logger::StringType; - /** @brief String view type for log categories. */ - using StringViewType = typename Logger::StringViewType; - /** @brief Character type for log messages. */ - using CharType = typename Logger::CharType; - /** @brief Buffer type used for formatting log messages. */ - using FormatBufferType = FormatBuffer>; + using StringType = String; + /** @brief Raw string view type. */ + using StringViewType = std::basic_string_view; + /** @brief Buffer type used for log message formatting. */ + using FormatBufferType = FormatBuffer; /** @brief Log record type. */ - using RecordType = Record; + using RecordType = Record; /** * @brief Constructs a new Sink object. @@ -66,25 +114,12 @@ class Sink { * @param args Optional pattern and list of log levels. */ template - explicit Sink(Args&&... args) + explicit FormattableSink(Args&&... args) // NOLINTNEXTLINE(*-array-to-pointer-decay,*-no-array-decay) : m_pattern(std::forward(args)...) { } - /** @brief Copy constructor. */ - Sink(Sink const&) = default; - /** @brief Move constructor. */ - Sink(Sink&&) noexcept = default; - - /** @brief Assignment operator. */ - auto operator=(Sink const&) -> Sink& = default; - /** @brief Move assignment operator. */ - auto operator=(Sink&&) noexcept -> Sink& = default; - - /** @brief Destructor. */ - virtual ~Sink() = default; - /** * @brief Sets the log message pattern. * @@ -113,20 +148,6 @@ class Sink { */ virtual auto set_levels(std::initializer_list> levels) -> void; - /** - * @brief Processes a log record. - * - * Formats and outputs the log record. - * - * @param record The log record to process. - */ - virtual auto message(RecordType& record) -> void = 0; - - /** - * @brief Flushes any buffered log messages. - */ - virtual auto flush() -> void = 0; - protected: /** * @brief Formats a log record according to the pattern. @@ -137,7 +158,18 @@ class Sink { auto format(FormatBufferType& result, RecordType& record) -> void; private: - Pattern m_pattern; + Pattern m_pattern; +}; + +/** + * @brief Checks if the specified type is a formattable sink. + * + * @tparam T Type to check. + */ +template +concept IsFormattableSink = requires(const T& arg) { + []( + const FormattableSink&) {}(arg); }; /** @@ -152,14 +184,16 @@ class Sink { template class SinkDriver final { public: - /** @brief Character type for log messages. */ - using CharType = typename Logger::CharType; /** @brief String view type for log category. */ using StringViewType = typename Logger::StringViewType; /** @brief Buffer type used for log message formatting. */ - using FormatBufferType = typename Sink::FormatBufferType; + using FormatBufferType = typename Logger::FormatBufferType; + /** @brief Base sink type for the logger. */ + using SinkType = typename Logger::SinkType; /** @brief Log record type. */ - using RecordType = typename Sink::RecordType; + using RecordType = typename SinkType::RecordType; + /** @brief Log record string view type. */ + using RecordStringViewType = typename RecordType::StringViewType; /** * @brief Constructs a new SinkDriver object. @@ -186,7 +220,7 @@ class SinkDriver final { * @return \b true if the sink was actually inserted. * @return \b false if the sink is already present in this logger. */ - auto add_sink(const std::shared_ptr>& sink) -> bool; + auto add_sink(const std::shared_ptr& sink) -> bool; /** * @brief Creates and emplaces a new sink. @@ -197,7 +231,7 @@ class SinkDriver final { * @return Shared pointer to the created sink or `nullptr` in case of failure. */ template - auto add_sink(Args&&... args) -> std::shared_ptr> + auto add_sink(Args&&... args) -> std::shared_ptr { auto sink = std::make_shared(std::forward(args)...); return add_sink(sink) ? sink : nullptr; @@ -210,7 +244,7 @@ class SinkDriver final { * @return \b true if the sink was actually removed. * @return \b false if the sink does not exist in this logger. */ - auto remove_sink(const std::shared_ptr>& sink) -> bool; + auto remove_sink(const std::shared_ptr& sink) -> bool; /** * @brief Enables or disables a sink for this logger. @@ -220,7 +254,7 @@ class SinkDriver final { * @return \b true if the sink exists and is enabled. * @return \b false if the sink does not exist in this logger. */ - auto set_sink_enabled(const std::shared_ptr>& sink, bool enabled) -> bool; + auto set_sink_enabled(const std::shared_ptr& sink, bool enabled) -> bool; /** * @brief Checks if a sink is enabled. @@ -229,7 +263,7 @@ class SinkDriver final { * @return \b true if the sink is enabled. * @return \b false if the sink is disabled. */ - auto sink_enabled(const std::shared_ptr>& sink) const -> bool; + auto sink_enabled(const std::shared_ptr& sink) const -> bool; /** * @brief Emits a new callback-based log message if it fits the specified logging level. @@ -274,7 +308,7 @@ class SinkDriver final { if constexpr (std::is_invocable_v) { // Callable with buffer argument: message will be stored in buffer. callback(buffer, std::forward(args)...); - record.message = RecordStringView{buffer.data(), buffer.size()}; + record.message = RecordStringViewType{buffer.data(), buffer.size()}; } else if constexpr (std::is_invocable_v) { using RetType = typename std::invoke_result_t; if constexpr (std::is_void_v) { @@ -284,16 +318,16 @@ class SinkDriver final { } else { // Non-void callable without arguments: message is the return value auto message = callback(std::forward(args)...); - if constexpr (std::is_convertible_v>) { - record.message = RecordStringView{std::move(message)}; + if constexpr (std::is_convertible_v) { + record.message = RecordStringViewType{std::move(message)}; } else { record.message = message; } } - } else if constexpr (std::is_convertible_v>) { + } else if constexpr (std::is_convertible_v) { // Non-invocable argument: argument is the message itself // NOLINTNEXTLINE(*-array-to-pointer-decay,*-no-array-decay) - record.message = RecordStringView{std::forward(callback)}; + record.message = RecordStringViewType{std::forward(callback)}; } else { record.message = callback; } @@ -361,8 +395,8 @@ class SinkDriver final { const Logger* m_logger; SinkDriver* m_parent; std::vector m_children; - std::unordered_map*, const Logger*> m_effective_sinks; - std::unordered_map>, bool> m_sinks; + std::unordered_map m_effective_sinks; + std::unordered_map, bool> m_sinks; mutable ThreadingPolicy::Mutex m_mutex; }; // namespace SlimLog diff --git a/include/slimlog/sinks/file_sink-inl.h b/include/slimlog/sinks/file_sink-inl.h index 594da17..e420587 100644 --- a/include/slimlog/sinks/file_sink-inl.h +++ b/include/slimlog/sinks/file_sink-inl.h @@ -7,12 +7,7 @@ // IWYU pragma: private, include -#ifndef SLIMLOG_HEADER_ONLY -#include -#endif - -#include -#include +#include // IWYU pragma: associated #if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__) // In addition to below for fopen_s() on Windows @@ -20,16 +15,13 @@ #endif #include -#include -#include #include -#include #include namespace SlimLog { -template -auto FileSink::open(std::string_view filename) -> void +template +auto FileSink::open(std::string_view filename) -> void { #if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__) FILE* fp; @@ -43,19 +35,19 @@ auto FileSink::open(std::string_view filename) -> void } } -template -auto FileSink::message(RecordType& record) -> void +template +auto FileSink::message(RecordType& record) -> void { FormatBufferType buffer; - Sink::format(buffer, record); + this->format(buffer, record); buffer.push_back('\n'); if (std::fwrite(buffer.data(), buffer.size(), 1, m_fp.get()) != 1) { throw std::system_error({errno, std::system_category()}, "Failed writing to log file"); } } -template -auto FileSink::flush() -> void +template +auto FileSink::flush() -> void { if (std::fflush(m_fp.get()) != 0) { throw std::system_error({errno, std::system_category()}, "Failed flush to log file"); diff --git a/include/slimlog/sinks/file_sink.h b/include/slimlog/sinks/file_sink.h index 72e38c2..0d855e6 100644 --- a/include/slimlog/sinks/file_sink.h +++ b/include/slimlog/sinks/file_sink.h @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -22,12 +23,15 @@ namespace SlimLog { * * @tparam Logger The logger class type intended for use with this sink. */ -template -class FileSink : public Sink { +template< + typename String, + typename Char = Util::Types::UnderlyingCharType, + std::size_t BufferSize = DefaultBufferSize, + typename Allocator = std::allocator> +class FileSink : public FormattableSink { public: - using typename Sink::CharType; - using typename Sink::FormatBufferType; - using typename Sink::RecordType; + using typename FormattableSink::RecordType; + using typename FormattableSink::FormatBufferType; /** * @brief Constructs a new FileSink object. @@ -38,7 +42,7 @@ class FileSink : public Sink { */ template explicit FileSink(std::string_view filename, Args&&... args) - : Sink(std::forward(args)...) + : FormattableSink(std::forward(args)...) { open(filename); } diff --git a/include/slimlog/sinks/null_sink-inl.h b/include/slimlog/sinks/null_sink-inl.h index f90404e..55384a2 100644 --- a/include/slimlog/sinks/null_sink-inl.h +++ b/include/slimlog/sinks/null_sink-inl.h @@ -7,25 +7,17 @@ // IWYU pragma: private, include -#ifndef SLIMLOG_HEADER_ONLY -#include -#endif - -#include -#include +#include // IWYU pragma: associated namespace SlimLog { -template -auto NullSink::message(RecordType& record) -> void +template +auto NullSink::message(RecordType& /*unused*/) -> void { - FormatBufferType buffer; - Sink::format(buffer, record); - buffer.push_back('\n'); } -template -auto NullSink::flush() -> void +template +auto NullSink::flush() -> void { } diff --git a/include/slimlog/sinks/null_sink.h b/include/slimlog/sinks/null_sink.h index 00a1daa..48aba44 100644 --- a/include/slimlog/sinks/null_sink.h +++ b/include/slimlog/sinks/null_sink.h @@ -5,9 +5,10 @@ #pragma once -#include #include +#include +#include #include namespace SlimLog { @@ -19,11 +20,10 @@ namespace SlimLog { * * @tparam Logger The logger class type intended for use with this sink. */ -template -class NullSink : public Sink { +template> +class NullSink : public Sink { public: - using typename Sink::RecordType; - using typename Sink::FormatBufferType; + using typename Sink::RecordType; /** * @brief Constructs a new NullSink object. @@ -33,7 +33,7 @@ class NullSink : public Sink { */ template explicit NullSink(Args&&... args) - : Sink(std::forward(args)...) + : Sink(std::forward(args)...) { } diff --git a/include/slimlog/sinks/ostream_sink-inl.h b/include/slimlog/sinks/ostream_sink-inl.h index c5af4ff..839e9c7 100644 --- a/include/slimlog/sinks/ostream_sink-inl.h +++ b/include/slimlog/sinks/ostream_sink-inl.h @@ -7,28 +7,21 @@ // IWYU pragma: private, include -#ifndef SLIMLOG_HEADER_ONLY -#include -#endif - -#include -#include - -#include +#include // IWYU pragma: associated namespace SlimLog { -template -auto OStreamSink::message(RecordType& record) -> void +template +auto OStreamSink::message(RecordType& record) -> void { FormatBufferType buffer; - Sink::format(buffer, record); + this->format(buffer, record); buffer.push_back('\n'); m_ostream.write(buffer.begin(), buffer.size()); } -template -auto OStreamSink::flush() -> void +template +auto OStreamSink::flush() -> void { m_ostream.flush(); } diff --git a/include/slimlog/sinks/ostream_sink.h b/include/slimlog/sinks/ostream_sink.h index 588a6f5..c55c385 100644 --- a/include/slimlog/sinks/ostream_sink.h +++ b/include/slimlog/sinks/ostream_sink.h @@ -7,8 +7,12 @@ #include #include +#include +#include +#include #include +#include #include namespace SlimLog { @@ -20,12 +24,15 @@ namespace SlimLog { * * @tparam Logger The logger class type intended for use with this sink. */ -template -class OStreamSink : public Sink { +template< + typename String, + typename Char = Util::Types::UnderlyingCharType, + std::size_t BufferSize = DefaultBufferSize, + typename Allocator = std::allocator> +class OStreamSink : public FormattableSink { public: - using typename Sink::CharType; - using typename Sink::FormatBufferType; - using typename Sink::RecordType; + using typename FormattableSink::RecordType; + using typename FormattableSink::FormatBufferType; /** * @brief Constructs a new OStreamSink object. @@ -35,8 +42,8 @@ class OStreamSink : public Sink { * @param args Optional pattern and list of log levels. */ template - explicit OStreamSink(const std::basic_ostream& ostream, Args&&... args) - : Sink(std::forward(args)...) + explicit OStreamSink(const std::basic_ostream& ostream, Args&&... args) + : FormattableSink(std::forward(args)...) , m_ostream(ostream.rdbuf()) { } @@ -49,8 +56,8 @@ class OStreamSink : public Sink { * @param args Optional pattern and list of log levels. */ template - explicit OStreamSink(std::basic_streambuf* streambuf, Args&&... args) - : Sink(std::forward(args)...) + explicit OStreamSink(std::basic_streambuf* streambuf, Args&&... args) + : FormattableSink(std::forward(args)...) , m_ostream(streambuf) { } @@ -70,7 +77,7 @@ class OStreamSink : public Sink { auto flush() -> void override; private: - std::basic_ostream m_ostream; + std::basic_ostream m_ostream; }; } // namespace SlimLog diff --git a/src/slimlog.cpp b/src/slimlog.cpp index 3ad2f90..303f290 100644 --- a/src/slimlog.cpp +++ b/src/slimlog.cpp @@ -28,10 +28,9 @@ namespace SlimLog { // char template class SinkDriver, SingleThreadedPolicy>; template class SinkDriver, MultiThreadedPolicy>; -template class Sink>; -template class FileSink>; -template class OStreamSink>; -template class NullSink>; +template class FileSink; +template class OStreamSink; +template class NullSink; template class RecordStringView; template class Pattern; template class CachedFormatter; @@ -44,10 +43,9 @@ template class FormatValue; // wchar_t template class SinkDriver, SingleThreadedPolicy>; template class SinkDriver, MultiThreadedPolicy>; -template class Sink>; -template class FileSink>; -template class OStreamSink>; -template class NullSink>; +template class FileSink; +template class OStreamSink; +template class NullSink; template class RecordStringView; template class Pattern; template class CachedFormatter; @@ -61,10 +59,9 @@ template class FormatValue; #ifdef SLIMLOG_CHAR8_T template class SinkDriver, SingleThreadedPolicy>; template class SinkDriver, MultiThreadedPolicy>; -template class Sink>; -template class FileSink>; -template class OStreamSink>; -template class NullSink>; +template class FileSink; +template class OStreamSink; +template class NullSink; template class RecordStringView; template class Pattern; template class CachedFormatter; @@ -75,10 +72,9 @@ template class CachedFormatter; #ifdef SLIMLOG_CHAR16_T template class SinkDriver, SingleThreadedPolicy>; template class SinkDriver, MultiThreadedPolicy>; -template class Sink>; -template class FileSink>; -template class OStreamSink>; -template class NullSink>; +template class FileSink; +template class OStreamSink; +template class NullSink; template class RecordStringView; template class Pattern; template class CachedFormatter; @@ -89,10 +85,10 @@ template class CachedFormatter; #ifdef SLIMLOG_CHAR32_T template class SinkDriver, SingleThreadedPolicy>; template class SinkDriver, MultiThreadedPolicy>; -template class Sink>; -template class FileSink>; -template class OStreamSink>; -template class NullSink>; +template class Sink; +template class FileSink; +template class OStreamSink; +template class NullSink; template class RecordStringView; template class Pattern; template class CachedFormatter;