From e704c082b762bb2d7b2d07dd681a9921baa1582e Mon Sep 17 00:00:00 2001
From: Patrick Wuttke
Date: Sat, 30 Aug 2025 00:29:16 +0200
Subject: [PATCH] Some fixes for logging, added MIJIN_LOG_IF and the
DebugOutputLogSink.
---
source/mijin/logging/debug_output_sink.hpp | 67 ++++++++++++++++++++++
source/mijin/logging/formatting.hpp | 4 +-
source/mijin/logging/logger.hpp | 11 +++-
source/mijin/logging/stdio_sink.hpp | 2 +-
4 files changed, 80 insertions(+), 4 deletions(-)
create mode 100644 source/mijin/logging/debug_output_sink.hpp
diff --git a/source/mijin/logging/debug_output_sink.hpp b/source/mijin/logging/debug_output_sink.hpp
new file mode 100644
index 0000000..54c900e
--- /dev/null
+++ b/source/mijin/logging/debug_output_sink.hpp
@@ -0,0 +1,67 @@
+
+#pragma once
+
+#if !defined(MIJIN_LOGGING_DEBUG_OUTPUT_SINK_HPP_INCLUDED)
+#define MIJIN_LOGGING_DEBUG_OUTPUT_SINK_HPP_INCLUDED 1
+
+#include "./formatting.hpp"
+#include "../detect.hpp"
+#include "../util/traits.hpp"
+
+#if MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
+#pragma comment(lib, "Kernel32.lib")
+
+extern "C" void OutputDebugStringA(const char* lpOutputString);
+extern "C" void OutputDebugStringW(const wchar_t* lpOutputString);
+
+namespace mijin
+{
+template
+ requires(allocator_type>)
+class BaseDebugOutputSink : 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;
+public:
+ explicit BaseDebugOutputSink(formatter_ptr_t formatter, allocator_t allocator = {})
+ MIJIN_NOEXCEPT_IF(std::is_nothrow_move_constructible_v)
+ : base_t(std::move(formatter), std::move(allocator)) {}
+
+ void handleMessageFormatted(const message_t&, const char_t* formatted) MIJIN_NOEXCEPT override
+ {
+ if constexpr (std::is_same_v)
+ {
+ OutputDebugStringA(formatted);
+ OutputDebugStringA("\n");
+ }
+ else if constexpr (std::is_same_v)
+ {
+ OutputDebugStringW(formatted);
+ OutputDebugStringW(L"\n");
+ }
+ else if constexpr (sizeof(char_t) == sizeof(char))
+ {
+ // char8_t etc.
+ OutputDebugStringA(std::bit_cast(formatted));
+ OutputDebugStringA("\n");
+ }
+ else
+ {
+ static_assert(always_false_v, "Character type not supported.");
+ }
+ }
+};
+
+#define SINK_SET_ARGS(chr_type) chr_type, std::char_traits, TAllocator, TDeleter
+
+MIJIN_DEFINE_CHAR_VERSIONS_TMPL(DebugOutputSink, MIJIN_FORMATTING_SINK_COMMON_ARGS, SINK_SET_ARGS)
+
+#undef SINK_SET_ARGS
+} // namespace mijin
+
+#endif // MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
+#endif // !defined(MIJIN_LOGGING_DEBUG_OUTPUT_SINK_HPP_INCLUDED)
diff --git a/source/mijin/logging/formatting.hpp b/source/mijin/logging/formatting.hpp
index ad3a6f8..cae956d 100644
--- a/source/mijin/logging/formatting.hpp
+++ b/source/mijin/logging/formatting.hpp
@@ -92,10 +92,10 @@ public:
using string_t = formatter_t::string_t;
using typename base_t::message_t;
private:
- not_null_t mFormatter;
+ formatter_ptr_t mFormatter;
string_t mBuffer;
public:
- explicit BaseFormattingLogSink(not_null_t formatter, allocator_t allocator = {})
+ explicit BaseFormattingLogSink(formatter_ptr_t formatter, allocator_t allocator = {})
MIJIN_NOEXCEPT_IF(std::is_nothrow_move_constructible_v)
: mFormatter(std::move(formatter)), mBuffer(std::move(allocator))
{}
diff --git a/source/mijin/logging/logger.hpp b/source/mijin/logging/logger.hpp
index 4904ae7..5de4045 100644
--- a/source/mijin/logging/logger.hpp
+++ b/source/mijin/logging/logger.hpp
@@ -254,10 +254,14 @@ MIJIN_DEFINE_LOG_LEVEL(ERROR, MIJIN_LOG_LEVEL_VALUE_ERROR)
#define MIJIN_LOG_ALWAYS(level, channel, ...) MIJIN_FUNCNAME_GET_LOGGER().log( \
MIJIN_LOG_LEVEL_OBJECT(level), MIJIN_LOG_CHANNEL_OBJECT(channel), std::source_location::current(), __VA_ARGS__ \
)
-#define MIJIN_LOG(level, channel, ...) \
+#define MIJIN_LOG(level, channel, ...) \
if constexpr (MIJIN_LOG_LEVEL_OBJECT(level).value < MIJIN_FUNCNAME_MIN_LOG_LEVEL_COMPILE()) {} \
else MIJIN_LOG_ALWAYS(level, channel, __VA_ARGS__)
+#define MIJIN_LOG_IF(cond, level, channel, ...) \
+if constexpr (MIJIN_LOG_LEVEL_OBJECT(level).value < MIJIN_FUNCNAME_MIN_LOG_LEVEL_COMPILE()) {} \
+else if (cond) MIJIN_LOG_ALWAYS(level, channel, __VA_ARGS__)
+
#define MIJIN_SET_CLASS_LOGGER(loggerExpr) \
const auto& MIJIN_FUNCNAME_GET_LOGGER() const noexcept \
{ \
@@ -268,6 +272,11 @@ auto MIJIN_FUNCNAME_GET_LOGGER = [&]() -> const auto& \
{ \
return loggerExpr; \
};
+#define MIJIN_SET_NS_LOGGER(loggerExpr) \
+inline const mijin::Logger& MIJIN_FUNCNAME_GET_LOGGER() \
+{ \
+ return loggerExpr; \
+}
#define MIJIN_SET_CLASS_MIN_LOG_LEVEL_COMPILE(level) \
int MIJIN_FUNCNAME_MIN_LOG_LEVEL_COMPILE() MIJIN_NOEXCEPT \
{ \
diff --git a/source/mijin/logging/stdio_sink.hpp b/source/mijin/logging/stdio_sink.hpp
index 7aa1e8c..423806a 100644
--- a/source/mijin/logging/stdio_sink.hpp
+++ b/source/mijin/logging/stdio_sink.hpp
@@ -22,7 +22,7 @@ public:
private:
int mMinStderrLevel = MIJIN_LOG_LEVEL_VALUE_WARNING;
public:
- explicit BaseStdioSink(not_null_t formatter, allocator_t allocator = {})
+ explicit BaseStdioSink(formatter_ptr_t formatter, allocator_t allocator = {})
MIJIN_NOEXCEPT_IF(std::is_nothrow_move_constructible_v)
: base_t(std::move(formatter), std::move(allocator)) {}