Improve performance and code size
[flog.git] / flog.h
blob06558545cd918ac836645e506b2bf030294440ee
1 //! Flog - The F logging library
3 //! @file flog.h
4 //! @author Nabeel Sowan (nabeel.sowan@vibes.se)
5 //!
6 //! Useful as the main logger of a program or embedded system.
7 //! Requires C99 + GNU support
10 #ifndef FLOG_H
11 #define FLOG_H
13 //! We need asprintf() for flog.c and flog_string.c
14 #define _GNU_SOURCE
16 #include "config.h"
17 #include "flog_msg_id.h"
18 #include <stdint.h>
20 #ifdef FLOG_TIMESTAMP
21 #ifdef FLOG_TIMESTAMP_USEC
22 #include <sys/time.h>
23 #include <time.h>
24 typedef struct timeval FLOG_TIMESTAMP_T;
25 #else //FLOG_TIMESTAMP_USEC
26 #include <time.h>
27 typedef time_t FLOG_TIMESTAMP_T;
28 #endif //FLOG_TIMESTAMP_USEC
29 #endif //FLOG_TIMESTAMP
32 #ifdef FLOG_CONFIG_MSG_TYPE_ENUM_API
34 typedef enum flog_msg_type {
35 FLOG_NONE = 0x00,
36 FLOG_NOTHING = FLOG_NONE,
38 FLOG_CRIT = 0x01,
39 FLOG_CRITICAL = FLOG_CRIT,
41 FLOG_ERR = 0x02,
42 FLOG_ERROR = FLOG_ERR,
44 FLOG_WARN = 0x04,
45 FLOG_WARNING = FLOG_WARN,
46 FLOG_ALERT = FLOG_WARN,
48 FLOG_NOTE = 0x08,
49 FLOG_NOTIFY = FLOG_NOTE,
50 FLOG_IMP = FLOG_NOTE,
51 FLOG_IMPORTANT = FLOG_NOTE,
53 FLOG_INFO = 0x10,
54 FLOG_INFORMATION = FLOG_INFO,
55 FLOG_MSG = FLOG_INFO,
56 FLOG_MESSAGE = FLOG_INFO,
58 FLOG_VINFO = 0x20,
59 FLOG_VERBOSE = FLOG_VINFO,
61 FLOG_DEBUG = 0x40,
63 FLOG_DEEP_DEBUG = 0x80,
65 FLOG_ACCEPT_ONLY_CRITICAL = FLOG_CRIT,
66 FLOG_ACCEPT_ONLY_ERROR = FLOG_CRIT | FLOG_ERR,
67 FLOG_ACCEPT_ERROR_AND_WARNING = FLOG_CRIT | FLOG_ERR | FLOG_WARN,
68 FLOG_ACCEPT_IMPORTANT_NOTES = FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE,
69 FLOG_ACCEPT_INFO = FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO,
70 FLOG_ACCEPT_VERBOSE_INFO = FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO,
71 FLOG_ACCEPT_DEBUG = FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO | FLOG_DEBUG,
72 FLOG_ACCEPT_DEEP_DEBUG = FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO | FLOG_DEBUG | FLOG_DEEP_DEBUG,
73 FLOG_ACCEPT_ALL = FLOG_ACCEPT_DEBUG
74 } FLOG_MSG_TYPE_T;
76 #else //FLOG_CONFIG_MSG_TYPE_ENUM_API
79 //! @addtogroup FLOG_MSG_TYPE_T
80 //! @brief Types of messages supported by FLOG
81 //! @details Use where ever a @ref FLOG_MSG_TYPE_T is referred
82 //! @{
84 typedef uint_fast8_t FLOG_MSG_TYPE_T;
86 //! Nothing
87 #define FLOG_NONE 0x00
88 #define FLOG_NOTHING FLOG_NONE
90 //! Critical error
91 #define FLOG_CRIT 0x01
92 #define FLOG_CRITICAL FLOG_CRIT
94 //! Error
95 #define FLOG_ERR 0x02
96 #define FLOG_ERROR FLOG_ERR
98 //! Warning
99 #define FLOG_WARN 0x04
100 #define FLOG_WARNING FLOG_WARN
101 #define FLOG_ALERT FLOG_WARN
103 //! Note
104 #define FLOG_NOTE 0x08
105 #define FLOG_NOTIFY FLOG_NOTE
106 #define FLOG_IMP FLOG_NOTE
107 #define FLOG_IMPORTANT FLOG_NOTE
109 //! Info
110 #define FLOG_INFO 0x10
111 #define FLOG_INFORMATION FLOG_INFO
112 #define FLOG_MSG FLOG_INFO
113 #define FLOG_MESSAGE FLOG_INFO
115 //! Info in verbose mode
116 #define FLOG_VINFO 0x20
117 #define FLOG_VERBOSE FLOG_VINFO
119 //! Debug info
120 #define FLOG_DEBUG 0x40
122 //! Deep debug info (such as when functions are started etc. )
123 #define FLOG_DEEP_DEBUG 0x80
125 //! @}
128 //! @addtogroup FLOG_ACCEPT_BITMASKS
129 //! @brief Bitmasks for filtering messages
130 //! @details Set the variable @ref FLOG_T->accepted_message_type
131 //! @{
133 //! Bitmask to accept only critical
134 #define FLOG_ACCEPT_ONLY_CRITICAL FLOG_CRIT
135 //! Bitmask to accept only errors
136 #define FLOG_ACCEPT_ONLY_ERROR FLOG_CRIT | FLOG_ERR
137 //! Bitmask to accept error and warning
138 #define FLOG_ACCEPT_ERROR_AND_WARNING FLOG_CRIT | FLOG_ERR | FLOG_WARN
139 //! Bitmask to accept all important messages
140 #define FLOG_ACCEPT_IMPORTANT_NOTE FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE
141 //! Bitmask to accept informational messages
142 #define FLOG_ACCEPT_INFO FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO
143 //! Bitmask to accept verbose messages
144 #define FLOG_ACCEPT_VERBOSE_INFO FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO
145 //! Bitmask to accept all messages (except deep debug)
146 #define FLOG_ACCEPT_DEBUG FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO | FLOG_DEBUG
147 //! Bitmask to accept all messages
148 #define FLOG_ACCEPT_DEEP_DEBUG FLOG_CRIT | FLOG_ERR | FLOG_WARN | FLOG_NOTE | FLOG_INFO | FLOG_VINFO | FLOG_DEBUG | FLOG_DEEP_DEBUG
149 //! Bitmask to accept all messages (except deep debug)
150 #define FLOG_ACCEPT_ALL FLOG_ACCEPT_DEBUG
152 //! @}
154 #endif //FLOG_CONFIG_MSG_TYPE_ENUM_API
157 // Macros to insert source info into print strings
158 // Maybe it is better to use __func__ than __FUNCTION__ ?
161 //! emit an flog message
163 //! use this when you need to emit simple text messages and flog_printf() when formatting is needed
164 //! @param[in,out] p log to emit message to
165 //! @param[in] type use one of the FLOG_* defines
166 //! @param[in] subsystem which part of the program is outputing this message
167 //! @param[in] text message text
168 //! @retval 0 success
169 //! @see _flog_print(), flog_printf(), flog_dprint()
170 #ifdef FLOG_SRC_INFO
171 #define flog_print(p, subsystem, type, msg_id, text) _flog_print(p,subsystem,__FILE__,__LINE__,__FUNCTION__,type,msg_id,text)
172 #else
173 #define flog_print(p, subsystem, type, msg_id, text) _flog_print(p,subsystem,type,msg_id,text)
174 #endif
177 //! emit a formatted flog message (calls flog_print())
179 //! use this when you need to emit formatted text messages and flog_print() when no formatting is needed
180 //! @param[in,out] p log to emit message to
181 //! @param[in] type use one of the FLOG_* defines
182 //! @param[in] subsystem which part of the program is outputing this message
183 //! @param[in] ... formatted message text
184 //! @retval 0 success
185 //! @see _flog_printf(), flog_print(), flog_dprintf()
186 #ifdef FLOG_SRC_INFO
187 #define flog_printf(p, subsystem, type, msg_id, ...) _flog_printf(p,subsystem,__FILE__,__LINE__,__FUNCTION__,type,msg_id,__VA_ARGS__)
188 #else
189 #define flog_printf(p, subsystem, type, msg_id, ...) _flog_printf(p,subsystem,type,msg_id,__VA_ARGS__)
190 #endif
193 //! Same as flog_print() but only defined if DEBUG is set
195 //! Use this macro to allow removal of messages from release builds
196 //! @see flog_print()
197 #ifdef DEBUG
198 #define flog_dprint(p, subsystem, type, msg_id, text) flog_print(p,subsystem,type,msg_id,text)
199 #else
200 #define flog_dprint(p, subsystem, type, msg_id, text)
201 #endif
204 //! Same as flog_printf() but only defined if DEBUG is set
206 //! Use this macro to allow removal of messages from release builds
207 //! @see flog_printf()
208 #ifdef DEBUG
209 #define flog_dprintf(p, subsystem, type, msg_id, ...) flog_printf(p,subsystem,type,msg_id,__VA_ARGS__)
210 #else
211 #define flog_dprintf(p, subsystem, type, msg_id, ...)
212 #endif
215 //! Macro for flog assert functionality
217 //! @param[in,out] p log to emit message to
218 //! @param[in] cond statement to evaluate
219 #ifdef FLOG_ABORT_ON_ASSERT
220 #define flog_assert(p, cond) \
222 if(!(cond)) { \
223 flog_printf(p,NULL,FLOG_ERROR,FLOG_MSG_ASSERTION_FAILED,#cond); \
224 abort(); \
227 #else
228 #define flog_assert(p, cond) \
230 if(!(cond)) \
231 flog_printf(p,NULL,FLOG_ERROR,FLOG_MSG_ASSERTION_FAILED,#cond); \
233 #endif
236 //! Message structure - Holds all data related to a single message
237 typedef struct {
238 char *subsystem; //!< subsystem which is outputting the msg
239 #ifdef FLOG_TIMESTAMP
240 FLOG_TIMESTAMP_T timestamp; //!< timestamp
241 #endif
242 #ifdef FLOG_SRC_INFO
243 char *src_file; //!< source file emitting message
244 uint_fast16_t src_line; //!< source line number emitting message
245 char *src_func; //!< source function emitting message
246 #endif
247 FLOG_MSG_TYPE_T type; //!< type of message
248 FLOG_MSG_ID_T msg_id; //!< message id (instead of, or with text) see flog_msg_id.h
249 char *text; //!< message text
250 } FLOG_MSG_T;
253 //! Main log structure - typedefined as @ref FLOG_T
255 //! These can be appended to each other in a tree structure (by using flog_append_sublog())
256 //! to form good flow and structure in software.
257 //! Sublogs are created for 3 main purposes: namespacing, multiple outputs and filtering
258 typedef struct flog_t {
259 char *name; //!< name of log
260 FLOG_MSG_TYPE_T accepted_msg_type; //!< bitmask of which messages to accept
261 int (*output_func)(struct flog_t *,const FLOG_MSG_T *); //!< function to output messages to
262 void *output_func_data; //!< data passed to output func
263 uint_fast8_t output_error; //!< errors occurred on output
264 uint_fast8_t output_stop_on_error; //!< stop outputting messages on error
265 struct flog_t *error_log; //!< error log for flog errors
266 FLOG_MSG_T **msg; //!< array of messages
267 uint_fast16_t msg_amount; //!< amount of messages in array
268 uint_fast16_t msg_max; //!< maximum amount of buffered messages
269 struct flog_t **sublog; //!< array of sublogs
270 uint_fast8_t sublog_amount; //!< amount of sublogs in array
271 } FLOG_T;
274 void init_flog_msg_t(FLOG_MSG_T *p);
276 FLOG_MSG_T * create_flog_msg_t(const char *subsystem,
277 #ifdef FLOG_TIMESTAMP
278 FLOG_TIMESTAMP_T timestamp,
279 #endif
280 #ifdef FLOG_SRC_INFO
281 const char *src_file,int src_line,const char *src_func,
282 #endif
283 FLOG_MSG_TYPE_T msg_type,FLOG_MSG_ID_T msg_id,const char *text);
285 void destroy_flog_msg_t(FLOG_MSG_T *p);
287 void init_flog_t(FLOG_T *p);
288 FLOG_T * create_flog_t(const char *name, FLOG_MSG_TYPE_T accepted_msg_type);
289 void destroy_flog_t(FLOG_T *p);
291 int flog_add_msg(FLOG_T *p,FLOG_MSG_T *msg);
292 void flog_clear_msg_buffer(FLOG_T *p);
293 int flog_append_sublog(FLOG_T *p,FLOG_T *sublog);
295 #ifdef FLOG_SRC_INFO
296 int _flog_print(FLOG_T *p,const char *subsystem,const char *src_file,int src_line,const char *src_func,FLOG_MSG_TYPE_T type,FLOG_MSG_ID_T msg_id,const char *text);
297 int _flog_printf(FLOG_T *p,const char *subsystem,const char *src_file,int src_line,const char *src_func,FLOG_MSG_TYPE_T type,FLOG_MSG_ID_T msg_id,const char *textf, ...);
298 #else
299 int _flog_print(FLOG_T *p,const char *subsystem,FLOG_MSG_TYPE_T type,FLOG_MSG_ID_T msg_id,const char *text);
300 int _flog_printf(FLOG_T *p,const char *subsystem,FLOG_MSG_TYPE_T type,FLOG_MSG_ID_T msg_id,const char *textf, ...);
301 #endif
303 #ifdef DEBUG
304 void flog_test(FLOG_T *p);
305 #endif
307 #endif