From c5c625f50e9672ce77e838ffa63d3e68e3c3cd38 Mon Sep 17 00:00:00 2001 From: youmetme <321640253@qq.com> Date: Fri, 17 Oct 2025 14:55:41 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E7=B3=BB=E7=BB=9F=EF=BC=8C=E7=BB=9F=E4=B8=80=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E6=8E=A5=E5=8F=A3=E5=B9=B6=E6=B7=BB=E5=8A=A0map?= =?UTF-8?q?=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/logging.h | 45 +++---- include/logging/logging-core.h | 8 ++ src/logging.c | 235 ++++++++++----------------------- src/utils/logging-map.c | 124 +++++++++++++++++ src/utils/logging-map.h | 37 ++++++ tests/CMakeLists.txt | 8 ++ tests/test-filter.c | 2 - tests/test-log-file.c | 1 - tests/test-map.c | 17 +++ tests/test-simple.c | 2 - 10 files changed, 284 insertions(+), 195 deletions(-) create mode 100644 src/utils/logging-map.c create mode 100644 src/utils/logging-map.h create mode 100644 tests/test-map.c diff --git a/include/logging.h b/include/logging.h index d3f14d9..174b4e8 100644 --- a/include/logging.h +++ b/include/logging.h @@ -15,27 +15,27 @@ extern "C" { // 默认日志器宏 #define Log_fatal(format, ...) \ - _log_fatal(NULL, __FILE__, __LINE__, format, ##__VA_ARGS__) + logMessage(NULL, LOG_FATAL, __FILE__, __LINE__, format, ##__VA_ARGS__) #define Log_error(format, ...) \ - _log_error(NULL, __FILE__, __LINE__, format, ##__VA_ARGS__) + logMessage(NULL, LOG_ERROR, __FILE__, __LINE__, format, ##__VA_ARGS__) #define Log_warning(format, ...) \ - _log_warning(NULL, __FILE__, __LINE__, format, ##__VA_ARGS__) + logMessage(NULL, LOG_WARNING, __FILE__, __LINE__, format, ##__VA_ARGS__) #define Log_info(format, ...) \ - _log_info(NULL, __FILE__, __LINE__, format, ##__VA_ARGS__) + logMessage(NULL, LOG_INFO, __FILE__, __LINE__, format, ##__VA_ARGS__) #define Log_debug(format, ...) \ - _log_debug(NULL, __FILE__, __LINE__, format, ##__VA_ARGS__) + logMessage(NULL, LOG_DEBUG, __FILE__, __LINE__, format, ##__VA_ARGS__) // 日志器宏 #define log_fatal(logger, format, ...) \ - _log_fatal(logger, __FILE__, __LINE__, format, ##__VA_ARGS__) + logMessage(logger, LOG_FATAL, __FILE__, __LINE__, format, ##__VA_ARGS__) #define log_error(logger, format, ...) \ - _log_error(logger, __FILE__, __LINE__, format, ##__VA_ARGS__) + logMessage(logger, LOG_ERROR, __FILE__, __LINE__, format, ##__VA_ARGS__) #define log_warning(logger, format, ...) \ - _log_warning(logger, __FILE__, __LINE__, format, ##__VA_ARGS__) + logMessage(logger, LOG_WARNING, __FILE__, __LINE__, format, ##__VA_ARGS__) #define log_info(logger, format, ...) \ - _log_info(logger, __FILE__, __LINE__, format, ##__VA_ARGS__) + logMessage(logger, LOG_INFO, __FILE__, __LINE__, format, ##__VA_ARGS__) #define log_debug(logger, format, ...) \ - _log_debug(logger, __FILE__, __LINE__, format, ##__VA_ARGS__) + logMessage(logger, LOG_DEBUG, __FILE__, __LINE__, format, ##__VA_ARGS__) typedef struct Logger { log_level level; @@ -47,24 +47,19 @@ typedef struct Logger { bool addHandler(Logger *logger, log_Handler *handler); bool addFilter(Logger *logger, log_filter *filter); -void _log_fatal( - Logger *logger, const char *file, int line, const char *format, ...); -void _log_error( - Logger *logger, const char *file, int line, const char *format, ...); -void _log_warning( - Logger *logger, const char *file, int line, const char *format, ...); -void _log_info( - Logger *logger, const char *file, int line, const char *format, ...); -void _log_debug( - Logger *logger, const char *file, int line, const char *format, ...); +void logMessage(Logger *logger, + log_level level, + const char *file, + int line, + const char *message, + ...); /** - * @brief 初始化默认日志对象 - * @param name 日志名称 - * @param level 日志等级 + * @brief 创建一个日志句柄对象 + * @param name 日志器名称 + * @return 日志句柄对象 */ -void initDefaultLogger(const char *name, log_level level); - +Logger *newLogger(const char *name); /** * @brief 获取默认日志对象 * @return 默认日志对象 diff --git a/include/logging/logging-core.h b/include/logging/logging-core.h index 8bcb614..4ec27f9 100644 --- a/include/logging/logging-core.h +++ b/include/logging/logging-core.h @@ -13,6 +13,14 @@ typedef enum { LOG_DEBUG, } log_level; +static const char *LOG_LEVEL_STR[] = { + "FATAL", + "ERROR", + "WARNING", + "INFO", + "DEBUG", +}; + typedef enum { L_ERROR, L_OK, diff --git a/src/logging.c b/src/logging.c index ff05ef0..1929b23 100644 --- a/src/logging.c +++ b/src/logging.c @@ -1,6 +1,7 @@ #include "logging.h" #include "logging/logging-core.h" #include "logging/logging-handler.h" +#include "utils/logging-map.h" #include "utils/logging-utils.h" #include #include @@ -18,7 +19,7 @@ #define LOG_BUFFER_SIZE 4096 // 日志缓冲区大小,单个日志长度不能超过该值 -static Logger *G_LOGGER = NULL; // 全局日志对象,唯一实例 +static Logger *ROOT_LOGGER = NULL; // 根日志对象,唯一实例 /** * @brief 为日志添加一个handler @@ -80,22 +81,15 @@ static void output_to_handler(Logger *logger, char *level, const char *color, const char *message) { - Logger *_logger = NULL; - - if (logger != NULL) { - _logger = logger; - } else { - _logger = G_LOGGER; - } char timeStr[20]; getTimeStr(timeStr); char logStr[LOG_BUFFER_SIZE * 2]; - if (_logger->handler->apply_color) { + if (logger->handler->apply_color) { snprintf(logStr, LOG_BUFFER_SIZE * 2, "[%s]: %s %s%s%s %s\n", - _logger->name, + logger->name, timeStr, color, level, @@ -105,13 +99,13 @@ static void output_to_handler(Logger *logger, snprintf(logStr, LOG_BUFFER_SIZE * 2, "[%s]: %s %s %s\n", - _logger->name, + logger->name, timeStr, level, message); } - _logger->handler->output(_logger->handler, logStr); + logger->handler->output(logger->handler, logStr); } /** @@ -124,174 +118,105 @@ static void output_to_handler(Logger *logger, */ static void log_cope(Logger *logger, char *level, const char *color, const char *message) { - Logger *_logger = NULL; - - if (logger != NULL) { - _logger = logger; - } else { - _logger = G_LOGGER; - } - - if (_logger == NULL) { + if (logger == NULL) { return; } - if (_logger->handler == NULL) { + if (logger->handler == NULL) { return; } - log_filter *it = _logger->filter; - log_Handler *handler = _logger->handler; + log_filter *it = logger->filter; + log_Handler *handler = logger->handler; while (it != NULL) { - if (it->_dispose(it, _logger->level, message)) { - output_to_handler(_logger, level, color, message); + if (it->_dispose(it, logger->level, message)) { + output_to_handler(logger, level, color, message); if (it->jump_out) { return; } } it = it->next; } - output_to_handler(_logger, level, color, message); + output_to_handler(logger, level, color, message); } -void _log_fatal( - Logger *logger, const char *file, int line, const char *message, ...) { +void logMessage(Logger *logger, + log_level level, + const char *file, + int line, + const char *message, + ...) { Logger *_logger = NULL; - - if (logger != NULL) { - _logger = logger; + if (logger == NULL) { + if (ROOT_LOGGER == NULL) { + ROOT_LOGGER = newLogger("ROOT"); // 创建根日志对象 + } + _logger = ROOT_LOGGER; } else { - _logger = G_LOGGER; + _logger = logger; // 使用传入的日志对象 } - if (_logger->level >= LOG_ERROR) { - char logStr[LOG_BUFFER_SIZE]; - char finalLogStr[LOG_BUFFER_SIZE * 2]; + if (_logger->level >= level) { + char logStr + [LOG_BUFFER_SIZE]; // 定义一个缓冲区,用于存储格式化后的日志字符串 + char finalLogStr[LOG_BUFFER_SIZE * + 2]; // 定义一个缓冲区,用于存储最终输出的日志字符串 va_list args; va_start(args, message); vsprintf(logStr, message, args); va_end(args); snprintf( finalLogStr, LOG_BUFFER_SIZE * 2, "[%s:%d] %s", file, line, logStr); - log_cope(_logger, "Fatal", RED_B, finalLogStr); - } -} -void _log_error( - Logger *logger, const char *file, int line, const char *message, ...) { - Logger *_logger = NULL; - - if (logger != NULL) { - _logger = logger; - } else { - _logger = G_LOGGER; - } - - if (_logger->level >= LOG_ERROR) { - char logStr[LOG_BUFFER_SIZE]; - char finalLogStr[LOG_BUFFER_SIZE * 2]; - va_list args; - va_start(args, message); - vsprintf(logStr, message, args); - va_end(args); - snprintf( - finalLogStr, LOG_BUFFER_SIZE * 2, "[%s:%d] %s", file, line, logStr); - log_cope(_logger, "Error", RED, finalLogStr); - } -} - -void _log_warning( - Logger *logger, const char *file, int line, const char *message, ...) { - Logger *_logger = NULL; - - if (logger != NULL) { - _logger = logger; - } else { - _logger = G_LOGGER; - } - - if (_logger->level >= LOG_WARNING) { - char logStr[LOG_BUFFER_SIZE]; - char finalLogStr[LOG_BUFFER_SIZE * 2]; - va_list args; - va_start(args, message); - vsprintf(logStr, message, args); - va_end(args); - snprintf( - finalLogStr, LOG_BUFFER_SIZE * 2, "[%s:%d] %s", file, line, logStr); - log_cope(_logger, "Warning", YELLOW, finalLogStr); - } -} - -void _log_info( - Logger *logger, const char *file, int line, const char *message, ...) { - Logger *_logger = NULL; - - if (logger != NULL) { - _logger = logger; - } else { - _logger = G_LOGGER; - } - - if (_logger->level >= LOG_INFO) { - char logStr[LOG_BUFFER_SIZE]; - char finalLogStr[LOG_BUFFER_SIZE * 2]; - va_list args; - va_start(args, message); - vsprintf(logStr, message, args); - va_end(args); - snprintf( - finalLogStr, LOG_BUFFER_SIZE * 2, "[%s:%d] %s", file, line, logStr); - log_cope(_logger, "Info", GREEN, finalLogStr); - } -} - -void _log_debug( - Logger *logger, const char *file, int line, const char *message, ...) { - Logger *_logger = NULL; - - if (logger != NULL) { - _logger = logger; - } else { - _logger = G_LOGGER; - } - - if (_logger->level >= LOG_DEBUG) { - char logStr[LOG_BUFFER_SIZE]; - char finalLogStr[LOG_BUFFER_SIZE * 2]; - va_list args; - va_start(args, message); - vsprintf(logStr, message, args); - va_end(args); - snprintf( - finalLogStr, LOG_BUFFER_SIZE * 2, "[%s:%d] %s", file, line, logStr); - log_cope(_logger, "Debug", CYAN, finalLogStr); + switch (level) { + case LOG_DEBUG: + log_cope(_logger, "Debug", BLUE, finalLogStr); + break; + case LOG_INFO: + log_cope(_logger, "Info", GREEN, finalLogStr); + break; + case LOG_WARNING: + log_cope(_logger, "Warning", YELLOW, finalLogStr); + break; + case LOG_ERROR: + log_cope(_logger, "Error", RED, finalLogStr); + break; + case LOG_FATAL: + log_cope(_logger, "Fatal", RED_B, finalLogStr); + break; + default: + break; + } } } /** - * @brief 初始化默认日志器 + * @brief 创建一个日志句柄 * @param name 日志器名称 - * @param level 日志等级 * @return 日志器对象 */ -void initDefaultLogger(const char *name, log_level level) { - if (G_LOGGER != NULL) { - G_LOGGER->name = name; - G_LOGGER->level = level; +Logger *newLogger(const char *name) { + Logger *logger = (Logger *)malloc(sizeof(Logger)); + if (logger == NULL) { + return NULL; } - Logger *logger = (Logger *)malloc(sizeof(Logger)); - - logger->level = level; + logger->level = LOG_INFO; logger->handler = loggingHandlerConsole(); logger->name = name; logger->filter = NULL; - G_LOGGER = logger; + return logger; } -Logger *getDefaultLogger(void) { return G_LOGGER; } +Logger *getDefaultLogger(void) { + if (ROOT_LOGGER != NULL) { + return ROOT_LOGGER; + } + + ROOT_LOGGER = newLogger("ROOT"); + return ROOT_LOGGER; +} /** * @brief 获取日志器对象 @@ -314,30 +239,6 @@ Logger *getLogger(const char *name, log_level level) { return logger; } -/** - * @brief 销毁日志对象 - */ -void destroyDefaultLogger(void) { - if (G_LOGGER != NULL) { - if (G_LOGGER->handler != NULL) { - G_LOGGER->handler->_free(G_LOGGER->handler); - } - - if (G_LOGGER->filter != NULL) { - log_filter *it = G_LOGGER->filter; - log_filter *next = NULL; - while (it != NULL) { - next = it->next; - it->_free(it); - it = next; - } - } - - free(G_LOGGER); - G_LOGGER = NULL; - } -} - void destroyLogger(Logger *logger) { if (logger != NULL) { if (logger->handler != NULL) { @@ -353,7 +254,11 @@ void destroyLogger(Logger *logger) { it = next; } } - free(logger); } -} \ No newline at end of file +} + +/** + * @brief 销毁日志对象 + */ +void destroyDefaultLogger(void) { destroyLogger(ROOT_LOGGER); } \ No newline at end of file diff --git a/src/utils/logging-map.c b/src/utils/logging-map.c new file mode 100644 index 0000000..8aa5bba --- /dev/null +++ b/src/utils/logging-map.c @@ -0,0 +1,124 @@ +#include "logging-map.h" + +#include +#include + +/* 哈希函数:FNV-1a */ +static uint32_t hash_bytes(const void *data, size_t len) { + const uint8_t *p = data; + uint32_t h = 2166136261u; + while (len--) { + h ^= *p++; + h *= 16777619u; + } + return h; +} + +/* 创建空 map */ +Map *map_create(size_t key_len, size_t value_len) { + Map *m = calloc(1, sizeof(*m)); + m->key_len = key_len; + m->value_len = value_len; + m->bucket_cap = 8; /* 初始桶数 */ + m->bucket = calloc(m->bucket_cap, sizeof(Node *)); + return m; +} + +/* 根据 key 找到桶下标 */ +static size_t bucket_index(Map *m, const void *key) { + uint32_t h = hash_bytes(key, m->key_len); + return h & (m->bucket_cap - 1); /* 要求 bucket_cap 是 2 的幂 */ +} + +/* 在桶链中线性查找 */ +static Node *find_in_chain(Node *head, const void *key, size_t key_len) { + for (; head; head = head->next) { + if (memcmp(head->kv, key, key_len) == 0) { + return head; + } + } + return NULL; +} + +/* 扩容:2× 桶数,重新哈希所有节点 */ +static void map_resize(Map *m) { + size_t new_cap = m->bucket_cap * 2; + Node **new_bucket = calloc(new_cap, sizeof(Node *)); + + for (size_t i = 0; i < m->bucket_cap; ++i) { + Node *node = m->bucket[i]; + while (node) { + Node *next = node->next; + size_t idx = hash_bytes(node->kv, m->key_len) & (new_cap - 1); + node->next = new_bucket[idx]; + new_bucket[idx] = node; + node = next; + } + } + free(m->bucket); + m->bucket = new_bucket; + m->bucket_cap = new_cap; +} + +/* 插入或覆盖 */ +void map_put(Map *m, const void *key, const void *value) { + if (m->size * 4 >= m->bucket_cap * 3) { /* 装载因子 0.75 */ + map_resize(m); + } + + size_t idx = bucket_index(m, key); + Node *node = find_in_chain(m->bucket[idx], key, m->key_len); + + if (node) { /* 覆盖旧值 */ + memcpy(node->kv + m->key_len, value, m->value_len); + return; + } + + /* 新建节点 */ + node = malloc(sizeof(*node)); + node->kv = malloc(m->key_len + m->value_len); + node->next = m->bucket[idx]; + memcpy(node->kv, key, m->key_len); + memcpy(node->kv + m->key_len, value, m->value_len); + m->bucket[idx] = node; + ++m->size; +} + +/* 查找 */ +void *map_get(Map *m, const void *key) { + size_t idx = bucket_index(m, key); + Node *node = find_in_chain(m->bucket[idx], key, m->key_len); + return node ? (node->kv + m->key_len) : NULL; +} + +/* 删除 */ +bool map_erase(Map *m, const void *key) { + size_t idx = bucket_index(m, key); + Node **link = &m->bucket[idx]; + for (; *link; link = &(*link)->next) { + if (memcmp((*link)->kv, key, m->key_len) == 0) { + Node *to_del = *link; + *link = to_del->next; + free(to_del->kv); + free(to_del); + --m->size; + return true; + } + } + return false; +} + +/* 销毁 */ +void map_destroy(Map *m) { + for (size_t i = 0; i < m->bucket_cap; ++i) { + Node *node = m->bucket[i]; + while (node) { + Node *next = node->next; + free(node->kv); + free(node); + node = next; + } + } + free(m->bucket); + free(m); +} \ No newline at end of file diff --git a/src/utils/logging-map.h b/src/utils/logging-map.h new file mode 100644 index 0000000..14a1e92 --- /dev/null +++ b/src/utils/logging-map.h @@ -0,0 +1,37 @@ +#ifndef __LOGGING_MAP_H__ +#define __LOGGING_MAP_H__ + +#include +#include +#include + +typedef struct Node { + struct Node *next; + uint8_t *kv; /* key 在前 value 在后 */ +} Node; + +struct Map { + size_t key_len, value_len; + size_t bucket_cap; + size_t size; /* 当前元素个数 */ + Node **bucket; /* 指针数组 */ +}; + +typedef struct Map Map; + +/* 创建空 map:key_len/value_len 以字节为单位 */ +Map *map_create(size_t key_len, size_t value_len); + +/* 插入或覆盖: 必须指向 key_len 字节;同理 value */ +void map_put(Map *m, const void *key, const void *value); + +/* 查找:找到返回 value 指针;未找到返回 NULL */ +void *map_get(Map *m, const void *key); + +/* 删除:返回 true 表示确实删掉了 */ +bool map_erase(Map *m, const void *key); + +/* 销毁并释放所有内存 */ +void map_destroy(Map *m); + +#endif /* __LOGGING_MAP_H__ */ \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0baacea..f2f9869 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,6 +2,8 @@ project(test) enable_testing() +include_directories(${CMAKE_SOURCE_DIR}/src) + #测试简单基本应用 add_executable(${PROJECT_NAME}simple test-simple.c) target_link_libraries(${PROJECT_NAME}simple logging) @@ -17,3 +19,9 @@ add_test(test_file ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}file${CMAKE_EXECUT add_executable(${PROJECT_NAME}filter test-filter.c) target_link_libraries(${PROJECT_NAME}filter logging) add_test(test_filter ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}filter${CMAKE_EXECUTEABLE_SUFFIX}) + + +#测试工具map +add_executable(${PROJECT_NAME}map test-map.c) +target_link_libraries(${PROJECT_NAME}map logging) +add_test(test_map ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}map${CMAKE_EXECUTEABLE_SUFFIX}) \ No newline at end of file diff --git a/tests/test-filter.c b/tests/test-filter.c index 2394298..74babda 100644 --- a/tests/test-filter.c +++ b/tests/test-filter.c @@ -6,8 +6,6 @@ #include int main() { - initDefaultLogger("test-filter", LOG_DEBUG); - Log_info("This is an info message"); Log_error("This is an error message%s", "123"); Log_fatal("This is an fatal message"); diff --git a/tests/test-log-file.c b/tests/test-log-file.c index 0f0e98c..0cb136e 100644 --- a/tests/test-log-file.c +++ b/tests/test-log-file.c @@ -2,7 +2,6 @@ #include "logging/logging-handler.h" int main() { - initDefaultLogger("testLogger", LOG_DEBUG); log_Handler *hander = loggingHandlerFile("test_log", 1024 * 1024 * 10); addHandler(getDefaultLogger(), hander); diff --git a/tests/test-map.c b/tests/test-map.c new file mode 100644 index 0000000..2253ce0 --- /dev/null +++ b/tests/test-map.c @@ -0,0 +1,17 @@ +#include "utils/logging-map.h" + +int main(int argc, char *argv[]) { + (void)argc; + (void)argv; + + Map *map = map_create(0, sizeof(int)); + + const char *keys[] = {"key1", "key2", "key3", "key4", "key5"}; + + for (int i = 0; i < 5; i++) { + map_put(map, keys[i], &i); + } + + map_destroy(map); + return 0; +} \ No newline at end of file diff --git a/tests/test-simple.c b/tests/test-simple.c index 994246d..42a5a07 100644 --- a/tests/test-simple.c +++ b/tests/test-simple.c @@ -1,8 +1,6 @@ #include "logging.h" int main() { - initDefaultLogger("simple", LOG_DEBUG); - Log_info("This is an info message"); Log_error("This is an error message%s", "123"); Log_fatal("This is an fatal message");