Files
UNSWebServerCore_WindowsDLL/UNSWebServerCore/LogArg.h
T
2026-06-30 17:46:34 +08:00

254 lines
7.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include <ctime>
#include <string>
#include <vector>
#include <chrono>
#include <variant>
#include "Export.h"
#include <functional>
#include <string_view>
#include <type_traits>
namespace uns
{
// 前置声明捕获器
struct RangeCapturer;
struct PairCapturer;
struct FuncCapturer;
struct TimeCapturer;
// 终极 Variant 池:容纳所有可能解包出的原子形态
using LogVariant = std::variant<
bool, char, int, unsigned int, long long, unsigned long long, double, std::string_view, const void*,
std::string, // 专门用于承载宽字符转换后的 UTF-8 临时字符串
RangeCapturer, // 专门用于承载 std::vector / std::list 等容器
PairCapturer, // 专门用于承载 std::pair (支持 std::map)
FuncCapturer, //承载 std::function
TimeCapturer //承载时间
>;
// --- 编译期类型推导工具链 ---
template <typename T, typename = void>
struct is_container : std::false_type
{
};
// 识别标准容器(排除字符串本身)
template <typename T>
struct is_container<T, std::void_t<typename T::value_type, decltype(std::declval<T>().begin()), decltype(std::declval<T>().end())>> : std::integral_constant<bool, !std::is_same_v<T, std::string> && !std::is_same_v<T, std::string_view>>
{
};
template <typename T> struct is_pair : std::false_type
{
};
template <typename F, typename S> struct is_pair<std::pair<F, S>> : std::true_type
{
};
// --- 延迟桥接结构体 ---
struct LogArg;
struct RangeCapturer
{
const void* ptr;
void (*to_log_args)(const void*, std::vector<LogArg>&);
};
struct PairCapturer
{
const void* ptr;
void (*to_log_args)(const void*, std::vector<LogArg>&);
};
struct FuncCapturer
{
const void* code_ptr; // 真正改变:这里存真正的函数代码地址
bool is_closure; // 标记:这究竟是个纯函数,还是个 Lambda 闭包
};
// 升级版 Trait:不仅识别,还提取原生函数指针类型(R(*)(Args...))
template <typename T> struct function_traits
{
static constexpr bool is_func = false;
using pointer_type = void*;
};
template <typename R, typename... Args>
struct function_traits<std::function<R(Args...)>>
{
static constexpr bool is_func = true;
using pointer_type = R(*)(Args...); // 提取出原生函数指针类型
};
enum class TimeMode
{
Point,
TMPoint,
Duration
};
struct TimeCapturer
{
TimeMode mode{ TimeMode::Point };
std::tm _tm{};
std::chrono::system_clock::time_point tp{};
std::chrono::nanoseconds duration{ 0 };
std::string format_spec; // "%Y-%m-%d %H:%M:%S" or empty
// 可选:单位策略控制
bool smart_unit = true;
};
template<typename T>
struct is_time_point : std::false_type
{
};
template<typename Clock, typename Dur>
struct is_time_point<std::chrono::time_point<Clock, Dur>> : std::true_type
{
};
template<>
struct is_time_point<std::tm> : std::true_type
{
};
template<typename T>
inline constexpr bool is_time_point_v = is_time_point<T>::value;
template<typename T>
struct is_duration : std::false_type
{
};
template<typename Rep, typename Period>
struct is_duration<std::chrono::duration<Rep, Period>> : std::true_type
{
};
template<typename T>
inline constexpr bool is_duration_v = is_duration<T>::value;
inline TimeCapturer MakeTimeCapturer(std::chrono::system_clock::time_point tp)
{
TimeCapturer c;
c.mode = TimeMode::Point;
c.tp = tp;
return c;
}
template<typename Rep, typename Period>
inline TimeCapturer MakeTimeCapturer(std::chrono::duration<Rep, Period> d)
{
TimeCapturer c;
c.mode = TimeMode::Duration;
c.duration = std::chrono::duration_cast<std::chrono::nanoseconds>(d);
c.smart_unit = true;
return c;
}
inline TimeCapturer MakeTimeCapturer(const std::tm& tm)
{
TimeCapturer c;
c.mode = TimeMode::TMPoint;
c._tm = tm;
return c;
}
// --- 宽字符转换声明(实现卸载到 .cpp) ---
std::string UNSWSC_DLL_EXPORT ConvertWStringToUtf8(std::wstring_view wstr);
// --- 核心包装类 ---
struct LogArg
{
LogVariant value;
template<typename T>
LogArg(T&& val)
{
using D = std::decay_t<T>;
// 1. 窄字符串系列(0拷贝)
if constexpr (std::is_same_v<D, std::string> || std::is_same_v<D, std::string_view>)
value = std::string_view(val);
else if constexpr (std::is_same_v<D, const char*> || std::is_same_v<D, char*>)
value = val ? std::string_view(val) : std::string_view("<null>");
// 2. 宽字符串系列(特殊处理:触发内部 UTF-8 转换)
else if constexpr (std::is_same_v<D, std::wstring> || std::is_same_v<D, std::wstring_view>)
value = ConvertWStringToUtf8(val);
else if constexpr (std::is_same_v<D, const wchar_t*> || std::is_same_v<D, wchar_t*>)
value = val ? ConvertWStringToUtf8(val) : std::string("<null>");
// 3. 基础原子类型(防范 wchar_t 被误判为整数)
else if constexpr (std::is_same_v<D, wchar_t> || std::is_same_v<D, char16_t> || std::is_same_v<D, char32_t>)
value = ConvertWStringToUtf8(std::wstring_view((const wchar_t*)&val, 1));
else if constexpr (std::is_same_v<D, bool>)
value = static_cast<bool>(val);
else if constexpr (std::is_same_v<D, char> || std::is_same_v<D, signed char>)
value = static_cast<char>(val);
// 3.5 时间点类型系列(防止时间对象退化为未知类型)
else if constexpr (is_time_point_v<D>)
value = MakeTimeCapturer(val);
else if constexpr (is_duration_v<D>)
value = MakeTimeCapturer(val);
// 4. 全整型变种矩阵 (short, int, long, long long, unsigned...)
else if constexpr (std::is_integral_v<D> && std::is_signed_v<D>)
{
if constexpr (sizeof(D) <= sizeof(int))
value = static_cast<int>(val);
else
value = static_cast<long long>(val);
}
else if constexpr (std::is_integral_v<D> && std::is_unsigned_v<D>)
{
if constexpr (sizeof(D) <= sizeof(unsigned int))
value = static_cast<unsigned int>(val);
else
value = static_cast<unsigned long long>(val);
}
// 5. 浮点矩阵
else if constexpr (std::is_floating_point_v<D>)
value = static_cast<double>(val);
// 6. 指针
else if constexpr (std::is_pointer_v<D>)
value = static_cast<const void*>(val);
// 7. 标准库容器(关键点:利用 Lambda 闭包在不引入 fmt 的情况下擦除容器类型!)
else if constexpr (is_container<D>::value)
{
value = RangeCapturer{ &val, [] (const void* p, std::vector<LogArg>& out)
{
for (const auto& item : *static_cast<const D*>(p))
out.emplace_back(item); // 递归包装子元素
}
};
}
// 8. 键值对(支持 Map 展开)
else if constexpr (is_pair<D>::value)
{
value = PairCapturer{ &val, [] (const void* p, std::vector<LogArg>& out)
{
const auto& pair = *static_cast<const D*>(p);
out.emplace_back(pair.first);
out.emplace_back(pair.second);
}
};
}
else if constexpr (function_traits<D>::is_func)
{
using TargetPtr = typename function_traits<D>::pointer_type;
// 关键点:尝试用 target() 拿底层指针
// std::function::target<T>() 返回的是 T*,所以如果 T 是函数指针,返回的就是“函数指针的指针”
if (auto* const* func_ptr = val.template target<TargetPtr>()) // 情况 A:内部装的是普通纯函数或静态成员函数
value = FuncCapturer{ reinterpret_cast<const void*>(*func_ptr), false };
else // 情况 B:内部装的是 Lambda 表达式或带状态的仿函数, 此时它在堆/栈上有一个闭包实体,我们退而求其次,打印这个闭包对象的地址
value = FuncCapturer{ static_cast<const void*>(&val), true };
}
else
value = std::string_view("<unsupported type>");
}
};
}