From 5f1e85d77efc672d0f3d19595e24789f744a9c60 Mon Sep 17 00:00:00 2001 From: flipflip Date: Wed, 14 Jan 2026 14:05:16 +0100 Subject: [PATCH 1/3] Add LoggingOstream to make a std::ostream that prints to logging --- fpsdk_common/include/fpsdk_common/logging.hpp | 44 +++++++++++++++++++ fpsdk_common/src/logging.cpp | 28 ++++++++++++ 2 files changed, 72 insertions(+) diff --git a/fpsdk_common/include/fpsdk_common/logging.hpp b/fpsdk_common/include/fpsdk_common/logging.hpp index 6e564fb..402b45c 100644 --- a/fpsdk_common/include/fpsdk_common/logging.hpp +++ b/fpsdk_common/include/fpsdk_common/logging.hpp @@ -359,6 +359,50 @@ void LoggingPrint(const LoggingLevel level, const std::size_t repeat, const char void LoggingHexdump(const LoggingLevel level, const uint8_t* data, const std::size_t size, const char* prefix, const char* fmt, ...) PRINTF_ATTR(5); +/** + * @brief Utility to create a std::ostream that prints through the logging system + * + * For example: + * + * @code{cpp} + * auto w = LoggingOstream(LoggingLevel::WARNING); + * *w << "Hello world!" << std::endl; // This should print: Warning: Hello world! + * @endcode + * + * @note Flusing the stream is required for the log message to be printed. Typically, std::endl flushes. Otherwise + * explicitly flush using std::flush when appropriate. + */ +class LoggingOstream +{ + public: + /** + * @brief Constructor + * + * @param[in] level The logging level to use + */ + LoggingOstream(const LoggingLevel level); + + /** + * @brief Get stream handle + * + * @returns the stream handle + */ + std::ostream& operator*() + { + return str_; + } + + private: + //! Helper buffer that prints through logging + struct StrBuf : public std::stringbuf + { + virtual int sync(); //!< Print function implementation + LoggingLevel level_; //!< Logging level + }; + StrBuf buf_; //!< Helper buffer + std::ostream str_; //!< Stream handle +}; + // Helper macros #ifndef _DOXYGEN_ # define _FPSDK_LOGGING_LOG(_level_, ...) \ diff --git a/fpsdk_common/src/logging.cpp b/fpsdk_common/src/logging.cpp index ac72237..beb6837 100644 --- a/fpsdk_common/src/logging.cpp +++ b/fpsdk_common/src/logging.cpp @@ -360,6 +360,34 @@ void LoggingHexdump( } } +// --------------------------------------------------------------------------------------------------------------------- + +LoggingOstream::LoggingOstream(const LoggingLevel level) : str_{ &buf_ } +{ + buf_.level_ = level; +} + +int LoggingOstream::StrBuf::sync() +{ + // Print each line + const auto s = this->str(); + std::size_t offs = 0; + std::size_t pos = 0; + while ((pos = s.find("\n", offs)) != std::string::npos) { + switch (level_) { // clang-format off + case LoggingLevel::FATAL: FATAL("%s", s.substr(offs, pos).c_str()); break; + case LoggingLevel::ERROR: ERROR("%s", s.substr(offs, pos).c_str()); break; + case LoggingLevel::WARNING: WARNING("%s", s.substr(offs, pos).c_str()); break; + case LoggingLevel::NOTICE: NOTICE("%s", s.substr(offs, pos).c_str()); break; + case LoggingLevel::INFO: INFO("%s", s.substr(offs, pos).c_str()); break; + case LoggingLevel::DEBUG: DEBUG("%s", s.substr(offs, pos).c_str()); break; + case LoggingLevel::TRACE: TRACE("%s", s.substr(offs, pos).c_str()); break; + } // clang-format on + offs = pos + 1; + } + return 0; +} + /* ****************************************************************************************************************** */ } // namespace logging } // namespace common From 5292847b1daf3eb5a31352613045dfc9b3a9904a Mon Sep 17 00:00:00 2001 From: flipflip Date: Wed, 14 Jan 2026 14:06:09 +0100 Subject: [PATCH 2/3] beautify --- fpsdk_common/src/logging.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fpsdk_common/src/logging.cpp b/fpsdk_common/src/logging.cpp index beb6837..123c609 100644 --- a/fpsdk_common/src/logging.cpp +++ b/fpsdk_common/src/logging.cpp @@ -375,13 +375,13 @@ int LoggingOstream::StrBuf::sync() std::size_t pos = 0; while ((pos = s.find("\n", offs)) != std::string::npos) { switch (level_) { // clang-format off - case LoggingLevel::FATAL: FATAL("%s", s.substr(offs, pos).c_str()); break; - case LoggingLevel::ERROR: ERROR("%s", s.substr(offs, pos).c_str()); break; + case LoggingLevel::FATAL: FATAL( "%s", s.substr(offs, pos).c_str()); break; + case LoggingLevel::ERROR: ERROR( "%s", s.substr(offs, pos).c_str()); break; case LoggingLevel::WARNING: WARNING("%s", s.substr(offs, pos).c_str()); break; - case LoggingLevel::NOTICE: NOTICE("%s", s.substr(offs, pos).c_str()); break; - case LoggingLevel::INFO: INFO("%s", s.substr(offs, pos).c_str()); break; - case LoggingLevel::DEBUG: DEBUG("%s", s.substr(offs, pos).c_str()); break; - case LoggingLevel::TRACE: TRACE("%s", s.substr(offs, pos).c_str()); break; + case LoggingLevel::NOTICE: NOTICE( "%s", s.substr(offs, pos).c_str()); break; + case LoggingLevel::INFO: INFO( "%s", s.substr(offs, pos).c_str()); break; + case LoggingLevel::DEBUG: DEBUG( "%s", s.substr(offs, pos).c_str()); break; + case LoggingLevel::TRACE: TRACE( "%s", s.substr(offs, pos).c_str()); break; } // clang-format on offs = pos + 1; } From 4f05f4ea986f4a4376107dc21cc901690756f687 Mon Sep 17 00:00:00 2001 From: flipflip Date: Wed, 14 Jan 2026 14:08:17 +0100 Subject: [PATCH 3/3] typo --- fpsdk_common/include/fpsdk_common/logging.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpsdk_common/include/fpsdk_common/logging.hpp b/fpsdk_common/include/fpsdk_common/logging.hpp index 402b45c..b4079c7 100644 --- a/fpsdk_common/include/fpsdk_common/logging.hpp +++ b/fpsdk_common/include/fpsdk_common/logging.hpp @@ -369,7 +369,7 @@ void LoggingHexdump(const LoggingLevel level, const uint8_t* data, const std::si * *w << "Hello world!" << std::endl; // This should print: Warning: Hello world! * @endcode * - * @note Flusing the stream is required for the log message to be printed. Typically, std::endl flushes. Otherwise + * @note Flushing the stream is required for the log message to be printed. Typically, std::endl flushes. Otherwise * explicitly flush using std::flush when appropriate. */ class LoggingOstream