logger.h (3348B)
1 /* Copyright (C) 2013-2023, 2025 Vincent Forest (vaplv@free.fr) 2 * 3 * The RSys library is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published 5 * by the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * The RSys library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #ifndef LOGGER_H 17 #define LOGGER_H 18 19 #include "dynamic_array_char.h" 20 #include "list.h" 21 #include "mem_allocator.h" 22 #include "mutex.h" 23 24 #include <stdarg.h> 25 26 #define LOGGER_DEFAULT ((struct logger*)(int64_t)0xC0DE) 27 28 enum log_type { 29 LOG_OUTPUT, 30 LOG_ERROR, 31 LOG_WARNING, 32 LOG_TYPES_COUNT__ 33 }; 34 35 struct logger { 36 /* Internal data */ 37 struct { 38 void (*writer)(const char* msg, void* ctx); 39 void* ctx; 40 } streams[LOG_TYPES_COUNT__]; 41 struct mutex* mutex; 42 struct mem_allocator* allocator; 43 struct darray_char buffer; 44 }; 45 46 static INLINE void 47 logger_release(struct logger* logger) 48 { 49 ASSERT(logger); 50 darray_char_release(&logger->buffer); 51 if(logger->mutex) mutex_destroy(logger->mutex); 52 } 53 54 static INLINE res_T 55 logger_init 56 (struct mem_allocator* allocator, /* May be NULL <=> default allocator */ 57 struct logger* logger) 58 { 59 int i; 60 res_T res = RES_OK; 61 ASSERT(logger); 62 63 memset(logger, 0, sizeof(struct logger)); 64 logger->allocator = allocator ? allocator : &mem_default_allocator; 65 FOR_EACH(i, 0, LOG_TYPES_COUNT__) logger->streams[i].writer = NULL; 66 67 darray_char_init(logger->allocator, &logger->buffer); 68 res = darray_char_resize(&logger->buffer, 256); 69 if(res != RES_OK) goto error; 70 71 logger->mutex = mutex_create(); 72 if(!logger->mutex) { 73 res = RES_MEM_ERR; 74 goto error; 75 } 76 77 exit: 78 return res; 79 error: 80 logger_release(logger); 81 goto exit; 82 } 83 84 static INLINE void 85 logger_clear(struct logger* logger) 86 { 87 int i; 88 ASSERT(logger); 89 FOR_EACH(i, 0, LOG_TYPES_COUNT__) logger->streams[i].writer = NULL; 90 } 91 92 static INLINE void 93 logger_set_stream 94 (struct logger* logger, 95 const enum log_type type, 96 void (*writer)(const char* msg, void* ctx), /* May be NULL */ 97 void* ctx) /* May be NULL */ 98 { 99 ASSERT(logger && (unsigned)type < LOG_TYPES_COUNT__); 100 mutex_lock(logger->mutex); 101 logger->streams[type].writer = writer; 102 logger->streams[type].ctx = ctx; 103 mutex_unlock(logger->mutex); 104 } 105 106 static FINLINE char 107 logger_has_stream 108 (struct logger* logger, 109 const enum log_type type) 110 { 111 char b; 112 ASSERT(logger && (unsigned)type < LOG_TYPES_COUNT__); 113 mutex_lock(logger->mutex); 114 b = logger->streams[type].writer != NULL; 115 mutex_unlock(logger->mutex); 116 return b; 117 } 118 119 BEGIN_DECLS 120 121 RSYS_API res_T 122 logger_print 123 (struct logger* logger, 124 const enum log_type type, 125 const char* log, 126 ... ) 127 #ifdef COMPILER_GCC 128 __attribute((format(printf, 3, 4))) 129 #endif 130 ; 131 132 /* The value of vargs is undefined after the call of logger_vprint */ 133 RSYS_API res_T 134 logger_vprint 135 (struct logger* logger, 136 const enum log_type type, 137 const char* log, 138 va_list vargs); 139 140 END_DECLS 141 142 #endif /* LOGGER_H */