diff --git a/CMakeLists.txt b/CMakeLists.txt index e985d4c..92faaab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,7 @@ include_directories(${INCLUDE_DIR}) add_definitions(-std=c99) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_GNU_SOURCE -DNOPOLL_LOGGER ") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wall -Wno-missing-field-initializers") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wall -Wextra") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall") add_subdirectory(src) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3c64329..2083b56 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,11 +16,15 @@ set(PROJ_CIMPL cimplog) file(GLOB HEADERS cimplog.h cimplog.h) if (RDK_LOGGER) -set(SOURCES cimplog-rdk-logger.c) +set(SOURCES cimplog.c cimplog-rdk-logger.c) else (RDK_LOGGER) set(SOURCES cimplog.c) endif (RDK_LOGGER) +if (RDK_LOGGER) + add_definitions(-DRDK_LOGGER) +endif (RDK_LOGGER) + add_library(${PROJ_CIMPL} STATIC ${HEADERS} ${SOURCES}) add_library(${PROJ_CIMPL}.shared SHARED ${HEADERS} ${SOURCES}) set_target_properties(${PROJ_CIMPL}.shared PROPERTIES diff --git a/src/cimplog-rdk-logger.c b/src/cimplog-rdk-logger.c index b936c55..f4b3e66 100644 --- a/src/cimplog-rdk-logger.c +++ b/src/cimplog-rdk-logger.c @@ -9,7 +9,7 @@ const char *__attribute__((weak)) rdk_logger_module_fetch(void); -void __cimplog(const char *module, int level, const char *msg, ...) +void cimplog_rdk(int level, const char* module, const char* format, va_list args) { static const char *rdk_logger_module = NULL; static int init_done = 0; @@ -36,15 +36,12 @@ void __cimplog(const char *module, int level, const char *msg, ...) //else print to RDK Logger static const rdk_LogLevel _level[] = { RDK_LOG_ERROR, RDK_LOG_INFO, RDK_LOG_DEBUG }; - va_list arg_ptr; char buf[MAX_BUF_SIZE]; int nbytes; if (level <= LEVEL_INFO) { - va_start(arg_ptr, msg); - nbytes = vsnprintf(buf, MAX_BUF_SIZE, msg, arg_ptr); - va_end(arg_ptr); + nbytes = vsnprintf(buf, MAX_BUF_SIZE, format, args); if( nbytes >= MAX_BUF_SIZE ) { diff --git a/src/cimplog.c b/src/cimplog.c index efb0e4e..6b8a260 100644 --- a/src/cimplog.c +++ b/src/cimplog.c @@ -7,29 +7,46 @@ #define MAX_BUF_SIZE 1024 -void __cimplog(const char *module, int level, const char *msg, ...) +static cimplog_handler_t _log_handler = NULL; + +void cimplog_stdout(int level, const char* moduel, const char* format, va_list args); +void cimplog_rdk(int level, const char* module, const char* format, va_list args); + +void __cimplog(const char *module, int level, const char* format, ...) +{ + va_list args; + va_start(args, format); + + if (_log_handler) + { + _log_handler(level, module, format, args); + } + else + { + #ifdef RDK_LOGGER + cimplog_rdk(level, module, format, args); + #else + cimplog_stdout(level, module, format, args); + #endif + } + + va_end(args); +} + +void +cimplog_stdout(int level, const char* module, const char* format, va_list args) { static const char *_level[] = { "Error", "Info", "Debug", "Unknown" }; - va_list arg_ptr; - char buf[MAX_BUF_SIZE]; - int nbytes; - struct timespec ts; - va_start(arg_ptr, msg); - nbytes = vsnprintf(buf, MAX_BUF_SIZE, msg, arg_ptr); - va_end(arg_ptr); - - if( nbytes >= MAX_BUF_SIZE ) - { - buf[ MAX_BUF_SIZE - 1 ] = '\0'; - } - else - { - buf[nbytes] = '\0'; - } - + struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); - printf("[%09ld][%s][%s]: %s", ts.tv_sec, module, _level[0x3 & level], buf); + printf("[%09ld][%s][%s]: ", ts.tv_sec, module, _level[0x3 & level]); + vprintf(format, args); } +void +cimplog_sethandler(cimplog_handler_t handler) +{ + _log_handler = handler; +} diff --git a/src/cimplog.h b/src/cimplog.h index 6f9bc1a..af99f26 100644 --- a/src/cimplog.h +++ b/src/cimplog.h @@ -27,6 +27,22 @@ #define cimplog_info(module, ...) __cimplog(module, LEVEL_INFO, __VA_ARGS__) #define cimplog_debug(module, ...) __cimplog(module, LEVEL_DEBUG, __VA_ARGS__) +/** + * @brief application provided log handler instead of default stdout + * + * @param module Library or Module indication + * @param level ERROR, INFO, or DEBUG + * @param msg The formatted log message + */ +typedef void (*cimplog_handler_t)(int level, const char* module, const char* format, va_list args); + +/** + * @briege Sets an application log handler instead of using default stdout + * + * @param handler The application logging callback + */ +void cimplog_sethandler(cimplog_handler_t handler); + /** * @brief handle log message based on log level * @@ -34,6 +50,8 @@ * @param level of log is info,debug,error * @param msg message */ -void __cimplog(const char *module, int level, const char *msg, ...); +void __cimplog(const char *module, int level, const char *msg, ...) + __attribute__ ((format (printf, 3, 4))); + #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 02910bd..db5c325 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -27,7 +27,7 @@ target_link_libraries (simple rt) add_test(NAME SimpleRDKLogger COMMAND simpleRDKLogger) include_directories ( ../tests ) -add_executable(simpleRDKLogger simple-rdk-logger.c ../src/cimplog-rdk-logger.c) +add_executable(simpleRDKLogger simple-rdk-logger.c ../src/cimplog.c ../src/cimplog-rdk-logger.c) set_property(TARGET simpleRDKLogger PROPERTY C_STANDARD 99) target_link_libraries (simpleRDKLogger gcov) @@ -36,7 +36,7 @@ target_link_libraries (simpleRDKLogger rt) add_test(NAME SimpleRDKLoggerErr COMMAND simpleRDKLoggerErr) include_directories ( ../tests ) -add_executable(simpleRDKLoggerErr simple-rdk-logger-error.c ../src/cimplog-rdk-logger.c) +add_executable(simpleRDKLoggerErr simple-rdk-logger-error.c ../src/cimplog.c ../src/cimplog-rdk-logger.c) set_property(TARGET simpleRDKLoggerErr PROPERTY C_STANDARD 99) target_link_libraries (simpleRDKLoggerErr gcov) diff --git a/tests/simple.c b/tests/simple.c index 9f56147..c615c2a 100644 --- a/tests/simple.c +++ b/tests/simple.c @@ -22,6 +22,26 @@ #include "../src/cimplog.h" +static int callback_count = 0; + +static void +my_log_callback(int level, const char* module, const char* format, va_list args) +{ + int n; + char buff[64]; + + (void) level; + (void) module; + + CU_ASSERT(level == LEVEL_INFO); + CU_ASSERT(strcmp(module, "module") == 0); + CU_ASSERT(strcmp(format, "%d") == 0); + + vsnprintf(buff, sizeof(buff), format, args); + n = (int) strtol(buff, NULL, 10); + callback_count += n; +} + void test_simple() { char mod2[] = "Module2", mod3[] = "Module3"; @@ -31,10 +51,22 @@ void test_simple() cimplog_debug(mod3, "Sample debug\n"); } +void test_log_callback() +{ + cimplog_sethandler(my_log_callback); + cimplog_info("module", "%d", 1); + cimplog_info("module", "%d", 2); + cimplog_info("module", "%d", 3); + cimplog_info("module", "%d", 4); + cimplog_info("module", "%d", 5); + CU_ASSERT(callback_count == 15); +} + void add_suites( CU_pSuite *suite ) { *suite = CU_add_suite( "cimplog tests", NULL, NULL ); CU_add_test( *suite, "Test simple logging", test_simple ); + CU_add_test( *suite, "Test log callback", test_log_callback); } /*----------------------------------------------------------------------------*/