Files
log-for-c/log.h

386 lines
13 KiB
C
Raw Permalink 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.
#ifndef LOG_H
#define LOG_H
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
#include <locale.h>
#include <stdbool.h>
// ANSI颜色代码
#define COLOR_RESET "\033[0m"
#define COLOR_RED "\033[31m"
#define COLOR_GREEN "\033[32m"
#define COLOR_YELLOW "\033[33m"
#define COLOR_BLUE "\033[34m"
#define COLOR_MAGENTA "\033[35m"
#define COLOR_CYAN "\033[36m"
#define COLOR_WHITE "\033[37m"
#define COLOR_GRAY "\033[90m"
// 辅助函数声明
const char* get_color_code(const char* color_name);
void get_time_string(char* buffer, size_t size);
// 内部打印函数
static inline void _print_int(int x) { printf("%d", x); }
static inline void _print_uint(unsigned int x) { printf("%u", x); }
static inline void _print_short(short x) { printf("%hd", x); }
static inline void _print_ushort(unsigned short x) { printf("%hu", x); }
static inline void _print_long(long x) { printf("%ld", x); }
static inline void _print_ulong(unsigned long x) { printf("%lu", x); }
static inline void _print_long_long(long long x) { printf("%lld", x); }
static inline void _print_ulong_long(unsigned long long x) { printf("%llu", x); }
static inline void _print_double(double x) { printf("%.2f", x); }
static inline void _print_long_double(long double x) { printf("%.2Lf", x); }
static inline void _print_str(const char* x) { printf("%s", x); }
static inline void _print_char(int x) { printf("%c", x); }
static inline void _print_bool(_Bool x) { printf(x ? "true" : "false"); }
static inline void _print_wstr(const wchar_t* x) {
static int locale_set = 0;
if (!locale_set) {
setlocale(LC_ALL, "");
locale_set = 1;
}
wprintf(L"%ls", x);
}
// 类型自动打印使用C23的_Generic
#define PRINT_VALUE(x) _Generic((x), \
_Bool: _print_bool, \
short: _print_short, \
unsigned short: _print_ushort, \
int: _print_int, \
unsigned int: _print_uint, \
long: _print_long, \
unsigned long: _print_ulong, \
long long: _print_long_long, \
unsigned long long: _print_ulong_long, \
double: _print_double, \
float: _print_double, \
long double: _print_long_double, \
signed char: _print_char, \
unsigned char: _print_char, \
char: _print_char, \
char*: _print_str, \
const char*: _print_str, \
wchar_t*: _print_wstr, \
const wchar_t*: _print_wstr \
)(x)
// log函数重载 - 单参数
#define _log_1(x) do { PRINT_VALUE(x); printf("\n"); } while(0)
// 通用格式化分发fmt + 0~10 个参数)
#define _fmt_0(fmt) do { printf("%s\n", (fmt)); } while(0)
#define _GET_FMT_ARG(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,NAME,...) NAME
#define _fmt_print(...) _GET_FMT_ARG(__VA_ARGS__, \
_log_fmt_10, _log_fmt_9, _log_fmt_8, _log_fmt_7, _log_fmt_6, \
_log_fmt_5, _log_fmt_4, _log_fmt_3, _log_fmt_2, _log_fmt_1, _fmt_0)(__VA_ARGS__)
// log函数重载 - 格式化字符串 + 一个参数
#define _log_fmt_1(fmt, a) do { \
const char* _p = (fmt); \
int _done = 0; \
while (*_p) { \
if (*_p == '{' && *(_p+1) == '}' && !_done) { \
PRINT_VALUE(a); \
_done = 1; \
_p += 2; \
} else { \
putchar(*_p); \
_p++; \
} \
} \
printf("\n"); \
} while(0)
// log函数重载 - 格式化字符串 + 两个参数
#define _log_fmt_2(fmt, a, b) do { \
const char* _p = (fmt); \
int _done = 0; \
while (*_p) { \
if (*_p == '{' && *(_p+1) == '}') { \
if (_done == 0) { PRINT_VALUE(a); _done = 1; } \
else if (_done == 1) { PRINT_VALUE(b); _done = 2; } \
_p += 2; \
} else { \
putchar(*_p); \
_p++; \
} \
} \
printf("\n"); \
} while(0)
// 格式化字符串 + 三个参数
#define _log_fmt_3(fmt, a, b, c) do { \
const char* _p = (fmt); \
int _done = 0; \
while (*_p) { \
if (*_p == '{' && *(_p+1) == '}') { \
if (_done == 0) { PRINT_VALUE(a); _done = 1; } \
else if (_done == 1) { PRINT_VALUE(b); _done = 2; } \
else if (_done == 2) { PRINT_VALUE(c); _done = 3; } \
_p += 2; \
} else { \
putchar(*_p); \
_p++; \
} \
} \
printf("\n"); \
} while(0)
// 格式化字符串 + 四个参数
#define _log_fmt_4(fmt, a, b, c, d) do { \
const char* _p = (fmt); \
int _done = 0; \
while (*_p) { \
if (*_p == '{' && *(_p+1) == '}') { \
if (_done == 0) { PRINT_VALUE(a); _done = 1; } \
else if (_done == 1) { PRINT_VALUE(b); _done = 2; } \
else if (_done == 2) { PRINT_VALUE(c); _done = 3; } \
else if (_done == 3) { PRINT_VALUE(d); _done = 4; } \
_p += 2; \
} else { \
putchar(*_p); \
_p++; \
} \
} \
printf("\n"); \
} while(0)
// 格式化字符串 + 五个参数
#define _log_fmt_5(fmt, a, b, c, d, e) do { \
const char* _p = (fmt); \
int _done = 0; \
while (*_p) { \
if (*_p == '{' && *(_p+1) == '}') { \
if (_done == 0) { PRINT_VALUE(a); _done = 1; } \
else if (_done == 1) { PRINT_VALUE(b); _done = 2; } \
else if (_done == 2) { PRINT_VALUE(c); _done = 3; } \
else if (_done == 3) { PRINT_VALUE(d); _done = 4; } \
else if (_done == 4) { PRINT_VALUE(e); _done = 5; } \
_p += 2; \
} else { \
putchar(*_p); \
_p++; \
} \
} \
printf("\n"); \
} while(0)
// 格式化字符串 + 六个参数
#define _log_fmt_6(fmt, a, b, c, d, e, f) do { \
const char* _p = (fmt); \
int _done = 0; \
while (*_p) { \
if (*_p == '{' && *(_p+1) == '}') { \
if (_done == 0) { PRINT_VALUE(a); _done = 1; } \
else if (_done == 1) { PRINT_VALUE(b); _done = 2; } \
else if (_done == 2) { PRINT_VALUE(c); _done = 3; } \
else if (_done == 3) { PRINT_VALUE(d); _done = 4; } \
else if (_done == 4) { PRINT_VALUE(e); _done = 5; } \
else if (_done == 5) { PRINT_VALUE(f); _done = 6; } \
_p += 2; \
} else { \
putchar(*_p); \
_p++; \
} \
} \
printf("\n"); \
} while(0)
// 格式化字符串 + 七个参数
#define _log_fmt_7(fmt, a, b, c, d, e, f, g) do { \
const char* _p = (fmt); \
int _done = 0; \
while (*_p) { \
if (*_p == '{' && *(_p+1) == '}') { \
if (_done == 0) { PRINT_VALUE(a); _done = 1; } \
else if (_done == 1) { PRINT_VALUE(b); _done = 2; } \
else if (_done == 2) { PRINT_VALUE(c); _done = 3; } \
else if (_done == 3) { PRINT_VALUE(d); _done = 4; } \
else if (_done == 4) { PRINT_VALUE(e); _done = 5; } \
else if (_done == 5) { PRINT_VALUE(f); _done = 6; } \
else if (_done == 6) { PRINT_VALUE(g); _done = 7; } \
_p += 2; \
} else { \
putchar(*_p); \
_p++; \
} \
} \
printf("\n"); \
} while(0)
// 格式化字符串 + 八个参数
#define _log_fmt_8(fmt, a, b, c, d, e, f, g, h) do { \
const char* _p = (fmt); \
int _done = 0; \
while (*_p) { \
if (*_p == '{' && *(_p+1) == '}') { \
if (_done == 0) { PRINT_VALUE(a); _done = 1; } \
else if (_done == 1) { PRINT_VALUE(b); _done = 2; } \
else if (_done == 2) { PRINT_VALUE(c); _done = 3; } \
else if (_done == 3) { PRINT_VALUE(d); _done = 4; } \
else if (_done == 4) { PRINT_VALUE(e); _done = 5; } \
else if (_done == 5) { PRINT_VALUE(f); _done = 6; } \
else if (_done == 6) { PRINT_VALUE(g); _done = 7; } \
else if (_done == 7) { PRINT_VALUE(h); _done = 8; } \
_p += 2; \
} else { \
putchar(*_p); \
_p++; \
} \
} \
printf("\n"); \
} while(0)
// 格式化字符串 + 九个参数
#define _log_fmt_9(fmt, a, b, c, d, e, f, g, h, i) do { \
const char* _p = (fmt); \
int _done = 0; \
while (*_p) { \
if (*_p == '{' && *(_p+1) == '}') { \
if (_done == 0) { PRINT_VALUE(a); _done = 1; } \
else if (_done == 1) { PRINT_VALUE(b); _done = 2; } \
else if (_done == 2) { PRINT_VALUE(c); _done = 3; } \
else if (_done == 3) { PRINT_VALUE(d); _done = 4; } \
else if (_done == 4) { PRINT_VALUE(e); _done = 5; } \
else if (_done == 5) { PRINT_VALUE(f); _done = 6; } \
else if (_done == 6) { PRINT_VALUE(g); _done = 7; } \
else if (_done == 7) { PRINT_VALUE(h); _done = 8; } \
else if (_done == 8) { PRINT_VALUE(i); _done = 9; } \
_p += 2; \
} else { \
putchar(*_p); \
_p++; \
} \
} \
printf("\n"); \
} while(0)
// 格式化字符串 + 十个参数
#define _log_fmt_10(fmt, a, b, c, d, e, f, g, h, i, j) do { \
const char* _p = (fmt); \
int _done = 0; \
while (*_p) { \
if (*_p == '{' && *(_p+1) == '}') { \
if (_done == 0) { PRINT_VALUE(a); _done = 1; } \
else if (_done == 1) { PRINT_VALUE(b); _done = 2; } \
else if (_done == 2) { PRINT_VALUE(c); _done = 3; } \
else if (_done == 3) { PRINT_VALUE(d); _done = 4; } \
else if (_done == 4) { PRINT_VALUE(e); _done = 5; } \
else if (_done == 5) { PRINT_VALUE(f); _done = 6; } \
else if (_done == 6) { PRINT_VALUE(g); _done = 7; } \
else if (_done == 7) { PRINT_VALUE(h); _done = 8; } \
else if (_done == 8) { PRINT_VALUE(i); _done = 9; } \
else if (_done == 9) { PRINT_VALUE(j); _done = 10; } \
_p += 2; \
} else { \
putchar(*_p); \
_p++; \
} \
} \
printf("\n"); \
} while(0)
// 主log宏 - 支持最多11个参数格式化字符串 + 10个变量
#define _GET_11TH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, N, ...) N
#define log(...) _GET_11TH_ARG(__VA_ARGS__, \
_log_fmt_10, _log_fmt_9, _log_fmt_8, _log_fmt_7, _log_fmt_6, \
_log_fmt_5, _log_fmt_4, _log_fmt_3, _log_fmt_2, _log_fmt_1, _log_1)(__VA_ARGS__)
// 颜色log
#define clog(color, msg) do { \
printf("%s", get_color_code(color)); \
PRINT_VALUE(msg); \
printf("%s\n", COLOR_RESET); \
} while(0)
// 颜色log格式化
#define clog_f(color, ...) do { \
printf("%s", get_color_code(color)); \
_fmt_print(__VA_ARGS__); \
printf("%s", COLOR_RESET); \
} while(0)
// 日志等级宏
#define logerr(msg) do { \
char time_str[64]; \
get_time_string(time_str, sizeof(time_str)); \
printf("%s[%s ERROR]%s ", COLOR_RED, time_str, COLOR_RESET); \
PRINT_VALUE(msg); \
printf("\n"); \
} while(0)
#define logerr_f(...) do { \
char time_str[64]; \
get_time_string(time_str, sizeof(time_str)); \
printf("%s[%s ERROR]%s ", COLOR_RED, time_str, COLOR_RESET); \
_fmt_print(__VA_ARGS__); \
} while(0)
#define logok(msg) do { \
char time_str[64]; \
get_time_string(time_str, sizeof(time_str)); \
printf("%s[%s OK]%s ", COLOR_GREEN, time_str, COLOR_RESET); \
PRINT_VALUE(msg); \
printf("\n"); \
} while(0)
#define logok_f(...) do { \
char time_str[64]; \
get_time_string(time_str, sizeof(time_str)); \
printf("%s[%s OK]%s ", COLOR_GREEN, time_str, COLOR_RESET); \
_fmt_print(__VA_ARGS__); \
} while(0)
#define loginfo(msg) do { \
char time_str[64]; \
get_time_string(time_str, sizeof(time_str)); \
printf("%s[%s INFO]%s ", COLOR_CYAN, time_str, COLOR_RESET); \
PRINT_VALUE(msg); \
printf("\n"); \
} while(0)
#define loginfo_f(...) do { \
char time_str[64]; \
get_time_string(time_str, sizeof(time_str)); \
printf("%s[%s INFO]%s ", COLOR_CYAN, time_str, COLOR_RESET); \
_fmt_print(__VA_ARGS__); \
} while(0)
#define logwarn(msg) do { \
char time_str[64]; \
get_time_string(time_str, sizeof(time_str)); \
printf("%s[%s WARN]%s ", COLOR_YELLOW, time_str, COLOR_RESET); \
PRINT_VALUE(msg); \
printf("\n"); \
} while(0)
#define logwarn_f(...) do { \
char time_str[64]; \
get_time_string(time_str, sizeof(time_str)); \
printf("%s[%s WARN]%s ", COLOR_YELLOW, time_str, COLOR_RESET); \
_fmt_print(__VA_ARGS__); \
} while(0)
#define logdebug(msg) do { \
char time_str[64]; \
get_time_string(time_str, sizeof(time_str)); \
printf("%s[%s DEBUG]%s ", COLOR_GRAY, time_str, COLOR_RESET); \
PRINT_VALUE(msg); \
printf("\n"); \
} while(0)
#define logdebug_f(...) do { \
char time_str[64]; \
get_time_string(time_str, sizeof(time_str)); \
printf("%s[%s DEBUG]%s ", COLOR_GRAY, time_str, COLOR_RESET); \
_fmt_print(__VA_ARGS__); \
} while(0)
#endif